From d033d08c5d73799966295bf920308a9389a90409 Mon Sep 17 00:00:00 2001 From: Sabine Date: Sat, 19 Oct 2024 14:53:52 +0200 Subject: [PATCH 001/251] feat(common): start with kmc-convert-read/write very basic keylayout-file --- developer/src/kmc-convert/data/MyResult.kmn | 47 ++ developer/src/kmc-convert/data/MyResult1.kmn | 39 ++ .../src/kmc-convert/data/MySample.keylayout | 99 ++++ .../src/kmc-convert/data/MySampleKMN.kmn | 33 ++ .../kmc-convert/data/My_dk_Keyboard.keylayout | 502 ++++++++++++++++++ .../src/converter-class-factory.ts | 3 + developer/src/kmc-convert/src/converter.ts | 12 +- .../keylayout-to-kmn-converter.ts | 144 ++++- .../test/test-keylayout-to-kmn-converter.ts | 30 ++ 9 files changed, 906 insertions(+), 3 deletions(-) create mode 100644 developer/src/kmc-convert/data/MyResult.kmn create mode 100644 developer/src/kmc-convert/data/MyResult1.kmn create mode 100644 developer/src/kmc-convert/data/MySample.keylayout create mode 100644 developer/src/kmc-convert/data/MySampleKMN.kmn create mode 100644 developer/src/kmc-convert/data/My_dk_Keyboard.keylayout diff --git a/developer/src/kmc-convert/data/MyResult.kmn b/developer/src/kmc-convert/data/MyResult.kmn new file mode 100644 index 00000000000..e426f096f72 --- /dev/null +++ b/developer/src/kmc-convert/data/MyResult.kmn @@ -0,0 +1,47 @@ + +c +c Keyman keyboard generated by kmn-convert +c + +store(&VERSION) '...' +store(&TARGETS) 'any' +store(&KEYBOARDVERSION) '...' +store(©RIGHT) '© 2024 SIL International +begin Unicode > use(main) + +group(main) using keys + ++ [K_A] > 'a' ++ [K_B] > 'b' ++ [K_C] > 'c' ++ [K_Q] > 'q' ++ [K_Y] > 'y' ++ [K_3] > '3' ++ [K_HYPHEN] > 'ß' ++ [K_PERIOD] > '.' + ++ [K_A] > 'A' ++ [K_B] > 'B' ++ [K_C] > 'C' ++ [K_Q] > 'Q' ++ [K_Y] > 'Y' ++ [K_3] > '§' ++ [K_HYPHEN] > '?' ++ [K_PERIOD] > ':' + ++ [K_A] > ':' ++ [K_B] > '9' ++ [K_Q] > '@' ++ [K_Y] > ':' ++ [K_3] > '³' ++ [K_HYPHEN] > '\' ++ [K_PERIOD] > '·' + ++ [K_A] > 'A' ++ [K_B] > 'B' ++ [K_C] > 'C' ++ [K_Q] > 'Q' ++ [K_Y] > 'Y' ++ [K_3] > '3' ++ [K_HYPHEN] > 'ß' + diff --git a/developer/src/kmc-convert/data/MyResult1.kmn b/developer/src/kmc-convert/data/MyResult1.kmn new file mode 100644 index 00000000000..cec5673a200 --- /dev/null +++ b/developer/src/kmc-convert/data/MyResult1.kmn @@ -0,0 +1,39 @@ +begin Unicode > use(main) + +group(main) using keys + ++ [K_A] > 'a' ++ [K_B] > 'b' ++ [K_C] > 'c' ++ [K_Q] > 'q' ++ [K_Y] > 'y' ++ [K_3] > '3' ++ [K_HYPHEN] > 'ß' ++ [K_PERIOD] > '.' + ++ [K_A] > 'A' ++ [K_B] > 'B' ++ [K_C] > 'C' ++ [K_Q] > 'Q' ++ [K_Y] > 'Y' ++ [K_3] > '§' ++ [K_HYPHEN] > '?' ++ [K_PERIOD] > ':' + ++ [K_A] > ':' ++ [K_B] > '9' ++ [K_Q] > '@' ++ [K_Y] > ':' ++ [K_3] > '³' ++ [K_HYPHEN] > '\' ++ [K_PERIOD] > '·' + ++ [K_A] > 'A' ++ [K_B] > 'B' ++ [K_C] > 'C' ++ [K_Q] > 'Q' ++ [K_Y] > 'Y' ++ [K_3] > '3' ++ [K_HYPHEN] > 'ß' + + diff --git a/developer/src/kmc-convert/data/MySample.keylayout b/developer/src/kmc-convert/data/MySample.keylayout new file mode 100644 index 00000000000..b3d3675e000 --- /dev/null +++ b/developer/src/kmc-convert/data/MySample.keylayout @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/data/MySampleKMN.kmn b/developer/src/kmc-convert/data/MySampleKMN.kmn new file mode 100644 index 00000000000..dae7175f741 --- /dev/null +++ b/developer/src/kmc-convert/data/MySampleKMN.kmn @@ -0,0 +1,33 @@ +begin Unicode > use(main) + +group(main) using keys + +c ## BASE layer ##################### ++ [K_A] > 'a' ++ [K_B] > 'b' ++ [K_C] > 'c' ++ [K_Q] > 'q' ++ [K_Z] > 'y' ++ [K_HYPHEN] > 'ß' ++ [K_3] > '3' ++ [K_PERIOD] > '.' + +c ## SHIFT layer #################### ++ [SHIFT K_A] > 'A' ++ [SHIFT K_B] > 'B' ++ [SHIFT K_C] > 'C' ++ [SHIFT K_Q] > 'Q' ++ [SHIFT K_Z] > 'Y' ++ [SHIFT K_HYPHEN] > '?' ++ [SHIFT K_3] > '§' ++ [SHIFT K_PERIOD] > ':' + +c ## ALT layer ###################### ++ [ALT K_A] > '☺' ++ [ALT K_B] > '‹' ++ [ALT K_C] > ' ' ++ [ALT K_Q] > '@' ++ [ALT K_Z] > '›' ++ [ALT K_HYPHEN] > '\' ++ [ALT K_3] > '³' ++ [ALT K_PERIOD] > '·' diff --git a/developer/src/kmc-convert/data/My_dk_Keyboard.keylayout b/developer/src/kmc-convert/data/My_dk_Keyboard.keylayout new file mode 100644 index 00000000000..39c4ce0966a --- /dev/null +++ b/developer/src/kmc-convert/data/My_dk_Keyboard.keylayout @@ -0,0 +1,502 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/src/converter-class-factory.ts b/developer/src/kmc-convert/src/converter-class-factory.ts index 2176b3df008..a947626df70 100644 --- a/developer/src/kmc-convert/src/converter-class-factory.ts +++ b/developer/src/kmc-convert/src/converter-class-factory.ts @@ -3,6 +3,9 @@ * * Lists all the available converters and finds matching converter */ +// _S2 const converters later holds several converters - each specified in diff module folder e.g. /keylayout-to-kmn,... +// _S2 this class will be used in each converter module +// _S2 class method returns/finds the right converter import { KeylayoutToKmnConverter } from './keylayout-to-kmn/keylayout-to-kmn-converter.js'; const converters = [ diff --git a/developer/src/kmc-convert/src/converter.ts b/developer/src/kmc-convert/src/converter.ts index 0a35bb3bc87..4492bf254cf 100644 --- a/developer/src/kmc-convert/src/converter.ts +++ b/developer/src/kmc-convert/src/converter.ts @@ -28,6 +28,8 @@ export interface ConverterResult extends KeymanCompilerResult { * compiler does not read or write from filesystem or network directly, but * relies on callbacks for all external IO. */ +// _S2 method init: uses Interface CompilerCallbacks( loadfile,...) +// _S2 method run: uses Interface CompilerCallbacks( loadfile,...) export class Converter implements KeymanCompiler { private callbacks: CompilerCallbacks; private options: CompilerOptions; @@ -39,6 +41,7 @@ export class Converter implements KeymanCompiler { * @param options - Compiler options * @returns false if initialization fails */ + // _S2 fills interface this.callbacks with array (holding our data), filesize ect async init(callbacks: CompilerCallbacks, options: CompilerOptions): Promise { this.options = { ...options }; this.callbacks = callbacks; @@ -56,8 +59,15 @@ export class Converter implements KeymanCompiler { * {@link Converter.write}. * @returns Source artifacts on success, null on failure. */ + // _S2 this is Base class of all converters + // _S2 check for things( file available,...) then + // _S2 finds converter e.g.keylayout->kmn ( uses converter-class-factory) + // _S2 factory uses/instanciates chiled class ( ~ in C++ virtual function in base class <-> use fun of derived class) + // _S2 loads file + // _S2 creates a new converter (-object) + // _S2 runs conversion for this object ( run-method of this converter of keylayout-to-kmn-tonverter.ts ) async run(inputFilename: string, outputFilename?: string): Promise { - +console.log('use run of converter.ts') const converterOptions: CompilerOptions = { ...defaultCompilerOptions, ...this.options, diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 7b0c1d29e08..d80d3a550a7 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -6,6 +6,12 @@ import { CompilerCallbacks, CompilerOptions } from "@keymanapp/developer-utils"; import { ConverterToKmnArtifacts } from "../converter-artifacts.js"; +// _S2 imports Sabine +import { XMLParser } from 'fast-xml-parser'; // for reading file +import { readFileSync } from 'fs'; +import { writeFileSync } from "fs"; // for writing file + + export class KeylayoutToKmnConverter { static readonly INPUT_FILE_EXTENSION = '.keylayout'; static readonly OUTPUT_FILE_EXTENSION = '.kmn'; @@ -16,12 +22,146 @@ export class KeylayoutToKmnConverter { } async run(inputFilename: string, outputFilename: string, binaryData: Uint8Array): Promise { + if(!inputFilename || !outputFilename || !binaryData) { throw new Error('Invalid parameters'); } - console.error('TODO: implement KeylayoutToKmnConverter'); + //console.error('TODO: implement KeylayoutToKmnConverter'); + + // _S2 first READ file ........................................ + const inArray = this.read(inputFilename) + //console.log(' inArray:',inArray) + + if (!inArray) { + return null; + } + + // _S2 then CONVERT ........................................ + const outArray = await this.convert(inArray); + + console.log(' outArray:',outArray) + if (!outArray) { + return null; + } + + // _S2 then WRITE to kmn ..................................... + const out = this.write(outArray) + if (!out) { + return null; + } + throw new Error('Not finished yet'); + } + +// ................................................................................ + + + + public read(filename: string):Uint8Array[] { + + const options = { + ignoreAttributes: false, + attributeNamePrefix: '@_', // you have to assign this to use this to access the attribute + }; + + //xml file from https://learn.microsoft.com/en-us/previous-versions/windows/desktop/ms762271(v=vs.85) + const xmlFile = readFileSync(`${process.cwd()}/data/MySample.keylayout`, 'utf8'); + const parser = new XMLParser(options); + const json = parser.parse(xmlFile); + + const nrOfStates = json.keyboard.keyMapSet[0].keyMap.length + const nrOfKeys = json.keyboard.keyMapSet[0].keyMap[0].key.length + const Keys_all_Layers : any[] = [] + + // _S2 TODO what about unicode char/ char < 255 ??? + // _S2 TODO and what about deadkeys??? + // _S2 TODO use unicode ? + [K_A] > 'a' or + [K_A] > U+0061 + // _S2 which stores? + // _S2 why Uint8Array ? + // _S2 how to use names of shiftstates + + for (let j = 0; j < nrOfStates; j++) { + const keys_in_Layer = new Uint8Array(nrOfKeys) + for (let i = 0; i < nrOfKeys; i++) { + if(json.keyboard.keyMapSet[0].keyMap[j].key[i]['@_output'] !== "\0" ) { + keys_in_Layer[i] = json.keyboard.keyMapSet[0].keyMap[j].key[i]['@_output'].charCodeAt(0) + } + } + Keys_all_Layers[j] = keys_in_Layer + } + return(Keys_all_Layers.length === nrOfStates) ? Keys_all_Layers : null; + } + + public convert(inArray: Uint8Array[]):Uint8Array[] { + + const processedKeys = 50 + const nrOfStates = inArray.length + + const outArray :any[] = [] + + for (let j = 0; j < nrOfStates; j++) { + const keys_in_Layer = new Uint8Array(processedKeys) - return null; + keys_in_Layer[0] = inArray[j][0] + keys_in_Layer[24] = inArray[j][1] + keys_in_Layer[2] = inArray[j][2] + keys_in_Layer[1] = inArray[j][3] + keys_in_Layer[16] = inArray[j][4] + keys_in_Layer[29] = inArray[j][5] + keys_in_Layer[38] = inArray[j][6] + keys_in_Layer[46] = inArray[j][7] + keys_in_Layer[50] = inArray[j][8] + + outArray.push(keys_in_Layer) + } + + return (outArray.length === nrOfStates) ? outArray : null } + + + public write(writeArray: Uint8Array[]):boolean { + + const shiftstates = writeArray.length + const keys = writeArray[0].length + + const KeyArray = [ + 'K_A','K_B','K_C','K_D','K_E','K_F','K_G','K_H','K_I','K_J','K_K','K_L','K_M','K_N','K_O','K_P','K_Q','K_R','K_S','K_T','K_U','K_V','K_W','K_X','K_Y','K_Z', + 'K_0','K_1','K_2','K_3','K_4','K_5','K_6','K_7','K_8','K_9', + 'K_SPACE', + 'K_ACCENT','K_HYPHEN','K_EQUAL', + 'K_LBRKT','KRBRKT','K_BKSLASH', + 'K_COLON','KQUOTE', + 'K_COMMA','K_PERIOD','K_SLASH', + 'K_xDF', 'K_OEM_102' + ] + + let data = "\n" + data += "c\n" + data += "c Keyman keyboard generated by kmn-convert\n" + data += "c\n" + data += "\n" + data += "store(&VERSION) \'...\'\n" + data += "store(&TARGETS) \'any\'\n" + data += "store(&KEYBOARDVERSION) \'...\'\n" + data += "store(©RIGHT) '© 2024 SIL International\n" + // what else ?? + + data += "begin Unicode > use(main)\n\n" + data += "group(main) using keys\n" + data += "\n" + + for (let i = 0; i < shiftstates; i++) { + for (let j = 0; j < keys; j++) { + if (String.fromCharCode(writeArray[i][j]) !== '\0' ) { + data += `+ [` + KeyArray[j] + `] > \'` + String.fromCharCode(writeArray[i][j]) +'\'\n' + } + } + data += '\n' + } + + writeFileSync("data/MyResult.kmn", data, { flag: "w"}) + + return true; + } + } \ No newline at end of file diff --git a/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts index 449dba9afca..f6d8546507c 100644 --- a/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts @@ -6,12 +6,15 @@ import {assert} from 'chai'; import {compilerTestCallbacks, compilerTestOptions} from './helpers/index.js'; import {KeylayoutToKmnConverter} from '../src/keylayout-to-kmn/keylayout-to-kmn-converter.js'; +import { makePathToFixture } from './helpers/index.js'; // _S2 my imports + describe('KeylayoutToKmnConverter', function() { before(function() { compilerTestCallbacks.clear(); }); + // _S2 first test it('should throw on null inputs', async function () { // const inputFilename = makePathToFixture('file.keylayout'); const converter = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); @@ -25,4 +28,31 @@ describe('KeylayoutToKmnConverter', function() { assert.isTrue(threw); }); + + // _S2 My tests... + it('should throw on all elements loaded', async function () { + + console.log(' ..................................................................................') + const inputFilename = makePathToFixture('../data/Mysample.keylayout'); + //const inputFilename = makePathToFixture('../data/My_dk_Keyboard.keylayout'); + + const outputFilename = makePathToFixture('../data/MyResult.kmn'); + const data = new Uint8Array([1, 2, 3, 4]); // _S2 just to have sth in an array + + console.log(' inputFilename', inputFilename) + console.log(' outputFilename', outputFilename) + console.log(' data', data) + + // _S2 create obj of derived class-> use derived functions + const converter = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + + let threw = false; + try { + await converter.run(inputFilename, outputFilename, data); + } catch { + threw = true; + } + assert.isTrue(threw); + }); + }); From 9ecc1c0ec71cc084cac3db180770b11cc3fdcb24 Mon Sep 17 00:00:00 2001 From: Sabine Date: Sun, 20 Oct 2024 22:02:07 +0200 Subject: [PATCH 002/251] feat(common): use Uint8Array in kmc-convert --- .../src/kmc-convert/data/MySample.keylayout | 6 +- .../keylayout-to-kmn-converter.ts | 149 +++++++++--------- .../test/test-keylayout-to-kmn-converter.ts | 5 +- 3 files changed, 81 insertions(+), 79 deletions(-) diff --git a/developer/src/kmc-convert/data/MySample.keylayout b/developer/src/kmc-convert/data/MySample.keylayout index b3d3675e000..23191ad7ebe 100644 --- a/developer/src/kmc-convert/data/MySample.keylayout +++ b/developer/src/kmc-convert/data/MySample.keylayout @@ -43,7 +43,6 @@ - @@ -55,7 +54,6 @@ - @@ -64,10 +62,9 @@ - + - @@ -79,7 +76,6 @@ - diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index d80d3a550a7..245e654ccd1 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -7,9 +7,9 @@ import { CompilerCallbacks, CompilerOptions } from "@keymanapp/developer-utils"; import { ConverterToKmnArtifacts } from "../converter-artifacts.js"; // _S2 imports Sabine -import { XMLParser } from 'fast-xml-parser'; // for reading file +import { XMLParser } from 'fast-xml-parser'; // for reading a file import { readFileSync } from 'fs'; -import { writeFileSync } from "fs"; // for writing file +import { writeFileSync } from "fs"; // for writing a file export class KeylayoutToKmnConverter { @@ -27,102 +27,109 @@ export class KeylayoutToKmnConverter { throw new Error('Invalid parameters'); } - //console.error('TODO: implement KeylayoutToKmnConverter'); - - // _S2 first READ file ........................................ + console.log(' _S2 first READ file ........................................'); const inArray = this.read(inputFilename) - //console.log(' inArray:',inArray) + // console.log(' inArray:',inArray) if (!inArray) { return null; } - // _S2 then CONVERT ........................................ + console.log(' _S2 then CONVERT ........................................'); const outArray = await this.convert(inArray); - console.log(' outArray:',outArray) + //console.log(' outArray:',outArray) if (!outArray) { return null; } - // _S2 then WRITE to kmn ..................................... + console.log(' _S2 then WRITE to kmn .....................................'); const out = this.write(outArray) if (!out) { return null; } + throw new Error('Not finished yet'); } - -// ................................................................................ - - +// ............................................................................................................ +// ............................................................................................................ +// ............................................................................................................ public read(filename: string):Uint8Array[] { - - const options = { - ignoreAttributes: false, - attributeNamePrefix: '@_', // you have to assign this to use this to access the attribute - }; - - //xml file from https://learn.microsoft.com/en-us/previous-versions/windows/desktop/ms762271(v=vs.85) - const xmlFile = readFileSync(`${process.cwd()}/data/MySample.keylayout`, 'utf8'); - const parser = new XMLParser(options); - const json = parser.parse(xmlFile); - - const nrOfStates = json.keyboard.keyMapSet[0].keyMap.length - const nrOfKeys = json.keyboard.keyMapSet[0].keyMap[0].key.length - const Keys_all_Layers : any[] = [] - - // _S2 TODO what about unicode char/ char < 255 ??? - // _S2 TODO and what about deadkeys??? - // _S2 TODO use unicode ? + [K_A] > 'a' or + [K_A] > U+0061 - // _S2 which stores? - // _S2 why Uint8Array ? - // _S2 how to use names of shiftstates - - for (let j = 0; j < nrOfStates; j++) { - const keys_in_Layer = new Uint8Array(nrOfKeys) +/* +- // _S2 TODO and what about deadkeys??? +- // _S2 TODO use output ? + [K_A] > 'a' or + [K_A] > U+0061 +- // _S2 which stores? +- // _S2 how to use names of shiftstates*/ + + const options = { + ignoreAttributes: false, + attributeNamePrefix: '@_', // you have to assign this to use this to access the attribute + }; + + + //xml file from https://learn.microsoft.com/en-us/previous-versions/windows/desktop/ms762271(v=vs.85) + const xmlFile = readFileSync(`${process.cwd()}/data/MySample.keylayout`, 'utf8'); + const parser = new XMLParser(options); + const jsonObj = parser.parse(xmlFile); // get plain Object + + const nrOfStates = jsonObj.keyboard.keyMapSet[0].keyMap.length + const nrOfKeys = jsonObj.keyboard.keyMapSet[0].keyMap[0].key.length + // create Object:any for storing Uint8tarray will be array[Uint8Array] Uint8Array might have several numbers (unicode) + const Keys_all_Layers :any[] = [] + + for (let j = 0; j < nrOfStates; j++) { + // create a new keys_in_Layer (type Uint8tarray) + const keys_in_Layer :Uint8Array[] = [] for (let i = 0; i < nrOfKeys; i++) { - if(json.keyboard.keyMapSet[0].keyMap[j].key[i]['@_output'] !== "\0" ) { - keys_in_Layer[i] = json.keyboard.keyMapSet[0].keyMap[j].key[i]['@_output'].charCodeAt(0) + if(jsonObj.keyboard.keyMapSet[0].keyMap[j].key[i]['@_output'] !== "\0" ) { + // textencoder converts string -> bytes ( 'A' -> [ 65 ], '☺' -> [ 226, 152, 186 ]) + // textencoder is of Uint8Array(1) for A and Uint8Array(3) for ☺ + const textencoder = new TextEncoder().encode(jsonObj.keyboard.keyMapSet[0].keyMap[j].key[i]['@_output' ]); + keys_in_Layer[i] = textencoder } } - Keys_all_Layers[j] = keys_in_Layer - } - return(Keys_all_Layers.length === nrOfStates) ? Keys_all_Layers : null; + // add [nrOfStates] Objects:Uint8tarray to Keys_all_Layers + Keys_all_Layers[j] = keys_in_Layer } - public convert(inArray: Uint8Array[]):Uint8Array[] { + console.log(" _S2 read finished\n") + return(Keys_all_Layers.length === nrOfStates && Keys_all_Layers[0].length === nrOfKeys) ? Keys_all_Layers : null; +} - const processedKeys = 50 - const nrOfStates = inArray.length +// ............................................................................................................ - const outArray :any[] = [] +public convert(inArray: any[]):any[] { - for (let j = 0; j < nrOfStates; j++) { - const keys_in_Layer = new Uint8Array(processedKeys) + const outArray :any[] = []; + const nrOfMaxKeys = 50 - keys_in_Layer[0] = inArray[j][0] - keys_in_Layer[24] = inArray[j][1] - keys_in_Layer[2] = inArray[j][2] - keys_in_Layer[1] = inArray[j][3] - keys_in_Layer[16] = inArray[j][4] - keys_in_Layer[29] = inArray[j][5] - keys_in_Layer[38] = inArray[j][6] - keys_in_Layer[46] = inArray[j][7] - keys_in_Layer[50] = inArray[j][8] + for (let j = 0; j < inArray.length ; j++) { + const outkeys_in_Layer :Uint8Array[] = [] - outArray.push(keys_in_Layer) + // initialize keys + for (let i = 0; i < nrOfMaxKeys; i++) { + outkeys_in_Layer[i] = new TextEncoder().encode("\0"); } - return (outArray.length === nrOfStates) ? outArray : null + // now convert + outkeys_in_Layer[0] = inArray[j][0]; + outkeys_in_Layer[24] = inArray[j][1]; + outkeys_in_Layer[2] = inArray[j][2]; + outkeys_in_Layer[1] = inArray[j][3]; + outkeys_in_Layer[16] = inArray[j][4]; + outkeys_in_Layer[29] = inArray[j][5]; + outkeys_in_Layer[38] = inArray[j][6]; + outkeys_in_Layer[46] = inArray[j][7]; + outkeys_in_Layer[49] = inArray[j][0]; + + outArray[j] = outkeys_in_Layer } + console.log(" _S2 convert finished\n") + return (outArray.length === inArray.length ) ? outArray : null +} - - public write(writeArray: Uint8Array[]):boolean { - - const shiftstates = writeArray.length - const keys = writeArray[0].length +public write(writeArray: any[]):boolean { const KeyArray = [ 'K_A','K_B','K_C','K_D','K_E','K_F','K_G','K_H','K_I','K_J','K_K','K_L','K_M','K_N','K_O','K_P','K_Q','K_R','K_S','K_T','K_U','K_V','K_W','K_X','K_Y','K_Z', @@ -150,18 +157,16 @@ export class KeylayoutToKmnConverter { data += "group(main) using keys\n" data += "\n" - for (let i = 0; i < shiftstates; i++) { - for (let j = 0; j < keys; j++) { - if (String.fromCharCode(writeArray[i][j]) !== '\0' ) { - data += `+ [` + KeyArray[j] + `] > \'` + String.fromCharCode(writeArray[i][j]) +'\'\n' - } + for (let i = 0; i < writeArray.length; i++) { + for (let j = 0; j < writeArray[0].length; j++) { + const textdecoder = new TextDecoder().decode(writeArray[i][j]) + if (textdecoder !== '\0' ) + data += `+ [` + KeyArray[j] + `] > \'` + textdecoder +'\'\n' } data += '\n' } - writeFileSync("data/MyResult.kmn", data, { flag: "w"}) - + console.log(" _S2 write finished\n") return true; } - } \ No newline at end of file diff --git a/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts index f6d8546507c..229b5d55cc0 100644 --- a/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts @@ -29,11 +29,12 @@ describe('KeylayoutToKmnConverter', function() { }); - // _S2 My tests... + // _S2 My tests... // later throws on NOT all elements loaded it('should throw on all elements loaded', async function () { - console.log(' ..................................................................................') + // some keys, no deadkeys const inputFilename = makePathToFixture('../data/Mysample.keylayout'); + // all keys, some deadkeys //const inputFilename = makePathToFixture('../data/My_dk_Keyboard.keylayout'); const outputFilename = makePathToFixture('../data/MyResult.kmn'); From 179ffc4657f85031d0b76a6b0628a0d784c41a4b Mon Sep 17 00:00:00 2001 From: Sabine Date: Mon, 21 Oct 2024 10:04:54 +0200 Subject: [PATCH 003/251] feat(common): remove filling of K_OEM_102 --- .../src/keylayout-to-kmn/keylayout-to-kmn-converter.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 245e654ccd1..a315edd86d1 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -58,7 +58,7 @@ export class KeylayoutToKmnConverter { public read(filename: string):Uint8Array[] { /* - // _S2 TODO and what about deadkeys??? -- // _S2 TODO use output ? + [K_A] > 'a' or + [K_A] > U+0061 +- // _S2 TODO which format to use in output ? + [K_A] > 'a' (character code) or + [K_A] > U+0061 (virt Keycode) - // _S2 which stores? - // _S2 how to use names of shiftstates*/ @@ -121,7 +121,6 @@ public convert(inArray: any[]):any[] { outkeys_in_Layer[29] = inArray[j][5]; outkeys_in_Layer[38] = inArray[j][6]; outkeys_in_Layer[46] = inArray[j][7]; - outkeys_in_Layer[49] = inArray[j][0]; outArray[j] = outkeys_in_Layer } From 6666ef228e656c504f690a5cee74fb7818b13a9f Mon Sep 17 00:00:00 2001 From: Sabine Date: Mon, 21 Oct 2024 10:04:54 +0200 Subject: [PATCH 004/251] feat(common): remove MyResult1.kmn --- developer/src/kmc-convert/data/MyResult1.kmn | 39 ------------------- .../keylayout-to-kmn-converter.ts | 3 +- 2 files changed, 1 insertion(+), 41 deletions(-) delete mode 100644 developer/src/kmc-convert/data/MyResult1.kmn diff --git a/developer/src/kmc-convert/data/MyResult1.kmn b/developer/src/kmc-convert/data/MyResult1.kmn deleted file mode 100644 index cec5673a200..00000000000 --- a/developer/src/kmc-convert/data/MyResult1.kmn +++ /dev/null @@ -1,39 +0,0 @@ -begin Unicode > use(main) - -group(main) using keys - -+ [K_A] > 'a' -+ [K_B] > 'b' -+ [K_C] > 'c' -+ [K_Q] > 'q' -+ [K_Y] > 'y' -+ [K_3] > '3' -+ [K_HYPHEN] > 'ß' -+ [K_PERIOD] > '.' - -+ [K_A] > 'A' -+ [K_B] > 'B' -+ [K_C] > 'C' -+ [K_Q] > 'Q' -+ [K_Y] > 'Y' -+ [K_3] > '§' -+ [K_HYPHEN] > '?' -+ [K_PERIOD] > ':' - -+ [K_A] > ':' -+ [K_B] > '9' -+ [K_Q] > '@' -+ [K_Y] > ':' -+ [K_3] > '³' -+ [K_HYPHEN] > '\' -+ [K_PERIOD] > '·' - -+ [K_A] > 'A' -+ [K_B] > 'B' -+ [K_C] > 'C' -+ [K_Q] > 'Q' -+ [K_Y] > 'Y' -+ [K_3] > '3' -+ [K_HYPHEN] > 'ß' - - diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 245e654ccd1..a315edd86d1 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -58,7 +58,7 @@ export class KeylayoutToKmnConverter { public read(filename: string):Uint8Array[] { /* - // _S2 TODO and what about deadkeys??? -- // _S2 TODO use output ? + [K_A] > 'a' or + [K_A] > U+0061 +- // _S2 TODO which format to use in output ? + [K_A] > 'a' (character code) or + [K_A] > U+0061 (virt Keycode) - // _S2 which stores? - // _S2 how to use names of shiftstates*/ @@ -121,7 +121,6 @@ public convert(inArray: any[]):any[] { outkeys_in_Layer[29] = inArray[j][5]; outkeys_in_Layer[38] = inArray[j][6]; outkeys_in_Layer[46] = inArray[j][7]; - outkeys_in_Layer[49] = inArray[j][0]; outArray[j] = outkeys_in_Layer } From 91f2105268c5662ae36e030e8c53002d14412a91 Mon Sep 17 00:00:00 2001 From: Sabine Date: Mon, 21 Oct 2024 10:43:48 +0200 Subject: [PATCH 005/251] feat(common): remove file --- .../src/kmc-convert/data/MySampleKMN.kmn | 33 ------------------- 1 file changed, 33 deletions(-) delete mode 100644 developer/src/kmc-convert/data/MySampleKMN.kmn diff --git a/developer/src/kmc-convert/data/MySampleKMN.kmn b/developer/src/kmc-convert/data/MySampleKMN.kmn deleted file mode 100644 index dae7175f741..00000000000 --- a/developer/src/kmc-convert/data/MySampleKMN.kmn +++ /dev/null @@ -1,33 +0,0 @@ -begin Unicode > use(main) - -group(main) using keys - -c ## BASE layer ##################### -+ [K_A] > 'a' -+ [K_B] > 'b' -+ [K_C] > 'c' -+ [K_Q] > 'q' -+ [K_Z] > 'y' -+ [K_HYPHEN] > 'ß' -+ [K_3] > '3' -+ [K_PERIOD] > '.' - -c ## SHIFT layer #################### -+ [SHIFT K_A] > 'A' -+ [SHIFT K_B] > 'B' -+ [SHIFT K_C] > 'C' -+ [SHIFT K_Q] > 'Q' -+ [SHIFT K_Z] > 'Y' -+ [SHIFT K_HYPHEN] > '?' -+ [SHIFT K_3] > '§' -+ [SHIFT K_PERIOD] > ':' - -c ## ALT layer ###################### -+ [ALT K_A] > '☺' -+ [ALT K_B] > '‹' -+ [ALT K_C] > ' ' -+ [ALT K_Q] > '@' -+ [ALT K_Z] > '›' -+ [ALT K_HYPHEN] > '\' -+ [ALT K_3] > '³' -+ [ALT K_PERIOD] > '·' From f1cdceabb1cc00caf03a9de9a39a1acb7810379b Mon Sep 17 00:00:00 2001 From: Sabine Date: Mon, 21 Oct 2024 10:43:48 +0200 Subject: [PATCH 006/251] feat(common): remove files of mcompile --- .../src/kmc-convert/data/MySampleKMN.kmn | 33 - linux/mcompile/Readme.md | 3 - linux/mcompile/keymap/README.md | 22 - linux/mcompile/keymap/keymap.cpp | 463 --------- linux/mcompile/keymap/keymap.h | 67 -- linux/mcompile/keymap/km_types.h | 88 -- linux/mcompile/keymap/kmx_file.h | 384 -------- linux/mcompile/keymap/main.cpp | 47 - linux/mcompile/keymap/mc_kmxfile.cpp | 297 ------ linux/mcompile/keymap/mc_kmxfile.h | 147 --- linux/mcompile/keymap/mc_savekeyboard.cpp | 423 -------- linux/mcompile/keymap/mc_savekeyboard.h | 18 - linux/mcompile/keymap/mcompile.cpp | 924 ------------------ linux/mcompile/keymap/mcompile.h | 51 - linux/mcompile/keymap/meson.build | 11 - 15 files changed, 2978 deletions(-) delete mode 100644 developer/src/kmc-convert/data/MySampleKMN.kmn delete mode 100644 linux/mcompile/Readme.md delete mode 100644 linux/mcompile/keymap/README.md delete mode 100644 linux/mcompile/keymap/keymap.cpp delete mode 100644 linux/mcompile/keymap/keymap.h delete mode 100644 linux/mcompile/keymap/km_types.h delete mode 100644 linux/mcompile/keymap/kmx_file.h delete mode 100644 linux/mcompile/keymap/main.cpp delete mode 100644 linux/mcompile/keymap/mc_kmxfile.cpp delete mode 100644 linux/mcompile/keymap/mc_kmxfile.h delete mode 100644 linux/mcompile/keymap/mc_savekeyboard.cpp delete mode 100644 linux/mcompile/keymap/mc_savekeyboard.h delete mode 100644 linux/mcompile/keymap/mcompile.cpp delete mode 100644 linux/mcompile/keymap/mcompile.h delete mode 100644 linux/mcompile/keymap/meson.build diff --git a/developer/src/kmc-convert/data/MySampleKMN.kmn b/developer/src/kmc-convert/data/MySampleKMN.kmn deleted file mode 100644 index dae7175f741..00000000000 --- a/developer/src/kmc-convert/data/MySampleKMN.kmn +++ /dev/null @@ -1,33 +0,0 @@ -begin Unicode > use(main) - -group(main) using keys - -c ## BASE layer ##################### -+ [K_A] > 'a' -+ [K_B] > 'b' -+ [K_C] > 'c' -+ [K_Q] > 'q' -+ [K_Z] > 'y' -+ [K_HYPHEN] > 'ß' -+ [K_3] > '3' -+ [K_PERIOD] > '.' - -c ## SHIFT layer #################### -+ [SHIFT K_A] > 'A' -+ [SHIFT K_B] > 'B' -+ [SHIFT K_C] > 'C' -+ [SHIFT K_Q] > 'Q' -+ [SHIFT K_Z] > 'Y' -+ [SHIFT K_HYPHEN] > '?' -+ [SHIFT K_3] > '§' -+ [SHIFT K_PERIOD] > ':' - -c ## ALT layer ###################### -+ [ALT K_A] > '☺' -+ [ALT K_B] > '‹' -+ [ALT K_C] > ' ' -+ [ALT K_Q] > '@' -+ [ALT K_Z] > '›' -+ [ALT K_HYPHEN] > '\' -+ [ALT K_3] > '³' -+ [ALT K_PERIOD] > '·' diff --git a/linux/mcompile/Readme.md b/linux/mcompile/Readme.md deleted file mode 100644 index f45bdbe1fb4..00000000000 --- a/linux/mcompile/Readme.md +++ /dev/null @@ -1,3 +0,0 @@ -This is a proposal to rewrite mcompile for Linux. For this we need to query the base keyboard data from the Linux platform, then rewriting the keyboard .kmx using the same approach as is done in mcompile for Windows, but working from the data from the x11 keyboard on Linux. - -Ideally, we'd rewrite mcompile to be cross-platform (Windows, Linux, macOS), so that the keyboard interrogation would be separated from the .kmx rewriting, at least to some degree. Nevertheless it would probably be easiest to start from a standalone implementation. diff --git a/linux/mcompile/keymap/README.md b/linux/mcompile/keymap/README.md deleted file mode 100644 index a40b7d4fefb..00000000000 --- a/linux/mcompile/keymap/README.md +++ /dev/null @@ -1,22 +0,0 @@ -# Keymap - -Sample program that reads US basic keyboard and compares to key value group - - - -TODO check if US basic is the right Keyboard to compare with -TODO non-letter characters don't work OK yet -TODO Umlauts don't work OK yet -TODO Check for use of correct dimensions in Vector/prevent error if dims are not correct -TODO prevent crashes: handle possible Errors in CreateCompleteRow_US, Split_US_To_3D_Vector -TODO check Keycode of TLDE, BKSL, LSGT -TODO remove unnecessary printf/cout -TODO path for xkb/symbols as compile time option in meson -TODO append_other_ToVector: ensure shift states of GetKeyvalsFromKeymap are not out of range -TODO check how many/which shift states we use ( at the moment we read all shiftstate-columns of US but then use only 2 colums - (non-shift + shift) then use as many colums for Other ) - -TODO define folder to store File_US.txt" in and find better name -TODO get rid of GTK functions that are deprecated and use X11 instead -TODO retrieve name of Other keyboard and use appropriate name instead of "Other" -TODO ... diff --git a/linux/mcompile/keymap/keymap.cpp b/linux/mcompile/keymap/keymap.cpp deleted file mode 100644 index 397be17f6c2..00000000000 --- a/linux/mcompile/keymap/keymap.cpp +++ /dev/null @@ -1,463 +0,0 @@ -#include "keymap.h" - -/* -static void PrintKeymapForCode(GdkKeymap *keymap, guint keycode) -{ - GdkKeymapKey *maps; - guint *keyvals; - gint count; - - if (!gdk_keymap_get_entries_for_keycode(keymap, keycode, &maps, &keyvals, &count)) - return; - - for (int i = 0; i < count; i++) { - if (maps[i].level > 0 || maps[i].group > 1) - continue; - printf(" i=%d, keycode=%d, keyval=%d (%c), level=%d, group=%d\n", i, maps[i].keycode, keyvals[i], keyvals[i], maps[i].level, maps[i].group); - } - - g_free(keyvals); - g_free(maps); -} -*/ - -void write_US_ToVector( v_str_3D &vec,std::string language, const char* text) { - // ? CHECK if ran OK-> return 0/1 - std::string FullPathName = "/usr/share/X11/xkb/symbols/" + language; - - const char* path = FullPathName.c_str(); - FILE* fp = fopen((path), "r"); - if ( !fp) - printf("could not open file!"); - - // create 1D-vector of the complete line - v_str_1D Vector_completeUS; - CreateCompleteRow_US(Vector_completeUS,fp , text, language); - - // split contents of 1D Vector to 3D vector - Split_US_To_3D_Vector( vec,Vector_completeUS); - - printf("+++++++ dimensions of Vector after write_US_ToVector\t\t %li..%li..%li\n", vec.size(), vec[0].size(),vec[0][0].size()); - fclose(fp); -} - -void CreateCompleteRow_US(v_str_1D &complete_List, FILE* fp, const char* text, std::string language) { - // in the Configuration file we find the appopriate paragraph between "xkb_symbol " and the next xkb_symbol - // and then copy all rows starting with "key <" to a v1D-Vector - - // ? CHECK if ran OK-> return 0/1 - int buffer_size = 512; - char buffer[buffer_size]; - bool print_OK = false; - const char* key = "key <"; - std::string str_txt(text); - std::string xbk_mark = "xkb_symbol"; - // TODO define folder to store File in - std::ofstream KeyboardFile("File_" + language + ".txt"); - - printf("Keyboard %s\n", text); - KeyboardFile << "Keyboard" << text << "\n"; - - if (fp) { - while (fgets(buffer, buffer_size, fp) != NULL) { - std::string str_buf(buffer); - - // stop when finding the mark xkb_symbol - if (std::string(str_buf).find(xbk_mark) != std::string::npos) - print_OK = false; - - // start when finding the mark xkb_symbol + correct layout - if ((std::string(str_buf).find(str_txt) != std::string::npos)) - print_OK = true; - - // as long as we are in the same xkb_symbol layout block and find "key <" we push the whole line into a 1D-vector - if ((print_OK) && (std::string(str_buf).find(key) != std::string::npos)) { - printf("%s", buffer); - complete_List.push_back(buffer); - KeyboardFile << buffer; - } - } - } - printf("-°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° \n"); -} - -void Split_US_To_3D_Vector(v_str_3D &all_US,v_str_1D completeList) { - // 1: take the whole line of the 1D-Vector and remove unwanted characters. - // 2: seperate the name e.g. key and the shiftstates - // 3: push Names/Shiftstates to shift_states and then shiftstates to All_US, our 3D-Vector holding all Elements - - // ? CHECK if ran OK-> return 0/1 - std::vector delim{' ', '[', ']', '}', ';', '\t', '\n'}; - char split_bracel = '{'; - char split_char_komma = ','; - std::string empty = "--"; - v_str_1D tokens; - v_str_2D shift_states; - - // go through the whole vector - for (int k = 0; k < (int)completeList.size() - 1; k++) { - - // remove all unwanted char - for (int i = 0; i < (int) delim.size(); i++) { - completeList[k].erase(remove(completeList[k].begin(), completeList[k].end(), delim[i]), completeList[k].end()); - } - - // only lines with ("key<.. are of interest - if (completeList[k].find("key<") != std::string::npos) { - - //split off the key names - std::istringstream split1(completeList[k]); - for (std::string each; std::getline(split1, each, split_bracel); tokens.push_back(each)); - - // replace keys names with number ( with 29,...) - - // ? CHECK if ran OK-> return 0/1 - int Keycde = replace_PosKey_with_Keycode(tokens[0]); - tokens[0] = std::to_string(Keycde); - - // seperate rest of the vector to its elements and push to 'tokens' - std::istringstream split(tokens[1]); - tokens.pop_back(); - for (std::string each; std::getline(split, each, split_char_komma); tokens.push_back(each)); - //printf("### 5 Split_US_To_3D_Vector: tokens: size:%li...tokens[0]-[4]:-name:%s\tShiftstates:%s--%s--%s--%s---.\n", tokens.size(),tokens[0].c_str(),tokens[1].c_str(),tokens[2].c_str(),tokens[3].c_str(),tokens[4].c_str()); - - // at the moment we only use the first 2 shiftstates (non-shift+shift) so get rid of all others - int surplus = tokens.size() - shift_state_count -1; - for( int j=0; j < surplus;j++) { - tokens.pop_back(); - } - - // now push result to shift_states - shift_states.push_back(tokens); - tokens.clear(); - } - } - all_US.push_back(shift_states); - - // ? CHECK if ran OK, vector size is correct -> return 0/1 - //printf("### 6 Split_US_To_3D_clearVector %li..%li..%li\n", all_US.size(), all_US[0].size(),all_US[0][0].size()); -} - -int replace_PosKey_with_Keycode(std::string in) { - int out=0; - if ( in == "key") out = 49; //correct ??? - else if ( in == "key") out = 10; - else if ( in == "key") out = 11; - else if ( in == "key") out = 12; - else if ( in == "key") out = 13; - else if ( in == "key") out = 14; - else if ( in == "key") out = 15; - else if ( in == "key") out = 16; - else if ( in == "key") out = 17; - else if ( in == "key") out = 18; - else if ( in == "key") out = 19; - else if ( in == "key") out = 20; - else if ( in == "key") out = 21; - - else if ( in == "key") out = 24; - else if ( in == "key") out = 25; - else if ( in == "key") out = 26; - else if ( in == "key") out = 27; - else if ( in == "key") out = 28; - else if ( in == "key") out = 29; - else if ( in == "key") out = 30; - else if ( in == "key") out = 31; - else if ( in == "key") out = 32; - else if ( in == "key") out = 33; - else if ( in == "key") out = 34; - else if ( in == "key") out = 35; - - else if ( in == "key") out = 38; - else if ( in == "key") out = 39; - else if ( in == "key") out = 40; - else if ( in == "key") out = 41; - else if ( in == "key") out = 42; - else if ( in == "key") out = 43; - else if ( in == "key") out = 44; - else if ( in == "key") out = 45; - else if ( in == "key") out = 46; - else if ( in == "key") out = 47; - else if ( in == "key") out = 48; - else if ( in == "key") out = 49; - - else if ( in == "key") out = 52; - else if ( in == "key") out = 53; - else if ( in == "key") out = 54; - else if ( in == "key") out = 55; - else if ( in == "key") out = 56; - else if ( in == "key") out = 57; - else if ( in == "key") out = 58; - else if ( in == "key") out = 59; - else if ( in == "key") out = 60; - else if ( in == "key") out = 61; - else if ( in == "key") out = 62; //correct ??? - else if ( in == "key") out = 51; //correct ??? - return out; -} - -void append_other_ToVector(v_str_3D &All_Vector,GdkKeymap * keymap) { - - // create a 2D vector all fill0ed with "--" and push to 3D-Vector - // ? CHECK if ran OK-> return 0/1 - v_str_2D Other_Vector2D = create_empty_2D(All_Vector[0].size(),All_Vector[0][0].size()); - All_Vector.push_back(Other_Vector2D); - - printf("+++++++ dimensions of Vector after append_other_ToVector\t %li..%li..%li\n", All_Vector.size(), All_Vector[0].size(),All_Vector[0][0].size()); - - for(int i =1; i< (int) All_Vector[1].size()-1;i++) - { - // get key name US stored in [0][i][0] and copy to name in other-block[1][i][0] - All_Vector[1][i][0] = All_Vector[0][i][0]; - - // write this value to 3D- Vector - All_Vector[1][i][0+1] = GetKeyvalsFromKeymap(keymap,stoi(All_Vector[1][i][0]),0); //shift state: unshifted:0 - All_Vector[1][i][1+1] = GetKeyvalsFromKeymap(keymap,stoi(All_Vector[1][i][0]),1); //shift state: shifted:1 - //printf("Keycodes US->Other: %d(US): %s %s ---- (other):%s, %s, %s \n",stoi(All_Vector[1][i][0]),All_Vector[0][i][1].c_str(),All_Vector[0][i][2].c_str(),All_Vector[1][i][1].c_str(),All_Vector[1][i][2].c_str(),All_Vector[1][i][3].c_str()); - } - // ? CHECK if ran OK, vector size is correct -> return 0/1 -} - -v_str_2D create_empty_2D( int dim_rows,int dim_shifts) -{ - std::string empty = "--"; - v_str_1D shifts; - v_str_2D all; - - for ( int i=0; i< dim_rows;i++) { - for ( int j=0; j< dim_shifts;j++) { - shifts.push_back(empty); - } - all.push_back(shifts); - shifts.clear(); - } - //printf("+++++++ dimensions of Vector after create_empty_2D\t\t %li..%li..%li\n", all.size(), all[0].size(),all[1].size()); - return all; -} - -int GetKeyvalsFromKeymap(GdkKeymap *keymap, guint keycode, int shift_state_pos) { - GdkKeymapKey *maps; - guint *keyvals; - gint count; - int out; - - if (!gdk_keymap_get_entries_for_keycode(keymap, keycode, &maps, &keyvals, &count)) - return 0; - //if(!gdk_wayland_keymap_get_entries_for_keycode(keymap, keycode, &maps, &keyvals, &count)) - // return 0; - - if (!(shift_state_pos < count)) - return 0; - - out = keyvals[shift_state_pos]; - - g_free(keyvals); - g_free(maps); - return out; -} - -void extract_difference( v_str_3D &All_Vector) -{ - // ? CHECK if ran OK-> return 0/1 - // TODO define which Folder; find better name - std::ofstream Map_File("Map_US.txt"); - std::string diff =" "; - - printf("-----------------------------------------------------------------------------------------------------------------------------------------------\n"); - std::cout << "Nr of \n" ; - std::cout << "Key: " << "\t Character US (no shift) " << " Character US (shift) "<< "\t\tCharacter other (no shift)" << "\tCharacter other (shift) difference \n" ; - printf("-----------------------------------------------------------------------------------------------------------------------------------------------\n"); - - Map_File <<"--------------------------------------------------------------------------------------------------------------------------------------------\n"; - Map_File << "Nr of \n" ; - Map_File << "Key: " << "\t Character US (no shift) " << " Character US (shift) "<< "\t\tCharacter other (no shift)" << "\tCharacter other (shift) difference \n" ; - Map_File <<"--------------------------------------------------------------------------------------------------------------------------------------------\n"; - - for ( int k=0; k<(int)All_Vector[0].size()-1; k++) { - if (All_Vector[0][k][1] == All_Vector[1][k][1]) - diff =" "; - else - diff =" *** "; - // ? CHECK if index exists - std::cout << All_Vector[0][k][0] << "\t " <<+(*(All_Vector[0][k][1].c_str()))<< "\t("<< All_Vector[0][k][1] <<")"< Other: "<< std::setw(5)< Other: (" << in << ": no match)\n"; - return "-"; -} - -std::string get_US_Char_FromOther(std::string in , v_str_3D &All_Vector) { - std::string diff; - // find correct row of char in other - for( int i=0; i< (int)All_Vector[1].size()-1;i++) { - for( int j=0; j< (int)All_Vector[1][0].size()-1;j++) { - if ( All_Vector[1][i][j] == in ) { - if ( All_Vector[0][i][j] != All_Vector[1][i][j]) - diff =" ** "; - // ? CHECK if Index exists - std::cout << "Other -> US: "<< std::setw(5)< US: (" << in << ": no match)\n"; - return "-"; - } - -std::string getKeyNrOf_USChar(std::string in , v_str_3D &All_Vector) { - // find correct row of char in US - for( int i=0; i< (int)All_Vector[0].size()-1;i++) { - for( int j=0; j< (int)All_Vector[0][0].size()-1;j++) { - if ( All_Vector[0][i][j] == in ) { - // ? CHECK if index exists - std::cout << "KeyNr of US char: \t"<< All_Vector[0][i][j] << " -> " << All_Vector[0][i][0] <<"\n"; - return All_Vector[0][i][0] ; - } - } - } - return "-"; -} - -std::string getKeyNrOf_OtherChar(std::string in , v_str_3D &All_Vector) { - // find correct row of char in US - for( int i=0; i< (int)All_Vector[1].size()-1;i++) { - for( int j=0; j< (int)All_Vector[1][0].size()-1;j++) { - if ( All_Vector[1][i][j] == in ) { - // ? CHECK if index exists - std::cout << "KeyNr of Other char : \t"<< All_Vector[1][i][j] << " -> " << All_Vector[1][i][0] <<"\n"; - return All_Vector[1][i][0] ; - } - } - } - return "-"; -} - -bool test(v_str_3D &V) { -// ? CHECK if index exists - printf("\n+++++++++ print some characters of US and Other +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"); - - for ( int k=13; k<43; k++) { - std::cout << " row 1 (US)......" << V[0][k][0]<< ".." << V[0][k][1]<< ".."<< V[0][k][2]<< ".." << V[0][k][3]<< ".." << V[0][k][4]<< "..\n" ; - if (V.size()>1) - std::cout << " row 1 (Other).."<< V[1][k][0]<< ".." << V[1][k][1]<< ".."<< V[1][k][2]<< ".." << V[1][k][3]<< ".." << V[1][k][4]<< "..\n" ; - } - printf("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"); - return true; -} - -void test_in_out(v_str_3D &All_Vector) { -std::string diff; - printf("-----------------------------------------------------------------------------------------------------------------------------------------------\n"); - //checks mapping between US and other - std::string a = get_Other_Char_FromUS( "z", All_Vector); - std::string aa = get_Other_Char_FromUS( "Z", All_Vector); - std::string aaa = get_Other_Char_FromUS( "y", All_Vector); - std::string aaaa = get_Other_Char_FromUS( "Y", All_Vector); - - std::string b = get_US_Char_FromOther( "z", All_Vector); - std::string bb = get_US_Char_FromOther( "Z", All_Vector); - std::string bbb = get_US_Char_FromOther( "y", All_Vector); - std::string bbbb = get_US_Char_FromOther( "Y", All_Vector); - - std::string c = getKeyNrOf_OtherChar( "z", All_Vector); - std::string cc = getKeyNrOf_OtherChar( "Z", All_Vector); - std::string ccc = getKeyNrOf_OtherChar( "y", All_Vector); - std::string cccc = getKeyNrOf_OtherChar( "Y", All_Vector); - - std::string d = getKeyNrOf_USChar( "z", All_Vector); - std::string dd = getKeyNrOf_USChar( "Z", All_Vector); - std::string ddd = getKeyNrOf_USChar( "y", All_Vector); - std::string dddd = getKeyNrOf_USChar( "Y", All_Vector); - - std::cout << "get_Other_Char_FromUS z-Z-y-Y: " << ".." << a<< ".." < return 0/1 - printf("-----------------------------------------------------------------------------------------------------------------------------------------------\n"); - for ( int i=0; i< (int)All_Vector[0].size();i++) { - out =get_Other_Char_FromUS(All_Vector[0][i][shiftstate], All_Vector); - } -} - -void print_simple_map_Other(v_str_3D &All_Vector, int shiftstate){ - std::string out, diff; - // ? CHECK if ran OK-> return 0/1 - printf("-----------------------------------------------------------------------------------------------------------------------------------------------\n"); - for ( int i=0; i< (int)All_Vector[0].size();i++) { - out = get_US_Char_FromOther(All_Vector[0][i][shiftstate], All_Vector); - } -} - -void test_specific_Characters(v_str_3D &All_Vector){ - printf("-----------------------------------------------------------------------------------------------------------------------------------------------\n"); - v_str_1D in {"a", "b", "m", "w", "x", "y", "z"}; - std::string out; - for( int i=0; i< (int) in.size()-1; i++) { - out = get_Other_Char_FromUS(in[i], All_Vector); - } -} - - -//-------------------------------------- -int main(gint argc, gchar *argv[]) -{ - gdk_init(&argc, &argv); - GdkDisplay *display = gdk_display_get_default(); - if (!display) { - printf("ERROR: can't get display\n"); - return 1; - } - GdkKeymap *keymap = gdk_keymap_get_for_display(display); - if (!keymap) { - printf("ERROR: Can't get keymap\n"); - gdk_display_close(display); - return 2; - } - - // write content of xkb_symbols to 3D Vector - // I assume we use Keyboard US basic as base - std::string US_language = "us"; - const char* text_us = "xkb_symbols \"basic\""; - - v_str_3D All_Vector; - write_US_ToVector(All_Vector,US_language, text_us); - //test(All_Vector); - - // add contents of other keyboard to vector - append_other_ToVector(All_Vector,keymap); - //test(All_Vector); - - extract_difference(All_Vector); - //test_in_out(All_Vector); - - //print_simple_map_US(All_Vector,1); // 1 = non-shift - //print_simple_map_Other(All_Vector,1); // 1 = non-shift - test_specific_Characters(All_Vector); - gdk_display_close(display); - - printf("°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° end\n"); - return 0; -} diff --git a/linux/mcompile/keymap/keymap.h b/linux/mcompile/keymap/keymap.h deleted file mode 100644 index cfbd5dc1df9..00000000000 --- a/linux/mcompile/keymap/keymap.h +++ /dev/null @@ -1,67 +0,0 @@ -// In ths program we use a 3D-Vector Vector[language][Keys][Shiftstates] -#pragma once - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "mc_kmxfile.h" -#include "mc_savekeyboard.h" - -typedef std::vector v_str_1D; -typedef std::vector > v_str_2D; -typedef std::vector > > v_str_3D; - -int shift_state_count = 2; // use shiftstate : no shift, shift - -// read configuration file, split and write to 3D-Vector (Data for US on [0][ ][ ] ) -void write_US_ToVector(v_str_3D &vec, std::string language, const char *text); - -// 1. step: read complete Row of Configuration file US -void CreateCompleteRow_US(v_str_1D &complete_List, FILE *fpp, const char *text, std::string language); - -// 2nd step: write contents to 3D vector -void Split_US_To_3D_Vector(v_str_3D &all_US, v_str_1D completeList); - -// replace Name of Key (e.g. ) wih Keycode ( e.g. 15 ) -int replace_PosKey_with_Keycode(std::string in); - -// append characters using GDK to 3D-Vector (Data for Other Language on [1][ ][ ] ) -void append_other_ToVector(v_str_3D &All_Vector, GdkKeymap *keymap); - -// create an empty 2D vector containing "--" in all fields -v_str_2D create_empty_2D(int dim_rows, int dim_shifts); - -// find Keyvals to fill into 2D-Vector of Other Language -int GetKeyvalsFromKeymap(GdkKeymap *keymap, guint keycode, int shift_state_pos); - -// print both sets of characters (US and OtherLanguage) to console and file for comparison -void extract_difference(v_str_3D &All_Vector); - -// get mapped key from Other (Other->US) -std::string get_Other_Char_FromUS(std::string in, v_str_3D &All_Vector); -// get mapped key from US->Other (US->Other) -std::string get_US_Char_FromOther(std::string in, v_str_3D &All_Vector); -// get KeyNr from US -std::string getKeyNrOf_USChar(std::string in, v_str_3D &All_Vector); -// get KeyNr from Other -std::string getKeyNrOf_OtherChar(std::string in, v_str_3D &All_Vector); - -// for testing/debugging - may be deleted later -// prints out a 1:1 mapping US->Other -void print_simple_map_US(v_str_3D &All_Vector, int shiftstate); -// prints out a 1:1 mapping Other->US -void print_simple_map_Other(v_str_3D &All_Vector, int shiftstate); -// test of above functions (character mapping US <-> Other; KeyNr <-> CHaracter) -void test_in_out(v_str_3D &All_Vector); -// testing of Vector contents ( first row of US and Other) -bool test(v_str_3D &V); -// writing out mapping of some characters: a,b,m,w,x,y,z -void test_specific_Characters(v_str_3D &All_Vector); diff --git a/linux/mcompile/keymap/km_types.h b/linux/mcompile/keymap/km_types.h deleted file mode 100644 index 5e6c25e8136..00000000000 --- a/linux/mcompile/keymap/km_types.h +++ /dev/null @@ -1,88 +0,0 @@ -#pragma once -#include - -#include - -/* -#if defined(_WIN32) || defined(_WIN64) -#define snprintf _snprintf -#define vsnprintf _vsnprintf -#define strcasecmp _stricmp -#define strncasecmp _strnicmp -#endif -*/ - -#if defined(__LP64__) || defined(_LP64) -/* 64-bit, g++ */ -#define KMX_64BIT -#endif - -#if defined(_WIN64) && !defined(USE_64) -/* 64-bit, Windows */ -#define KMX_64BIT -#endif - -typedef uint32_t KMX_DWORD; -typedef int32_t KMX_BOOL; -typedef uint8_t KMX_BYTE; -typedef uint16_t KMX_WORD; - -#if defined(__cplusplus) -typedef char16_t km_kbp_cp; -typedef char32_t km_kbp_usv; -#else -typedef uint16_t km_kbp_cp; // code point -typedef uint32_t km_kbp_usv; // Unicode Scalar Value -#endif - -typedef km_kbp_cp KMX_WCHAR; // wc, 16-bit UNICODE character - -typedef wchar_t WCHAR; // _S2 needs to be removed/ wchart-> char16 -typedef WCHAR KMX_WCHART; // _S2 needs to be removed/ wchart-> char16 -typedef KMX_WCHAR* PKMX_WCHAR; // _S2 -typedef wchar_t* PWSTR; // _S2 needs to be removed/ wchart-> char16 -typedef PWSTR PKMX_WCHART; // _S2 needs to be removed/ wchart-> char16 - -typedef wchar_t* LPKMX_WCHART; // _S2 needs to be removed/ wchart-> char16 - -typedef char* LPSTR; // _S2 needs to be removed? -typedef LPSTR LPKMX_STR; // _S2 needs to be removed? - -typedef uint8_t* LPBYTE; // _S2 needs to be removed/? -typedef LPBYTE LPKMX_BYTE; // _S2 needs to be removed? - -typedef uint8_t* PBYTE; // _S2 needs to be removed/? -typedef PBYTE PKMX_BYTE; // _S2 needs to be removed? - - // _S2 LPKEYBOARD ok to leave as is?? - -typedef char KMX_CHAR; // _S2 needs to be removed/? -typedef char* PKMX_STR; // _S2 needs to be removed/? - -typedef KMX_CHAR* PKMX_CHAR; // _S2 needs to be removed/? - -typedef uint32_t KMX_UINT; - -typedef KMX_BYTE* PKMX_BYTE; -typedef KMX_WORD* PKMX_WORD; -typedef KMX_DWORD* PKMX_DWORD; - -#ifndef FALSE -#define FALSE 0 -#endif - -#ifndef TRUE -#define TRUE 1 -#endif - -// Macros and types to support char16_t vs wchar_t depending on project - -#ifdef USE_CHAR16_T -#define lpuch(x) u ## x -typedef km_kbp_cp KMX_UCHAR; -#else -#define lpuch(x) L ## x -typedef wchar_t KMX_UCHAR; -#endif - -typedef KMX_UCHAR* KMX_PUCHAR; diff --git a/linux/mcompile/keymap/kmx_file.h b/linux/mcompile/keymap/kmx_file.h deleted file mode 100644 index 998c9780072..00000000000 --- a/linux/mcompile/keymap/kmx_file.h +++ /dev/null @@ -1,384 +0,0 @@ -/* - Copyright: Copyright (C) 2003-2018 SIL International. - Authors: mcdurdin -*/ - -#pragma once - -#include - -#ifdef KMN_KBP -// TODO: move this to a common namespace keyman::common::kmx_file or similar in the future -namespace km { -namespace kbp { -namespace kmx { -#endif - -#define KMX_MAX_ALLOWED_FILE_SIZE (128 * 1024 * 1024) /* 128MB */ -/* */ - -#define KEYMAN_LAYOUT_DEFAULT 0x000005FE - -#define KEYMANID_NONKEYMAN 0xFFFFFFFF -#define KEYMANID_IGNORE 0xFFFFFFFE -#define KEYMANID_INVALID 0xFFFFFFFD - -/* Shift flags for hotkeys (version 1.0) */ - -#define SHIFTFLAG 0x2000 -#define CTRLFLAG 0x4000 -#define ALTFLAG 0x8000 - -/* Miscellaneous flags and defines */ - -#define MAXGROUPS 128 - -/* File version identifiers */ - -#define VERSION_30 0x00000300 -#define VERSION_31 0x00000301 -#define VERSION_32 0x00000302 -#define VERSION_40 0x00000400 -#define VERSION_50 0x00000500 -#define VERSION_501 0x00000501 -#define VERSION_60 0x00000600 -#define VERSION_70 0x00000700 -#define VERSION_80 0x00000800 -#define VERSION_90 0x00000900 -#define VERSION_100 0x00000A00 -#define VERSION_140 0x00000E00 -#define VERSION_150 0x00000F00 - -#define VERSION_160 0x00001000 - -#define VERSION_MIN VERSION_50 -#define VERSION_MAX VERSION_160 - -// -// Backspace types -// - -#define BK_DEFAULT 0 -#define BK_DEADKEY 1 - -// Different begin types -#define BEGIN_ANSI 0 -#define BEGIN_UNICODE 1 -#define BEGIN_NEWCONTEXT 2 -#define BEGIN_POSTKEYSTROKE 3 - -#define TSS_NONE 0 -#define TSS_BITMAP 1 -#define TSS_COPYRIGHT 2 -#define TSS_HOTKEY 3 -#define TSS_LANGUAGE 4 -#define TSS_LAYOUT 5 -#define TSS_MESSAGE 6 -#define TSS_NAME 7 -#define TSS_VERSION 8 -#define TSS_CAPSONONLY 9 -#define TSS_CAPSALWAYSOFF 10 -#define TSS_SHIFTFREESCAPS 11 -#define TSS_LANGUAGENAME 12 - -#define TSS_CALLDEFINITION 13 -#define TSS_CALLDEFINITION_LOADFAILED 14 - -#define TSS_ETHNOLOGUECODE 15 - -#define TSS_DEBUG_LINE 16 - -#define TSS_MNEMONIC 17 - -#define TSS_INCLUDECODES 18 - -#define TSS_OLDCHARPOSMATCHING 19 - -#define TSS_COMPILEDVERSION 20 -#define TSS_KEYMANCOPYRIGHT 21 - -#define TSS_CUSTOMKEYMANEDITION 22 -#define TSS_CUSTOMKEYMANEDITIONNAME 23 - -/* Keyman 7.0 system stores */ - -#define TSS__KEYMAN_60_MAX 23 - -#define TSS_VISUALKEYBOARD 24 -#define TSS_KMW_RTL 25 -#define TSS_KMW_HELPFILE 26 -#define TSS_KMW_HELPTEXT 27 -#define TSS_KMW_EMBEDJS 28 - -#define TSS_WINDOWSLANGUAGES 29 - -#define TSS__KEYMAN_70_MAX 29 - -/* Keyman 8.0 system stores */ - -#define TSS_COMPARISON 30 - -#define TSS__KEYMAN_80_MAX 30 - -/* Keyman 9.0 system stores */ - -#define TSS_PLATFORM 31 -#define TSS_BASELAYOUT 32 -#define TSS_LAYER 33 - -#define TSS_PLATFORM_NOMATCH 0x8001 // Reserved for internal use - after platform statement is run, set to either TSS_PLATFORM_NOMATCH or TSS_PLATFORM_MATCH -#define TSS_PLATFORM_MATCH 0x8002 // Reserved for internal use - as the result will never change for the lifetime of the process. - -#define TSS_VKDICTIONARY 34 // Dictionary of virtual key names for v9 dynamic layouts -#define TSS_LAYOUTFILE 35 // Keyman 9 layer-based JSON OSK -#define TSS_KEYBOARDVERSION 36 // &keyboardversion system store // I4140 -#define TSS_KMW_EMBEDCSS 37 - -#define TSS_TARGETS 38 - -#define TSS__KEYMAN_90_MAX 38 - -/* Keyman 14.0 system stores */ - -#define TSS_CASEDKEYS 39 - -#define TSS__KEYMAN_140_MAX 39 - -/* Keyman 15.0 system stores */ - -#define TSS_BEGIN_NEWCONTEXT 40 -#define TSS_BEGIN_POSTKEYSTROKE 41 -#define TSS_NEWLAYER 42 -#define TSS_OLDLAYER 43 - -#define TSS__KEYMAN_150_MAX 43 - -#define TSS__MAX 43 - -/* wm_keyman_control_internal message control codes */ - -#define KMCI_SELECTKEYBOARD 3 // I3933 -#define KMCI_SELECTKEYBOARD_TSF 4 // I3933 -#define KMCI_GETACTIVEKEYBOARD 5 // I3933 -#define KMCI_SETFOREGROUND 6 // I3933 -#define KMCI_SELECTKEYBOARD_BACKGROUND 7 // I4271 -#define KMCI_SELECTKEYBOARD_BACKGROUND_TSF 8 // I4271 - -#define FILEID_COMPILED 0x5354584B - -#define SZMAX_LANGUAGENAME 80 -#define SZMAX_KEYBOARDNAME 80 -#define SZMAX_COPYRIGHT 256 -#define SZMAX_MESSAGE 1024 - -#define UC_SENTINEL 0xFFFF -#define UC_SENTINEL_EXTENDEDEND 0x10 // was ((CODE_LASTCODE)+1)... what was I thinking? - -#define U_UC_SENTINEL u"\uFFFF" - -/* - * VK__MAX defines the highest virtual key code defined in the system = 0xFF. Custom VK codes start at 256 - */ -#define VK__MAX 255 - -#define CODE_ANY 0x01 -#define CODE_INDEX 0x02 -#define CODE_CONTEXT 0x03 -#define CODE_NUL 0x04 -#define CODE_USE 0x05 -#define CODE_RETURN 0x06 -#define CODE_BEEP 0x07 -#define CODE_DEADKEY 0x08 -// 0x09 = bkspace.-- we don't need to keep this separate though with UC_SENTINEL -#define CODE_EXTENDED 0x0A -//#define CODE_EXTENDEDEND 0x0B deprecated -#define CODE_SWITCH 0x0C -#define CODE_KEY 0x0D -#define CODE_CLEARCONTEXT 0x0E -#define CODE_CALL 0x0F -// UC_SENTINEL_EXTENDEDEND 0x10 -#define CODE_CONTEXTEX 0x11 - -#define CODE_NOTANY 0x12 - -#define CODE_KEYMAN70_LASTCODE 0x12 - -#define CODE_SETOPT 0x13 -#define CODE_IFOPT 0x14 -#define CODE_SAVEOPT 0x15 -#define CODE_RESETOPT 0x16 - -#define CODE_KEYMAN80_LASTCODE 0x16 - -/* Keyman 9.0 codes */ - -#define CODE_IFSYSTEMSTORE 0x17 -#define CODE_SETSYSTEMSTORE 0x18 - -#define CODE_LASTCODE 0x18 - -#define U_CODE_ANY u"\u0001" -#define U_CODE_INDEX u"\u0002" -#define U_CODE_CONTEXT u"\u0003" -#define U_CODE_NUL u"\u0004" -#define U_CODE_USE u"\u0005" -#define U_CODE_RETURN u"\u0006" -#define U_CODE_BEEP u"\u0007" -#define U_CODE_DEADKEY u"\u0008" -#define U_CODE_EXTENDED u"\u000A" -#define U_CODE_SWITCH u"\u000C" -#define U_CODE_CLEARCONTEXT u"\u000E" -#define U_CODE_CALL u"\u000F" -#define U_CODE_EXTENDEDEND u"\u0010" -#define U_CODE_CONTEXTEX u"\u0011" -#define U_CODE_NOTANY u"\u0012" -#define U_CODE_SETOPT u"\u0013" -#define U_CODE_IFOPT u"\u0014" -#define U_CODE_SAVEOPT u"\u0015" -#define U_CODE_RESETOPT u"\u0016" -#define U_CODE_IFSYSTEMSTORE u"\u0017" -#define U_CODE_SETSYSTEMSTORE u"\u0018" - -#define C_CODE_ANY(store) U_UC_SENTINEL U_CODE_ANY store -#define C_CODE_INDEX(val1, val2) U_UC_SENTINEL U_CODE_INDEX val1 val2 -#define C_CODE_CONTEXT() U_UC_SENTINEL U_CODE_CONTEXT -#define C_CODE_NUL() U_UC_SENTINEL U_CODE_NUL -#define C_CODE_USE(val) U_UC_SENTINEL U_CODE_USE val -#define C_CODE_RETURN() U_UC_SENTINEL U_CODE_RETURN -#define C_CODE_BEEP() U_UC_SENTINEL U_CODE_BEEP -#define C_CODE_DEADKEY(deadkey) U_UC_SENTINEL U_CODE_DEADKEY deadkey -#define C_CODE_EXTENDED(varargs) U_UC_SENTINEL U_CODE_EXTENDED varargs -#define C_CODE_SWITCH(val) U_UC_SENTINEL U_CODE_SWITCH val -#define C_CODE_CLEARCONTEXT() U_UC_SENTINEL U_CODE_CLEARCONTEXT -#define C_CODE_CALL(val) U_UC_SENTINEL U_CODE_CALL val -#define C_CODE_CONTEXTEX(val) U_UC_SENTINEL U_CODE_CONTEXTEX val -#define C_CODE_NOTANY(val) U_UC_SENTINEL U_CODE_NOTANY val -#define C_CODE_SETOPT(val1, val2) U_UC_SENTINEL U_CODE_SETOPT val1 val2 -#define C_CODE_IFOPT(opt, val1, val2) U_UC_SENTINEL U_CODE_IFOPT opt val1 val2 -#define C_CODE_SAVEOPT(opt) U_UC_SENTINEL U_CODE_SAVEOPT opt -#define C_CODE_RESETOPT(opt) U_UC_SENTINEL U_CODE_RESETOPT opt -#define C_CODE_IFSYSTEMSTORE(store, val1, val2) U_UC_SENTINEL U_CODE_IFSYSTEMSTORE store val1 val2 -#define C_CODE_SETSYSTEMSTORE(store, val) U_UC_SENTINEL U_CODE_SETSYSTEMSTORE store val - -#define KF_SHIFTFREESCAPS 0x0001 -#define KF_CAPSONONLY 0x0002 -#define KF_CAPSALWAYSOFF 0x0004 -#define KF_LOGICALLAYOUT 0x0008 -#define KF_AUTOMATICVERSION 0x0010 - -// 16.0: Support for LDML Keyboards in KMXPlus file format -#define KF_KMXPLUS 0x0020 - -#define HK_ALT 0x00010000 -#define HK_CTRL 0x00020000 -#define HK_SHIFT 0x00040000 - -#define LCTRLFLAG 0x0001 // Left Control flag -#define RCTRLFLAG 0x0002 // Right Control flag -#define LALTFLAG 0x0004 // Left Alt flag -#define RALTFLAG 0x0008 // Right Alt flag -#define K_SHIFTFLAG 0x0010 // Either shift flag -#define K_CTRLFLAG 0x0020 // Either ctrl flag -#define K_ALTFLAG 0x0040 // Either alt flag -//#define K_METAFLAG 0x0080 // Either Meta-key flag (tentative). Not usable in keyboard rules; - // Used internally (currently, only by KMW) to ensure Meta-key - // shortcuts safely bypass rules - // Meta key = Command key on macOS, Windows key on Windows -#define CAPITALFLAG 0x0100 // Caps lock on -#define NOTCAPITALFLAG 0x0200 // Caps lock NOT on -#define NUMLOCKFLAG 0x0400 // Num lock on -#define NOTNUMLOCKFLAG 0x0800 // Num lock NOT on -#define SCROLLFLAG 0x1000 // Scroll lock on -#define NOTSCROLLFLAG 0x2000 // Scroll lock NOT on -#define ISVIRTUALKEY 0x4000 // It is a Virtual Key Sequence -#define VIRTUALCHARKEY 0x8000 // Keyman 6.0: Virtual Key Cap Sequence NOT YET - -#define K_MODIFIERFLAG 0x007F -#define K_NOTMODIFIERFLAG 0xFF00 // I4548 - -struct COMP_STORE { - KMX_DWORD dwSystemID; - KMX_DWORD dpName; - KMX_DWORD dpString; - }; - -struct COMP_KEY { - KMX_WORD Key; - KMX_WORD _reserved; - KMX_DWORD Line; - KMX_DWORD ShiftFlags; - KMX_DWORD dpOutput; - KMX_DWORD dpContext; - }; - -struct COMP_GROUP { - KMX_DWORD dpName; - KMX_DWORD dpKeyArray; // [LPKEY] address of first item in key array - KMX_DWORD dpMatch; - KMX_DWORD dpNoMatch; - KMX_DWORD cxKeyArray; // in array entries - KMX_BOOL fUsingKeys; // group(xx) [using keys] <-- specified or not - }; - -struct COMP_KEYBOARD { - KMX_DWORD dwIdentifier; // 0000 Keyman compiled keyboard id - - KMX_DWORD dwFileVersion; // 0004 Version of the file - Keyman 4.0 is 0x0400 - - KMX_DWORD dwCheckSum; // 0008 As stored in keyboard. DEPRECATED as of 16.0 - KMX_DWORD KeyboardID; // 000C as stored in HKEY_LOCAL_MACHINE//system//currentcontrolset//control//keyboard layouts - KMX_DWORD IsRegistered; // 0010 - KMX_DWORD version; // 0014 keyboard version - - KMX_DWORD cxStoreArray; // 0018 in array entries - KMX_DWORD cxGroupArray; // 001C in array entries - - KMX_DWORD dpStoreArray; // 0020 [LPSTORE] address of first item in store array - KMX_DWORD dpGroupArray; // 0024 [LPGROUP] address of first item in group array - - KMX_DWORD StartGroup[2]; // 0028 index of starting groups [2 of them] - - KMX_DWORD dwFlags; // 0030 Flags for the keyboard file - - KMX_DWORD dwHotKey; // 0034 standard windows hotkey (hiword=shift/ctrl/alt stuff, loword=vkey) - - KMX_DWORD dpBitmapOffset; // 0038 offset of the bitmaps in the file - KMX_DWORD dwBitmapSize; // 003C size in bytes of the bitmaps -}; - -struct COMP_KEYBOARD_KMXPLUSINFO { - KMX_DWORD dpKMXPlus; // 0040 offset of KMXPlus data, header is first - KMX_DWORD dwKMXPlusSize; // 0044 size in bytes of entire KMXPlus data -}; - -/** - * Only valid if comp_keyboard.dwFlags&KF_KMXPLUS - */ -struct COMP_KEYBOARD_EX { - COMP_KEYBOARD header; // 0000 see COMP_KEYBOARD - COMP_KEYBOARD_KMXPLUSINFO kmxplus; // 0040 see COMP_KEYBOARD_EXTRA -}; - -typedef COMP_KEYBOARD *PCOMP_KEYBOARD; -typedef COMP_STORE *PCOMP_STORE; -typedef COMP_KEY *PCOMP_KEY; -typedef COMP_GROUP *PCOMP_GROUP; - -extern const int CODE__SIZE[]; -#define CODE__SIZE_MAX 5 - -#define KEYBOARDFILEHEADER_SIZE 64 -#define KEYBOARDFILESTORE_SIZE 12 -#define KEYBOARDFILEGROUP_SIZE 24 -#define KEYBOARDFILEKEY_SIZE 20 - -static_assert(sizeof(COMP_STORE) == KEYBOARDFILESTORE_SIZE, "COMP_STORE must be KEYBOARDFILESTORE_SIZE bytes"); -static_assert(sizeof(COMP_KEY) == KEYBOARDFILEKEY_SIZE, "COMP_KEY must be KEYBOARDFILEKEY_SIZE bytes"); -static_assert(sizeof(COMP_GROUP) == KEYBOARDFILEGROUP_SIZE, "COMP_GROUP must be KEYBOARDFILEGROUP_SIZE bytes"); -static_assert(sizeof(COMP_KEYBOARD) == KEYBOARDFILEHEADER_SIZE, "COMP_KEYBOARD must be KEYBOARDFILEHEADER_SIZE bytes"); - -#ifdef KMN_KBP -} // namespace kmx -} // namespace kbp -} // namespace km -#endif diff --git a/linux/mcompile/keymap/main.cpp b/linux/mcompile/keymap/main.cpp deleted file mode 100644 index 2fa3409d871..00000000000 --- a/linux/mcompile/keymap/main.cpp +++ /dev/null @@ -1,47 +0,0 @@ -#include - - -static void PrintKeymapForCode(GdkKeymap *keymap, guint keycode) -{ - GdkKeymapKey *maps; - guint *keyvals; - gint count; - - if (!gdk_keymap_get_entries_for_keycode(keymap, keycode, &maps, &keyvals, &count)) - return; - - for (int i = 0; i < count; i++) { - if (maps[i].level > 0 || maps[i].group > 1) - continue; - printf(" i=%d, keycode=%d, keyval=%d (%c), level=%d, group=%d\n", i, maps[i].keycode, keyvals[i], keyvals[i], maps[i].level, maps[i].group); - } - - g_free(keyvals); - g_free(maps); -} - -int main(gint argc, gchar **argv) -{ - gdk_init(&argc, &argv); - GdkDisplay *display = gdk_display_get_default(); - if (!display) { - printf("ERROR: can't get display\n"); - return 1; - } - GdkKeymap *keymap = gdk_keymap_get_for_display(display); - if (!keymap) { - printf("ERROR: Can't get keymap\n"); - gdk_display_close(display); - return 2; - } - - for (int keycode = 10; keycode <= 61; keycode++) { - printf("-------------------\n"); - printf("Keycode %d:\n", keycode); - PrintKeymapForCode(keymap, keycode); - } - - gdk_display_close(display); - - return 0; -} diff --git a/linux/mcompile/keymap/mc_kmxfile.cpp b/linux/mcompile/keymap/mc_kmxfile.cpp deleted file mode 100644 index e0a20c34ac7..00000000000 --- a/linux/mcompile/keymap/mc_kmxfile.cpp +++ /dev/null @@ -1,297 +0,0 @@ - -#include "mc_kmxfile.h" - -KMX_DWORD TEST2; - -static KMX_BOOL LoadKeyboardFile(LPKMX_STR fileName, LPKEYBOARD *lpKeyboard); - -KMX_BOOL VerifyKeyboard(LPKMX_BYTE filebase, KMX_DWORD sz); - -LPKEYBOARD FixupKeyboard(PKMX_BYTE bufp, PKMX_BYTE base, KMX_DWORD dwFileSize); - -/*void Err(wchar_t *s) { - LogError(L"LoadKeyboard: %s, last error = %d\n", s, GetLastError()); -}*/ -/*BOOL LoadKeyboard(LPWSTR fileName, LPKEYBOARD *lpKeyboard) { - DWORD sz; - LPBYTE buf; - HANDLE hFile; - LPKEYBOARD kbp; - PBYTE filebase; - - if(!fileName || !lpKeyboard) { - Err(L"Bad Filename"); - return FALSE; - } - - hFile = CreateFile(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); - if(hFile == INVALID_HANDLE_VALUE) { - Err(L"Could not open file"); - return FALSE; - } - - sz = GetFileSize(hFile, NULL); - - buf = new BYTE[sz]; - - if(!buf) { - Err(L"Not allocmem"); - CloseHandle(hFile); - return FALSE; - } - - filebase = buf; - - if(!ReadFile(hFile, filebase, sz, &sz, NULL)) { - Err(L"errReadFile"); - CloseHandle(hFile); - delete[] buf; - return FALSE; - } - CloseHandle(hFile); - - if(!VerifyKeyboard(filebase, sz)) { - Err(L"errVerifyKeyboard"); - delete[] buf; - return FALSE; - } - - kbp = FixupKeyboard(buf, filebase, sz); - if(!kbp) { - Err(L"errFixupKeyboard"); - delete[] buf; - return FALSE; - } - - if(kbp->dwIdentifier != FILEID_COMPILED) { - Err(L"errNotFileID"); - delete[] buf; - return FALSE; - } - - *lpKeyboard = kbp; - return TRUE; -} -*/ - -/*PKMX_WCHART StringOffset(PKMX_BYTE base, KMX_DWORD offset) { - if(offset == 0) return NULL; - return (PKMX_WCHART)(base + offset); -}*/ - - -/*LPKEYBOARD FixupKeyboard(PBYTE bufp, PBYTE base, DWORD dwFileSize) { - UNREFERENCED_PARAMETER(dwFileSize); - - DWORD i, j; - PCOMP_KEYBOARD ckbp = (PCOMP_KEYBOARD) base; - PCOMP_GROUP cgp; - PCOMP_STORE csp; - PCOMP_KEY ckp; - LPKEYBOARD kbp = (LPKEYBOARD) bufp; - LPSTORE sp; - LPGROUP gp; - LPKEY kp; - - kbp->dpStoreArray = (LPSTORE) (base + ckbp->dpStoreArray); - kbp->dpGroupArray = (LPGROUP) (base + ckbp->dpGroupArray); - - for(sp = kbp->dpStoreArray, csp = (PCOMP_STORE) sp, i = 0; i < kbp->cxStoreArray; i++, sp++, csp++) { - sp->dpName = StringOffset(base, csp->dpName); - sp->dpString = StringOffset(base, csp->dpString); - } - - for(gp = kbp->dpGroupArray, cgp = (PCOMP_GROUP) gp, i = 0; i < kbp->cxGroupArray; i++, gp++, cgp++) { - gp->dpName = StringOffset(base, cgp->dpName); - gp->dpKeyArray = (LPKEY) (base + cgp->dpKeyArray); - if(cgp->dpMatch != NULL) gp->dpMatch = (PWSTR) (base + cgp->dpMatch); - if(cgp->dpNoMatch != NULL) gp->dpNoMatch = (PWSTR) (base + cgp->dpNoMatch); - - for(kp = gp->dpKeyArray, ckp = (PCOMP_KEY) kp, j = 0; j < gp->cxKeyArray; j++, kp++, ckp++) { - kp->dpOutput = (PWSTR) (base + ckp->dpOutput); - kp->dpContext = (PWSTR) (base + ckp->dpContext); - } - } - - return kbp; -} -*/ - - -/*BOOL VerifyKeyboard(LPBYTE filebase, DWORD sz) { - DWORD i; - PCOMP_KEYBOARD ckbp = (PCOMP_KEYBOARD) filebase; - PCOMP_STORE csp; - - // Check file version // - - if(ckbp->dwFileVersion < VERSION_MIN || - ckbp->dwFileVersion > VERSION_MAX) { - // Old or new version -- identify the desired program version // - for(csp = (PCOMP_STORE)(filebase + ckbp->dpStoreArray), i = 0; i < ckbp->cxStoreArray; i++, csp++) { - if(csp->dwSystemID == TSS_COMPILEDVERSION) { - wchar_t buf2[256]; - if(csp->dpString == 0) { - wsprintf(buf2, L"errWrongFileVersion:NULL"); - } else { - wsprintf(buf2, L"errWrongFileVersion:%10.10ls", StringOffset(filebase, csp->dpString)); - } - Err(buf2); - return FALSE; - } - } - Err(L"errWrongFileVersion"); - return FALSE; - } - - - return TRUE; -}*/ - - -//---------------------old---------------------------------------- -/* -#include "pch.h" - - -static BOOL LoadKeyboardFile(LPSTR fileName, LPKEYBOARD *lpKeyboard); -BOOL VerifyKeyboard(LPBYTE filebase, DWORD sz); - -LPKEYBOARD FixupKeyboard(PBYTE bufp, PBYTE base, DWORD dwFileSize); - -void Err(wchar_t *s) { - LogError(L"LoadKeyboard: %s, last error = %d\n", s, GetLastError()); -} - -BOOL LoadKeyboard(LPWSTR fileName, LPKEYBOARD *lpKeyboard) { - DWORD sz; - LPBYTE buf; - HANDLE hFile; - LPKEYBOARD kbp; - PBYTE filebase; - - if(!fileName || !lpKeyboard) { - Err(L"Bad Filename"); - return FALSE; - } - - hFile = CreateFile(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); - if(hFile == INVALID_HANDLE_VALUE) { - Err(L"Could not open file"); - return FALSE; - } - - sz = GetFileSize(hFile, NULL); - - buf = new BYTE[sz]; - - if(!buf) { - Err(L"Not allocmem"); - CloseHandle(hFile); - return FALSE; - } - - filebase = buf; - - if(!ReadFile(hFile, filebase, sz, &sz, NULL)) { - Err(L"errReadFile"); - CloseHandle(hFile); - delete[] buf; - return FALSE; - } - CloseHandle(hFile); - - if(!VerifyKeyboard(filebase, sz)) { - Err(L"errVerifyKeyboard"); - delete[] buf; - return FALSE; - } - - kbp = FixupKeyboard(buf, filebase, sz); - if(!kbp) { - Err(L"errFixupKeyboard"); - delete[] buf; - return FALSE; - } - - if(kbp->dwIdentifier != FILEID_COMPILED) { - Err(L"errNotFileID"); - delete[] buf; - return FALSE; - } - - *lpKeyboard = kbp; - return TRUE; -} - -PWCHAR StringOffset(PBYTE base, DWORD offset) { - if(offset == 0) return NULL; - return (PWCHAR)(base + offset); -} - -LPKEYBOARD FixupKeyboard(PBYTE bufp, PBYTE base, DWORD dwFileSize) { - UNREFERENCED_PARAMETER(dwFileSize); - - DWORD i, j; - PCOMP_KEYBOARD ckbp = (PCOMP_KEYBOARD) base; - PCOMP_GROUP cgp; - PCOMP_STORE csp; - PCOMP_KEY ckp; - LPKEYBOARD kbp = (LPKEYBOARD) bufp; - LPSTORE sp; - LPGROUP gp; - LPKEY kp; - - kbp->dpStoreArray = (LPSTORE) (base + ckbp->dpStoreArray); - kbp->dpGroupArray = (LPGROUP) (base + ckbp->dpGroupArray); - - for(sp = kbp->dpStoreArray, csp = (PCOMP_STORE) sp, i = 0; i < kbp->cxStoreArray; i++, sp++, csp++) { - sp->dpName = StringOffset(base, csp->dpName); - sp->dpString = StringOffset(base, csp->dpString); - } - - for(gp = kbp->dpGroupArray, cgp = (PCOMP_GROUP) gp, i = 0; i < kbp->cxGroupArray; i++, gp++, cgp++) { - gp->dpName = StringOffset(base, cgp->dpName); - gp->dpKeyArray = (LPKEY) (base + cgp->dpKeyArray); - if(cgp->dpMatch != NULL) gp->dpMatch = (PWSTR) (base + cgp->dpMatch); - if(cgp->dpNoMatch != NULL) gp->dpNoMatch = (PWSTR) (base + cgp->dpNoMatch); - - for(kp = gp->dpKeyArray, ckp = (PCOMP_KEY) kp, j = 0; j < gp->cxKeyArray; j++, kp++, ckp++) { - kp->dpOutput = (PWSTR) (base + ckp->dpOutput); - kp->dpContext = (PWSTR) (base + ckp->dpContext); - } - } - - return kbp; -} - -BOOL VerifyKeyboard(LPBYTE filebase, DWORD sz) { - DWORD i; - PCOMP_KEYBOARD ckbp = (PCOMP_KEYBOARD) filebase; - PCOMP_STORE csp; - - // Check file version // - - if(ckbp->dwFileVersion < VERSION_MIN || - ckbp->dwFileVersion > VERSION_MAX) { - // Old or new version -- identify the desired program version // - for(csp = (PCOMP_STORE)(filebase + ckbp->dpStoreArray), i = 0; i < ckbp->cxStoreArray; i++, csp++) { - if(csp->dwSystemID == TSS_COMPILEDVERSION) { - wchar_t buf2[256]; - if(csp->dpString == 0) { - wsprintf(buf2, L"errWrongFileVersion:NULL"); - } else { - wsprintf(buf2, L"errWrongFileVersion:%10.10ls", StringOffset(filebase, csp->dpString)); - } - Err(buf2); - return FALSE; - } - } - Err(L"errWrongFileVersion"); - return FALSE; - } - - - return TRUE; -} -*/ \ No newline at end of file diff --git a/linux/mcompile/keymap/mc_kmxfile.h b/linux/mcompile/keymap/mc_kmxfile.h deleted file mode 100644 index 2d82db90b1e..00000000000 --- a/linux/mcompile/keymap/mc_kmxfile.h +++ /dev/null @@ -1,147 +0,0 @@ -#pragma once -#include "km_types.h" - -KMX_DWORD TEST; - -#ifndef _KMXFILE_H -#define _KMXFILE_H - -typedef struct tagSTORE { - KMX_DWORD dwSystemID; - PKMX_WCHART dpName; - PKMX_WCHART dpString; -} STORE, *LPSTORE; - - -typedef struct tagKEY { - KMX_WCHAR Key; - KMX_DWORD Line; - KMX_DWORD ShiftFlags; - PKMX_WCHART dpOutput; - PKMX_WCHART dpContext; -} KEY, *LPKEY; - - -typedef struct tagGROUP { - PKMX_WCHART dpName; - LPKEY dpKeyArray; // [LPKEY] address of first item in key array - PKMX_WCHART dpMatch; - PKMX_WCHART dpNoMatch; - KMX_DWORD cxKeyArray; // in array entries - KMX_BOOL fUsingKeys; // group(xx) [using keys] <-- specified or not -} GROUP, *LPGROUP; - - - -typedef struct tagKEYBOARD { - KMX_DWORD dwIdentifier; // Keyman compiled keyboard id - - KMX_DWORD dwFileVersion; // Version of the file - Keyman 4.0 is 0x0400 - - KMX_DWORD dwCheckSum; // As stored in keyboard. DEPRECATED as of 16.0 - KMX_DWORD xxkbdlayout; // as stored in HKEY_LOCAL_MACHINE//system//currentcontrolset//control//keyboard layouts - KMX_DWORD IsRegistered; // layout id, from same registry key - KMX_DWORD version; // keyboard version - - KMX_DWORD cxStoreArray; // in array entries - KMX_DWORD cxGroupArray; // in array entries - - LPSTORE dpStoreArray; // [LPSTORE] address of first item in store array, from start of file - LPGROUP dpGroupArray; // [LPGROUP] address of first item in group array, from start of file - - KMX_DWORD StartGroup[2]; // index of starting groups [2 of them] - // Ansi=0, Unicode=1 - - KMX_DWORD dwFlags; // Flags for the keyboard file - - KMX_DWORD dwHotKey; // standard windows hotkey (hiword=shift/ctrl/alt stuff, loword=vkey) - - //PKMX_WCHART dpName; // offset of name - //PKMX_WCHART dpLanguageName; // offset of language name; - //PKMX_WCHART dpCopyright; // offset of copyright - //PKMX_WCHART dpMessage; // offset of message in Keyboard About box - - KMX_DWORD dpBitmapOffset; // 0038 offset of the bitmaps in the file - KMX_DWORD dwBitmapSize; // 003C size in bytes of the bitmaps - //HBITMAP hBitmap; // handle to the bitmap in the file; -} KEYBOARD, *LPKEYBOARD; - -KMX_BOOL LoadKeyboard(LPKMX_WCHART fileName, LPKEYBOARD *lpKeyboard); // _S2 LPKEYBOARD ok to leave as is?? - -#endif - - - - - - -//---------------------old---------------------------------------- -/* -#include - -#ifndef _KMXFILE_H -#define _KMXFILE_H - -typedef struct tagSTORE { - DWORD dwSystemID; - PWSTR dpName; - PWSTR dpString; -} STORE, *LPSTORE; - -typedef struct tagKEY { - WCHAR Key; - DWORD Line; - DWORD ShiftFlags; - PWSTR dpOutput; - PWSTR dpContext; -} KEY, *LPKEY; - - -typedef struct tagGROUP { - PWSTR dpName; - LPKEY dpKeyArray; // [LPKEY] address of first item in key array - PWSTR dpMatch; - PWSTR dpNoMatch; - DWORD cxKeyArray; // in array entries - BOOL fUsingKeys; // group(xx) [using keys] <-- specified or not -} GROUP, *LPGROUP; - - -typedef struct tagKEYBOARD { - DWORD dwIdentifier; // Keyman compiled keyboard id - - DWORD dwFileVersion; // Version of the file - Keyman 4.0 is 0x0400 - - DWORD dwCheckSum; // As stored in keyboard. DEPRECATED as of 16.0 - DWORD xxkbdlayout; // as stored in HKEY_LOCAL_MACHINE//system//currentcontrolset//control//keyboard layouts - DWORD IsRegistered; // layout id, from same registry key - DWORD version; // keyboard version - - DWORD cxStoreArray; // in array entries - DWORD cxGroupArray; // in array entries - - LPSTORE dpStoreArray; // [LPSTORE] address of first item in store array, from start of file - LPGROUP dpGroupArray; // [LPGROUP] address of first item in group array, from start of file - - DWORD StartGroup[2]; // index of starting groups [2 of them] - // Ansi=0, Unicode=1 - - DWORD dwFlags; // Flags for the keyboard file - - DWORD dwHotKey; // standard windows hotkey (hiword=shift/ctrl/alt stuff, loword=vkey) - - //PWSTR dpName; // offset of name - //PWSTR dpLanguageName; // offset of language name; - //PWSTR dpCopyright; // offset of copyright - //PWSTR dpMessage; // offset of message in Keyboard About box - - DWORD dpBitmapOffset; // 0038 offset of the bitmaps in the file - DWORD dwBitmapSize; // 003C size in bytes of the bitmaps - //HBITMAP hBitmap; // handle to the bitmap in the file; -} KEYBOARD, *LPKEYBOARD; - -BOOL LoadKeyboard(LPWSTR fileName, LPKEYBOARD *lpKeyboard); - -#endif -*/ - diff --git a/linux/mcompile/keymap/mc_savekeyboard.cpp b/linux/mcompile/keymap/mc_savekeyboard.cpp deleted file mode 100644 index 497f2d4379d..00000000000 --- a/linux/mcompile/keymap/mc_savekeyboard.cpp +++ /dev/null @@ -1,423 +0,0 @@ -#include "mc_savekeyboard.h" - - -/*BOOL SaveKeyboard(LPKEYBOARD kbd, PWSTR filename) { - HANDLE hOutfile = CreateFile(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL); - if(hOutfile == INVALID_HANDLE_VALUE) { - LogError(L"Failed to create output file (%d)", GetLastError()); - return FALSE; - } - - DWORD err = WriteCompiledKeyboard(kbd, hOutfile, FALSE); - - CloseHandle(hOutfile); - - if(err != CERR_None) { - LogError(L"Failed to write compiled keyboard with error %d", err); - DeleteFile(filename); - return FALSE; - } - - return TRUE; -}*/ - -/*DWORD WriteCompiledKeyboard(LPKEYBOARD fk, HANDLE hOutfile, BOOL FSaveDebug) -{ - LPGROUP fgp; - LPSTORE fsp; - LPKEY fkp; - - PCOMP_KEYBOARD ck; - PCOMP_GROUP gp; - PCOMP_STORE sp; - PCOMP_KEY kp; - PBYTE buf; - DWORD size, offset; - DWORD i, j; - - // Calculate how much memory to allocate - - size = sizeof(COMP_KEYBOARD) + - fk->cxGroupArray * sizeof(COMP_GROUP) + - fk->cxStoreArray * sizeof(COMP_STORE) + - //wcslen(fk->szName)*2 + 2 + - //wcslen(fk->szCopyright)*2 + 2 + - //wcslen(fk->szLanguageName)*2 + 2 + - //wcslen(fk->szMessage)*2 + 2 + - fk->dwBitmapSize; - - for(i = 0, fgp = fk->dpGroupArray; i < fk->cxGroupArray; i++, fgp++) { - if(fgp->dpName) - size += wcslen(fgp->dpName)*2 + 2; - size += fgp->cxKeyArray * sizeof(COMP_KEY); - for(j = 0, fkp = fgp->dpKeyArray; j < fgp->cxKeyArray; j++, fkp++) { - size += wcslen(fkp->dpOutput)*2 + 2; - size += wcslen(fkp->dpContext)*2 + 2; - } - - if( fgp->dpMatch ) size += wcslen(fgp->dpMatch)*2 + 2; - if( fgp->dpNoMatch ) size += wcslen(fgp->dpNoMatch)*2 + 2; - } - - for(i = 0; i < fk->cxStoreArray; i++) - { - size += wcslen(fk->dpStoreArray[i].dpString)*2 + 2; - if(fk->dpStoreArray[i].dpName) - size += wcslen(fk->dpStoreArray[i].dpName)*2 + 2; - } - - buf = new BYTE[size]; - if(!buf) return CERR_CannotAllocateMemory; - memset(buf, 0, size); - - ck = (PCOMP_KEYBOARD) buf; - - ck->dwIdentifier = FILEID_COMPILED; - - ck->dwFileVersion = fk->dwFileVersion; - ck->dwCheckSum = 0; // No checksum in 16.0, see #7276 - ck->KeyboardID = fk->xxkbdlayout; - ck->IsRegistered = fk->IsRegistered; - ck->cxStoreArray = fk->cxStoreArray; - ck->cxGroupArray = fk->cxGroupArray; - ck->StartGroup[0] = fk->StartGroup[0]; - ck->StartGroup[1] = fk->StartGroup[1]; - ck->dwHotKey = fk->dwHotKey; - - ck->dwFlags = fk->dwFlags; - - offset = sizeof(COMP_KEYBOARD); - - //ck->dpLanguageName = offset; - //wcscpy((PWSTR)(buf + offset), fk->szLanguageName); - //offset += wcslen(fk->szLanguageName)*2 + 2; - - //ck->dpName = offset; - //wcscpy((PWSTR)(buf + offset), fk->szName); - //offset += wcslen(fk->szName)*2 + 2; - - //ck->dpCopyright = offset; - //wcscpy((PWSTR)(buf + offset), fk->szCopyright); - //offset += wcslen(fk->szCopyright)*2 + 2; - - //ck->dpMessage = offset; - //wcscpy((PWSTR)(buf + offset), fk->szMessage); - //offset += wcslen(fk->szMessage)*2 + 2; - - ck->dpStoreArray = offset; - sp = (PCOMP_STORE)(buf+offset); - fsp = fk->dpStoreArray; - offset += sizeof(COMP_STORE) * ck->cxStoreArray; - for(i = 0; i < ck->cxStoreArray; i++, sp++, fsp++) { - sp->dwSystemID = fsp->dwSystemID; - sp->dpString = offset; - wcscpy_s((PWSTR)(buf+offset), (size-offset) / sizeof(WCHAR), fsp->dpString); // I3481 // I3641 - offset += wcslen(fsp->dpString)*2 + 2; - - if(!fsp->dpName) { - sp->dpName = 0; - } else { - sp->dpName = offset; - wcscpy_s((PWSTR)(buf+offset), (size-offset) / sizeof(WCHAR), fsp->dpName); // I3481 // I3641 - offset += wcslen(fsp->dpName)*2 + 2; - } - } - - ck->dpGroupArray = offset; - gp = (PCOMP_GROUP)(buf+offset); - fgp = fk->dpGroupArray; - - offset += sizeof(COMP_GROUP) * ck->cxGroupArray; - - for(i = 0; i < ck->cxGroupArray; i++, gp++, fgp++) { - gp->cxKeyArray = fgp->cxKeyArray; - gp->fUsingKeys = fgp->fUsingKeys; - - gp->dpMatch = gp->dpNoMatch = 0; - - if(fgp->dpMatch) { - gp->dpMatch = offset; - wcscpy_s((PWSTR)(buf+offset), (size-offset) / sizeof(WCHAR), fgp->dpMatch); // I3481 // I3641 - offset += wcslen(fgp->dpMatch)*2 + 2; - } - if(fgp->dpNoMatch) { - gp->dpNoMatch = offset; - wcscpy_s((PWSTR)(buf+offset), (size-offset) / sizeof(WCHAR), fgp->dpNoMatch); // I3481 // I3641 - offset += wcslen(fgp->dpNoMatch)*2 + 2; - } - - if(fgp->dpName) { - gp->dpName = offset; - wcscpy_s((PWSTR)(buf+offset), (size-offset) / sizeof(WCHAR), fgp->dpName); // I3481 // I3641 - offset += wcslen(fgp->dpName)*2 + 2; - } else { - gp->dpName = 0; - } - - gp->dpKeyArray = offset; - kp = (PCOMP_KEY) (buf + offset); - fkp = fgp->dpKeyArray; - offset += gp->cxKeyArray * sizeof(COMP_KEY); - for(j = 0; j < gp->cxKeyArray; j++, kp++, fkp++) { - kp->Key = fkp->Key; - kp->Line = fkp->Line; - kp->ShiftFlags = fkp->ShiftFlags; - kp->dpOutput = offset; - wcscpy_s((PWSTR)(buf+offset), (size-offset) / sizeof(WCHAR), fkp->dpOutput); // I3481 // I3641 - offset += wcslen(fkp->dpOutput)*2 + 2; - - - kp->dpContext = offset; - wcscpy_s((PWSTR)(buf+offset), (size-offset) / sizeof(WCHAR), fkp->dpContext); // I3481 // I3641 - offset += wcslen(fkp->dpContext)*2 + 2; - } - } - - if(fk->dwBitmapSize > 0) { - ck->dwBitmapSize = fk->dwBitmapSize; - ck->dpBitmapOffset = offset; - memcpy(buf + offset, ((PBYTE)fk) + fk->dpBitmapOffset, fk->dwBitmapSize); - offset += fk->dwBitmapSize; - } else { - ck->dwBitmapSize = 0; - ck->dpBitmapOffset = 0; - } - - if(offset != size) - { - delete[] buf; - return CERR_SomewhereIGotItWrong; - } - - WriteFile(hOutfile, buf, size, &offset, NULL); - - if(offset != size) - { - delete[] buf; - return CERR_UnableToWriteFully; - } - - delete[] buf; - - return CERR_None; -}*/ - - - - -//---------------------old---------------------------------------- -/*#include "pch.h" - -// These four errors are copied from kmn_compiler_errors.h, because WriteCompiledKeyboard is -// a clone of the compiler's equivalent function. However, the functions -// diverge, as mc_savekeyboard.cpp's version is copying from an existing -// compiled keyboard. The error codes have been kept consistent with those in -// kmn_compiler_errors.h -#define CERR_None 0x00000000 -#define CERR_CannotAllocateMemory 0x00008004 -#define CERR_UnableToWriteFully 0x00008007 -#define CERR_SomewhereIGotItWrong 0x00008009 - -DWORD WriteCompiledKeyboard(LPKEYBOARD fk, HANDLE hOutfile, BOOL FSaveDebug); - -BOOL SaveKeyboard(LPKEYBOARD kbd, PWSTR filename) { - HANDLE hOutfile = CreateFile(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL); - if(hOutfile == INVALID_HANDLE_VALUE) { - LogError(L"Failed to create output file (%d)", GetLastError()); - return FALSE; - } - - DWORD err = WriteCompiledKeyboard(kbd, hOutfile, FALSE); - - CloseHandle(hOutfile); - - if(err != CERR_None) { - LogError(L"Failed to write compiled keyboard with error %d", err); - DeleteFile(filename); - return FALSE; - } - - return TRUE; -} - -DWORD WriteCompiledKeyboard(LPKEYBOARD fk, HANDLE hOutfile, BOOL FSaveDebug) -{ - LPGROUP fgp; - LPSTORE fsp; - LPKEY fkp; - - PCOMP_KEYBOARD ck; - PCOMP_GROUP gp; - PCOMP_STORE sp; - PCOMP_KEY kp; - PBYTE buf; - DWORD size, offset; - DWORD i, j; - - // Calculate how much memory to allocate - - size = sizeof(COMP_KEYBOARD) + - fk->cxGroupArray * sizeof(COMP_GROUP) + - fk->cxStoreArray * sizeof(COMP_STORE) + - //wcslen(fk->szName)*2 + 2 + - //wcslen(fk->szCopyright)*2 + 2 + - //wcslen(fk->szLanguageName)*2 + 2 + - //wcslen(fk->szMessage)*2 + 2 + - fk->dwBitmapSize; - - for(i = 0, fgp = fk->dpGroupArray; i < fk->cxGroupArray; i++, fgp++) { - if(fgp->dpName) - size += wcslen(fgp->dpName)*2 + 2; - size += fgp->cxKeyArray * sizeof(COMP_KEY); - for(j = 0, fkp = fgp->dpKeyArray; j < fgp->cxKeyArray; j++, fkp++) { - size += wcslen(fkp->dpOutput)*2 + 2; - size += wcslen(fkp->dpContext)*2 + 2; - } - - if( fgp->dpMatch ) size += wcslen(fgp->dpMatch)*2 + 2; - if( fgp->dpNoMatch ) size += wcslen(fgp->dpNoMatch)*2 + 2; - } - - for(i = 0; i < fk->cxStoreArray; i++) - { - size += wcslen(fk->dpStoreArray[i].dpString)*2 + 2; - if(fk->dpStoreArray[i].dpName) - size += wcslen(fk->dpStoreArray[i].dpName)*2 + 2; - } - - buf = new BYTE[size]; - if(!buf) return CERR_CannotAllocateMemory; - memset(buf, 0, size); - - ck = (PCOMP_KEYBOARD) buf; - - ck->dwIdentifier = FILEID_COMPILED; - - ck->dwFileVersion = fk->dwFileVersion; - ck->dwCheckSum = 0; // No checksum in 16.0, see #7276 - ck->KeyboardID = fk->xxkbdlayout; - ck->IsRegistered = fk->IsRegistered; - ck->cxStoreArray = fk->cxStoreArray; - ck->cxGroupArray = fk->cxGroupArray; - ck->StartGroup[0] = fk->StartGroup[0]; - ck->StartGroup[1] = fk->StartGroup[1]; - ck->dwHotKey = fk->dwHotKey; - - ck->dwFlags = fk->dwFlags; - - offset = sizeof(COMP_KEYBOARD); - - //ck->dpLanguageName = offset; - //wcscpy((PWSTR)(buf + offset), fk->szLanguageName); - //offset += wcslen(fk->szLanguageName)*2 + 2; - - //ck->dpName = offset; - //wcscpy((PWSTR)(buf + offset), fk->szName); - //offset += wcslen(fk->szName)*2 + 2; - - //ck->dpCopyright = offset; - //wcscpy((PWSTR)(buf + offset), fk->szCopyright); - //offset += wcslen(fk->szCopyright)*2 + 2; - - //ck->dpMessage = offset; - //wcscpy((PWSTR)(buf + offset), fk->szMessage); - //offset += wcslen(fk->szMessage)*2 + 2; - - ck->dpStoreArray = offset; - sp = (PCOMP_STORE)(buf+offset); - fsp = fk->dpStoreArray; - offset += sizeof(COMP_STORE) * ck->cxStoreArray; - for(i = 0; i < ck->cxStoreArray; i++, sp++, fsp++) { - sp->dwSystemID = fsp->dwSystemID; - sp->dpString = offset; - wcscpy_s((PWSTR)(buf+offset), (size-offset) / sizeof(WCHAR), fsp->dpString); // I3481 // I3641 - offset += wcslen(fsp->dpString)*2 + 2; - - if(!fsp->dpName) { - sp->dpName = 0; - } else { - sp->dpName = offset; - wcscpy_s((PWSTR)(buf+offset), (size-offset) / sizeof(WCHAR), fsp->dpName); // I3481 // I3641 - offset += wcslen(fsp->dpName)*2 + 2; - } - } - - ck->dpGroupArray = offset; - gp = (PCOMP_GROUP)(buf+offset); - fgp = fk->dpGroupArray; - - offset += sizeof(COMP_GROUP) * ck->cxGroupArray; - - for(i = 0; i < ck->cxGroupArray; i++, gp++, fgp++) { - gp->cxKeyArray = fgp->cxKeyArray; - gp->fUsingKeys = fgp->fUsingKeys; - - gp->dpMatch = gp->dpNoMatch = 0; - - if(fgp->dpMatch) { - gp->dpMatch = offset; - wcscpy_s((PWSTR)(buf+offset), (size-offset) / sizeof(WCHAR), fgp->dpMatch); // I3481 // I3641 - offset += wcslen(fgp->dpMatch)*2 + 2; - } - if(fgp->dpNoMatch) { - gp->dpNoMatch = offset; - wcscpy_s((PWSTR)(buf+offset), (size-offset) / sizeof(WCHAR), fgp->dpNoMatch); // I3481 // I3641 - offset += wcslen(fgp->dpNoMatch)*2 + 2; - } - - if(fgp->dpName) { - gp->dpName = offset; - wcscpy_s((PWSTR)(buf+offset), (size-offset) / sizeof(WCHAR), fgp->dpName); // I3481 // I3641 - offset += wcslen(fgp->dpName)*2 + 2; - } else { - gp->dpName = 0; - } - - gp->dpKeyArray = offset; - kp = (PCOMP_KEY) (buf + offset); - fkp = fgp->dpKeyArray; - offset += gp->cxKeyArray * sizeof(COMP_KEY); - for(j = 0; j < gp->cxKeyArray; j++, kp++, fkp++) { - kp->Key = fkp->Key; - kp->Line = fkp->Line; - kp->ShiftFlags = fkp->ShiftFlags; - kp->dpOutput = offset; - wcscpy_s((PWSTR)(buf+offset), (size-offset) / sizeof(WCHAR), fkp->dpOutput); // I3481 // I3641 - offset += wcslen(fkp->dpOutput)*2 + 2; - - - kp->dpContext = offset; - wcscpy_s((PWSTR)(buf+offset), (size-offset) / sizeof(WCHAR), fkp->dpContext); // I3481 // I3641 - offset += wcslen(fkp->dpContext)*2 + 2; - } - } - - if(fk->dwBitmapSize > 0) { - ck->dwBitmapSize = fk->dwBitmapSize; - ck->dpBitmapOffset = offset; - memcpy(buf + offset, ((PBYTE)fk) + fk->dpBitmapOffset, fk->dwBitmapSize); - offset += fk->dwBitmapSize; - } else { - ck->dwBitmapSize = 0; - ck->dpBitmapOffset = 0; - } - - if(offset != size) - { - delete[] buf; - return CERR_SomewhereIGotItWrong; - } - - WriteFile(hOutfile, buf, size, &offset, NULL); - - if(offset != size) - { - delete[] buf; - return CERR_UnableToWriteFully; - } - - delete[] buf; - - return CERR_None; -} -*/ \ No newline at end of file diff --git a/linux/mcompile/keymap/mc_savekeyboard.h b/linux/mcompile/keymap/mc_savekeyboard.h deleted file mode 100644 index 7ac15f4ff1a..00000000000 --- a/linux/mcompile/keymap/mc_savekeyboard.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include "km_types.h" -KMX_DWORD TEST3; -// this file is all new _S2 - -//#include "../../../common/include/km_types.h" - - -#define CERR_None 0x00000000 -#define CERR_CannotAllocateMemory 0x00008004 -#define CERR_UnableToWriteFully 0x00008007 -#define CERR_SomewhereIGotItWrong 0x00008009 -/* -DWORD WriteCompiledKeyboard(LPKEYBOARD fk, HANDLE hOutfile, BOOL FSaveDebug); -BOOL SaveKeyboard(LPKEYBOARD kbd, PWSTR filename) ; -DWORD WriteCompiledKeyboard(LPKEYBOARD fk, HANDLE hOutfile, BOOL FSaveDebug); -*/ \ No newline at end of file diff --git a/linux/mcompile/keymap/mcompile.cpp b/linux/mcompile/keymap/mcompile.cpp deleted file mode 100644 index b990f02806c..00000000000 --- a/linux/mcompile/keymap/mcompile.cpp +++ /dev/null @@ -1,924 +0,0 @@ -/* - Name: mcompile - Copyright: Copyright (C) SIL International. - Documentation: - Description: - Create Date: 24 Apr 2014 - - Modified Date: 8 Apr 2015 - Authors: mcdurdin - Related Files: - Dependencies: - - Bugs: - Todo: - Notes: - History: 24 Apr 2014 - mcdurdin - I4174 - V9 - mcompile logs should be stored in diag folder - 16 Jun 2014 - mcdurdin - I4273 - V9.0 - Convert keyboards to Unicode before installing - 23 Jun 2014 - mcdurdin - I4279 - V9.0 - mcompile fails to start when converting keyboard to Unicode - 03 Aug 2014 - mcdurdin - I4353 - V9.0 - mnemonic layout recompiler mixes up deadkey rules - 03 Aug 2014 - mcdurdin - I4327 - V9.0 - Mnemonic layout compiler follow-up - 31 Dec 2014 - mcdurdin - I4549 - V9.0 - Mnemonic layout recompiler does not translate Lctrl Ralt for deadkeys correctly - 06 Feb 2015 - mcdurdin - I4552 - V9.0 - Add mnemonic recompile option to ignore deadkeys - 08 Apr 2015 - mcdurdin - I4651 - V9.0 - Mnemonic layout recompiler maps AltGr+VK_BKSLASH rather than VK_OEM_102 -*/ -// -// m-to-p.cpp : Defines the entry point for the console application. -// -// Note: this program deliberately leaks memory as it has a very short life cycle and managing the memory allocations -// for the subcomponents of the compiled keyboard is an unnecessary optimisation. Just so you know. -// - -#include "pch.h" -#include - -#include -#include -#include - -BOOL DoConvert(LPKEYBOARD kbd, PWSTR kbid, BOOL bDeadkeyConversion); -BOOL SaveKeyboard(LPKEYBOARD kbd, PWSTR filename); -bool ImportRules(WCHAR *kbid, LPKEYBOARD kp, std::vector *FDeadkeys, BOOL bDeadkeyConversion); // I4353 // I4327 -BOOL ConvertKeyboardToUnicode(LPKEYBOARD kbd); // I4273 -int run(int argc, wchar_t * argv[]); - -std::vector FDeadkeys; // I4353 - -#define KEYMAN_SENTRY_LOGGER_DESKTOP_ENGINE_MCOMPILE KEYMAN_SENTRY_LOGGER_DESKTOP_ENGINE ".mcompile" - -int wmain(int argc, wchar_t * argv[]) -{ - return keyman_sentry_wmain(false, KEYMAN_SENTRY_LOGGER_DESKTOP_ENGINE_MCOMPILE, argc, argv, run); -} - -int run(int argc, wchar_t * argv[]) -{ - if(argc < 3 || (argc < 5 && wcscmp(argv[1], L"-u") != 0)) { // I4273 - printf( - "Usage: mcompile -u infile.kmx outfile.kmx\n" - " mcompile [-d] infile.kmx kbdfile.dll kbid outfile.kmx\n" - " With -u parameter, converts keyboard from ANSI to Unicode\n" - " Otherwise, mcompile converts a Keyman mnemonic layout to a\n" - " positional one based on the Windows keyboard\n" - " layout file given by kbdfile.dll\n\n" - " kbid should be a hexadecimal number e.g. 409 for US English\n" - " -d convert deadkeys to plain keys\n"); // I4552 - - return 1; - } - - if(wcscmp(argv[1], L"-u") == 0) { // I4273 - wchar_t *infile = argv[2], *outfile = argv[3]; - - LPKEYBOARD kmxfile; - - if(!LoadKeyboard(infile, &kmxfile)) { - LogError(L"Failed to load keyboard (%d)", GetLastError()); - return 3; - } - - if(ConvertKeyboardToUnicode(kmxfile)) { - SaveKeyboard(kmxfile, outfile); - } - - //DeleteReallocatedPointers(kmxfile); :TODO - delete[] kmxfile; - - return 0; // I4279 - } - - int bDeadkeyConversion = wcscmp(argv[1], L"-d") == 0; // I4552 - int n = (bDeadkeyConversion ? 2 : 1); - - wchar_t *infile = argv[n], *indll = argv[n+1], *kbid = argv[n+2], *outfile = argv[n+3]; - - wprintf(L"mcompile%ls \"%ls\" \"%ls\" \"%ls\" \"%ls\"\n", bDeadkeyConversion ? L" -d":L"", infile, indll, kbid, outfile); // I4174 - - // 1. Load the keyman keyboard file - - // 2. For each key on the system layout, determine its output character and perform a - // 1-1 replacement on the keyman keyboard of that character with the base VK + shift - // state. This fixup will transform the char to a vk, which will avoid any issues - // with the key. - // - // --> deadkeys we will attack after the POC - // - // For each deadkey, we need to determine its possible outputs. Then we generate a VK - // rule for that deadkey, e.g. [K_LBRKT] > dk(c101) - // - // Next, update each rule that references the output from that deadkey to add an extra - // context deadkey at the end of the context match, e.g. 'a' dk(c101) + [K_SPACE] > 'b'. - // This will require a memory layout change for the .kmx file, plus fixups on the - // context+output index offsets - // - // --> virtual character keys - // - // [CTRL ' '] : we look at the character, and replace it in the same way, but merely - // switch the shift state from the VIRTUALCHARKEY to VIRTUALKEY, without changing any - // other properties of the key. - // - - // 3. Write the new keyman keyboard file - - if(!LoadNewLibrary(indll)) { - LogError(L"Failed to load keyboard DLL (%d)", GetLastError()); - return 2; - } - - LPKEYBOARD kmxfile; - - if(!LoadKeyboard(infile, &kmxfile)) { - LogError(L"Failed to load keyboard (%d)", GetLastError()); - return 3; - } - - if(DoConvert(kmxfile, kbid, bDeadkeyConversion)) { // I4552 - SaveKeyboard(kmxfile, outfile); - } - - //DeleteReallocatedPointers(kmxfile); :TODO - delete kmxfile; - - return 0; -} - - -// -// Map of all US English virtual key codes that we can translate -// -const WORD VKMap[] = { - 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z', - '0','1','2','3','4','5','6','7','8','9', - VK_SPACE, - VK_ACCENT, VK_HYPHEN, VK_EQUAL, - VK_LBRKT, VK_RBRKT, VK_BKSLASH, - VK_COLON, VK_QUOTE, - VK_COMMA, VK_PERIOD, VK_SLASH, - VK_xDF, VK_OEM_102, - 0 -}; - - -// -// Map of all shift states that we will work with -// -const UINT VKShiftState[] = {0, K_SHIFTFLAG, LCTRLFLAG|RALTFLAG, K_SHIFTFLAG|LCTRLFLAG|RALTFLAG, 0xFFFF}; - -// -// TranslateKey -// -// For each key rule on the keyboard, remap its key to the -// correct shift state and key. Adjust the LCTRL+RALT -> RALT if necessary -// -void TranslateKey(LPKEY key, WORD vk, UINT shift, WCHAR ch) { - - // The weird LCTRL+RALT is Windows' way of mapping the AltGr key. - // We store that as just RALT, and use the option "Simulate RAlt with Ctrl+Alt" - // to provide an alternate.. - if((shift & (LCTRLFLAG|RALTFLAG)) == (LCTRLFLAG|RALTFLAG)) - shift &= ~LCTRLFLAG; - - if(key->ShiftFlags == 0 && key->Key == ch) { - // Key is a mnemonic key with no shift state defined. - // Remap the key according to the character on the key cap. - //LogError(L"Converted mnemonic rule on line %d, + '%c' TO + [%x K_%d]", key->Line, key->Key, shift, vk); - key->ShiftFlags = ISVIRTUALKEY | shift; - key->Key = vk; - } else if(key->ShiftFlags & VIRTUALCHARKEY && key->Key == ch) { - // Key is a virtual character key with a hard-coded shift state. - // Do not remap the shift state, just move the key. - // This will not result in 100% wonderful mappings as there could - // be overlap, depending on how keys are arranged on the target layout. - // But that is up to the designer. - //LogError(L"Converted mnemonic virtual char key rule on line %d, + [%x '%c'] TO + [%x K_%d]", key->Line, key->ShiftFlags, key->Key, key->ShiftFlags & ~VIRTUALCHARKEY, vk); - key->ShiftFlags &= ~VIRTUALCHARKEY; - key->Key = vk; - } -} - -void TranslateGroup(LPGROUP group, WORD vk, UINT shift, WCHAR ch) { - for(unsigned int i = 0; i < group->cxKeyArray; i++) { - TranslateKey(&group->dpKeyArray[i], vk, shift, ch); - } -} - -void TranslateKeyboard(LPKEYBOARD kbd, WORD vk, UINT shift, WCHAR ch) { - for(unsigned int i = 0; i < kbd->cxGroupArray; i++) { - if(kbd->dpGroupArray[i].fUsingKeys) { - TranslateGroup(&kbd->dpGroupArray[i], vk, shift, ch); - } - } -} - -void ReportUnconvertedKeyRule(LPKEY key) { - if(key->ShiftFlags == 0) { - LogError(L"Did not find a match for mnemonic rule on line %d, + '%c' > ...", key->Line, key->Key); - } else if(key->ShiftFlags & VIRTUALCHARKEY) { - LogError(L"Did not find a match for mnemonic virtual character key rule on line %d, + [%x '%c'] > ...", key->Line, key->ShiftFlags, key->Key); - } -} - -void ReportUnconvertedGroupRules(LPGROUP group) { - for(unsigned int i = 0; i < group->cxKeyArray; i++) { - ReportUnconvertedKeyRule(&group->dpKeyArray[i]); - } -} - -void ReportUnconvertedKeyboardRules(LPKEYBOARD kbd) { - for(unsigned int i = 0; i < kbd->cxGroupArray; i++) { - if(kbd->dpGroupArray[i].fUsingKeys) { - ReportUnconvertedGroupRules(&kbd->dpGroupArray[i]); - } - } -} - -void TranslateDeadkeyKey(LPKEY key, WCHAR deadkey, WORD vk, UINT shift, WORD ch) { - if((key->ShiftFlags == 0 || key->ShiftFlags & VIRTUALCHARKEY) && key->Key == ch) { - - // The weird LCTRL+RALT is Windows' way of mapping the AltGr key. - // We store that as just RALT, and use the option "Simulate RAlt with Ctrl+Alt" - // to provide an alternate.. - if((shift & (LCTRLFLAG|RALTFLAG)) == (LCTRLFLAG|RALTFLAG)) // I4327 - shift &= ~LCTRLFLAG; - - if(key->ShiftFlags == 0) { - //LogError("Converted mnemonic rule on line %d, + '%c' TO dk(%d) + [%x K_%d]", key->Line, key->Key, deadkey, shift, vk); - key->ShiftFlags = ISVIRTUALKEY | shift; - } else { - //LogError("Converted mnemonic virtual char key rule on line %d, + [%x '%c'] TO dk(%d) + [%x K_%d]", key->Line, key->ShiftFlags, key->Key, deadkey, key->ShiftFlags & ~VIRTUALCHARKEY, vk); - key->ShiftFlags &= ~VIRTUALCHARKEY; - } - - int len = wcslen(key->dpContext); - PWSTR context = new WCHAR[len + 4]; - memcpy(context, key->dpContext, len * sizeof(WCHAR)); - context[len] = UC_SENTINEL; - context[len+1] = CODE_DEADKEY; - context[len+2] = deadkey; - context[len+3] = 0; - key->dpContext = context; - key->Key = vk; - } -} - -void TranslateDeadkeyGroup(LPGROUP group, WCHAR deadkey, WORD vk, UINT shift, WORD ch) { - for(unsigned int i = 0; i < group->cxKeyArray; i++) { - TranslateDeadkeyKey(&group->dpKeyArray[i], deadkey, vk, shift, ch); - } -} - -void TranslateDeadkeyKeyboard(LPKEYBOARD kbd, WCHAR deadkey, WORD vk, UINT shift, WORD ch) { - for(unsigned int i = 0; i < kbd->cxGroupArray; i++) { - if(kbd->dpGroupArray[i].fUsingKeys) { - TranslateDeadkeyGroup(&kbd->dpGroupArray[i], deadkey, vk, shift, ch); - } - } -} - -void AddDeadkeyRule(LPKEYBOARD kbd, WCHAR deadkey, WORD vk, UINT shift) { - // The weird LCTRL+RALT is Windows' way of mapping the AltGr key. - // We store that as just RALT, and use the option "Simulate RAlt with Ctrl+Alt" - // to provide an alternate.. - if((shift & (LCTRLFLAG|RALTFLAG)) == (LCTRLFLAG|RALTFLAG)) // I4549 - shift &= ~LCTRLFLAG; - - // If the first group is not a matching-keys group, then we need to add into - // each subgroup, otherwise just the match group - for(unsigned int i = 0; i < kbd->cxGroupArray; i++) { - if(kbd->dpGroupArray[i].fUsingKeys) { - LPKEY keys = new KEY[kbd->dpGroupArray[i].cxKeyArray + 1]; - memcpy(keys+1, kbd->dpGroupArray[i].dpKeyArray, kbd->dpGroupArray[i].cxKeyArray * sizeof(KEY)); - keys[0].dpContext = new WCHAR[1]; - keys[0].dpContext[0] = 0; - keys[0].dpOutput = new WCHAR[4]; // UC_SENTINEL, CODE_DEADKEY, deadkey_value, 0 - keys[0].dpOutput[0] = UC_SENTINEL; - keys[0].dpOutput[1] = CODE_DEADKEY; - keys[0].dpOutput[2] = deadkey; // TODO: translate to unique index - keys[0].dpOutput[3] = 0; - keys[0].Key = vk; - keys[0].Line = 0; - keys[0].ShiftFlags = shift | ISVIRTUALKEY; - kbd->dpGroupArray[i].dpKeyArray = keys; - kbd->dpGroupArray[i].cxKeyArray++; - //LogError("Add deadkey rule: + [%d K_%d] > dk(%d)", shift, vk, deadkey); - if(i == kbd->StartGroup[1]) break; // If this is the initial group, that's all we need to do. - } - } -} - -WCHAR ScanXStringForMaxDeadkeyID(LPWSTR str) { - WCHAR dkid = 0; - while(str && *str) { - if(*str == UC_SENTINEL) { - switch(*(str+1)) { - case CODE_DEADKEY: - dkid = max(dkid, *(str+2)); - } - } - str = incxstr(str); - } - return dkid; -} - -struct dkidmap { - WCHAR src_deadkey, dst_deadkey; -}; - -WCHAR GetUniqueDeadkeyID(LPKEYBOARD kbd, WCHAR deadkey) { - LPGROUP gp; - LPKEY kp; - LPSTORE sp; - UINT i, j; - WCHAR dkid = 0; - static WCHAR s_next_dkid = 0; - static dkidmap *s_dkids = NULL; - static int s_ndkids = 0; - - if(!kbd) { - if(s_dkids) { - delete s_dkids; - } - s_dkids = NULL; - s_ndkids = 0; - s_next_dkid = 0; - return 0; - } - - for(int i = 0; i < s_ndkids; i++) { - if(s_dkids[i].src_deadkey == deadkey) { - return s_dkids[i].dst_deadkey; - } - } - - if(s_next_dkid != 0) { - s_dkids = (dkidmap*) realloc(s_dkids, sizeof(dkidmap) * (s_ndkids+1)); - s_dkids[s_ndkids].src_deadkey = deadkey; - return s_dkids[s_ndkids++].dst_deadkey = ++s_next_dkid; - } - - for(i = 0, gp = kbd->dpGroupArray; i < kbd->cxGroupArray; i++, gp++) { - for(j = 0, kp = gp->dpKeyArray; j < gp->cxKeyArray; j++, kp++) { - dkid = max(dkid, ScanXStringForMaxDeadkeyID(kp->dpContext)); - dkid = max(dkid, ScanXStringForMaxDeadkeyID(kp->dpOutput)); - } - dkid = max(dkid, ScanXStringForMaxDeadkeyID(gp->dpMatch)); - dkid = max(dkid, ScanXStringForMaxDeadkeyID(gp->dpNoMatch)); - } - - for(i = 0, sp = kbd->dpStoreArray; i < kbd->cxStoreArray; i++, sp++) { - dkid = max(dkid, ScanXStringForMaxDeadkeyID(sp->dpString)); - } - - s_dkids = (dkidmap*) realloc(s_dkids, sizeof(dkidmap) * (s_ndkids+1)); - s_dkids[s_ndkids].src_deadkey = deadkey; - return s_dkids[s_ndkids++].dst_deadkey = s_next_dkid = ++dkid; -} - - -void ConvertDeadkey(LPKEYBOARD kbd, WORD vk, UINT shift, WCHAR deadkey) { - WORD deadkeys[512], *pdk; - - // Lookup the deadkey table for the deadkey in the physical keyboard - // Then for each character, go through and map it through - - WCHAR dkid = GetUniqueDeadkeyID(kbd, deadkey); - - // Add the deadkey to the mapping table for use in the import rules phase - DeadkeyMapping deadkeyMapping = { deadkey, dkid, shift, vk }; // I4353 - FDeadkeys.push_back(deadkeyMapping); //dkid, vk, shift); // I4353 - - AddDeadkeyRule(kbd, dkid, vk, shift); - - GetDeadkeys(deadkey, pdk = deadkeys); // returns array of [usvk, ch_out] pairs - while(*pdk) { - // Look up the ch - UINT vkUnderlying = VKUnderlyingLayoutToVKUS(*pdk); - TranslateDeadkeyKeyboard(kbd, dkid, vkUnderlying, *(pdk+1), *(pdk+2)); - pdk+=3; - } -} - -BOOL SetKeyboardToPositional(LPKEYBOARD kbd) { - LPSTORE sp; - UINT i; - for(i = 0, sp = kbd->dpStoreArray; i < kbd->cxStoreArray; i++, sp++) { - if(sp->dwSystemID == TSS_MNEMONIC) { - if(!sp->dpString) { - LogError(L"Invalid &mnemoniclayout system store"); - return FALSE; - } - if(wcscmp(sp->dpString, L"1") != 0) { - LogError(L"Keyboard is not a mnemonic layout keyboard"); - return FALSE; - } - *sp->dpString = '0'; - return TRUE; - } - } - - LogError(L"Keyboard is not a mnemonic layout keyboard"); - return FALSE; -} - -BOOL DoConvert(LPKEYBOARD kbd, LPWSTR kbid, BOOL bDeadkeyConversion) { // I4552 - WCHAR DeadKey; - - if(!SetKeyboardToPositional(kbd)) return FALSE; - - // Go through each of the shift states - base, shift, ctrl+alt, ctrl+alt+shift, [caps vs ncaps?] - // Currently, we go in this order so the 102nd key works. But this is not ideal for keyboards without 102nd key: // I4651 - // it catches only the first key that matches a given rule, but multiple keys may match that rule. This is particularly - // evident for the 102nd key on UK, for example, where \ can be generated with VK_OEM_102 or AltGr+VK_QUOTE. - // For now, we get the least shifted version, which is hopefully adequate. - - for(int j = 0; VKShiftState[j] != 0xFFFF; j++) { // I4651 - // Go through each possible key on the keyboard - for(int i = 0; VKMap[i]; i++) { // I4651 - UINT vkUnderlying = VKUSToVKUnderlyingLayout(VKMap[i]); - - WCHAR ch = CharFromVK(vkUnderlying, VKShiftState[j], &DeadKey); - - //LogError("--- VK_%d -> VK_%d [%c] dk=%d", VKMap[i], vkUnderlying, ch == 0 ? 32 : ch, DeadKey); - - if(bDeadkeyConversion) { // I4552 - if(ch == 0xFFFF) { - ch = DeadKey; - } - } - - switch(ch) { - case 0x0000: break; - case 0xFFFF: ConvertDeadkey(kbd, VKMap[i], VKShiftState[j], DeadKey); break; - default: TranslateKeyboard(kbd, VKMap[i], VKShiftState[j], ch); - } - - // - } - } - - ReportUnconvertedKeyboardRules(kbd); - - if(!ImportRules(kbid, kbd, &FDeadkeys, bDeadkeyConversion)) { // I4353 // I4552 - return FALSE; - } - - return TRUE; -} - -void LogError(PWSTR fmt, ...) { - WCHAR fmtbuf[256]; - - va_list vars; - va_start(vars, fmt); - _vsnwprintf_s(fmtbuf, _countof(fmtbuf), _TRUNCATE, fmt, vars); // I2248 // I3547 - fmtbuf[255] = 0; - _putws(fmtbuf); -} - -//---------old------------------------------------------- -/*#include "pch.h" -#include - -#include -#include -#include - -BOOL DoConvert(LPKEYBOARD kbd, PWSTR kbid, BOOL bDeadkeyConversion); -BOOL SaveKeyboard(LPKEYBOARD kbd, PWSTR filename); -bool ImportRules(WCHAR *kbid, LPKEYBOARD kp, std::vector *FDeadkeys, BOOL bDeadkeyConversion); // I4353 // I4327 -BOOL ConvertKeyboardToUnicode(LPKEYBOARD kbd); // I4273 -int run(int argc, wchar_t * argv[]); - -std::vector FDeadkeys; // I4353 - -#define KEYMAN_SENTRY_LOGGER_DESKTOP_ENGINE_MCOMPILE KEYMAN_SENTRY_LOGGER_DESKTOP_ENGINE ".mcompile" - -int wmain(int argc, wchar_t * argv[]) -{ - return keyman_sentry_wmain(false, KEYMAN_SENTRY_LOGGER_DESKTOP_ENGINE_MCOMPILE, argc, argv, run); -} - -int run(int argc, wchar_t * argv[]) -{ - if(argc < 3 || (argc < 5 && wcscmp(argv[1], L"-u") != 0)) { // I4273 - printf( - "Usage: mcompile -u infile.kmx outfile.kmx\n" - " mcompile [-d] infile.kmx kbdfile.dll kbid outfile.kmx\n" - " With -u parameter, converts keyboard from ANSI to Unicode\n" - " Otherwise, mcompile converts a Keyman mnemonic layout to a\n" - " positional one based on the Windows keyboard\n" - " layout file given by kbdfile.dll\n\n" - " kbid should be a hexadecimal number e.g. 409 for US English\n" - " -d convert deadkeys to plain keys\n"); // I4552 - - return 1; - } - - if(wcscmp(argv[1], L"-u") == 0) { // I4273 - wchar_t *infile = argv[2], *outfile = argv[3]; - - LPKEYBOARD kmxfile; - - if(!LoadKeyboard(infile, &kmxfile)) { - LogError(L"Failed to load keyboard (%d)", GetLastError()); - return 3; - } - - if(ConvertKeyboardToUnicode(kmxfile)) { - SaveKeyboard(kmxfile, outfile); - } - - //DeleteReallocatedPointers(kmxfile); :TODO - delete[] kmxfile; - - return 0; // I4279 - } - - int bDeadkeyConversion = wcscmp(argv[1], L"-d") == 0; // I4552 - int n = (bDeadkeyConversion ? 2 : 1); - - wchar_t *infile = argv[n], *indll = argv[n+1], *kbid = argv[n+2], *outfile = argv[n+3]; - - wprintf(L"mcompile%ls \"%ls\" \"%ls\" \"%ls\" \"%ls\"\n", bDeadkeyConversion ? L" -d":L"", infile, indll, kbid, outfile); // I4174 - - // 1. Load the keyman keyboard file - - // 2. For each key on the system layout, determine its output character and perform a - // 1-1 replacement on the keyman keyboard of that character with the base VK + shift - // state. This fixup will transform the char to a vk, which will avoid any issues - // with the key. - // - // --> deadkeys we will attack after the POC - // - // For each deadkey, we need to determine its possible outputs. Then we generate a VK - // rule for that deadkey, e.g. [K_LBRKT] > dk(c101) - // - // Next, update each rule that references the output from that deadkey to add an extra - // context deadkey at the end of the context match, e.g. 'a' dk(c101) + [K_SPACE] > 'b'. - // This will require a memory layout change for the .kmx file, plus fixups on the - // context+output index offsets - // - // --> virtual character keys - // - // [CTRL ' '] : we look at the character, and replace it in the same way, but merely - // switch the shift state from the VIRTUALCHARKEY to VIRTUALKEY, without changing any - // other properties of the key. - // - - // 3. Write the new keyman keyboard file - - if(!LoadNewLibrary(indll)) { - LogError(L"Failed to load keyboard DLL (%d)", GetLastError()); - return 2; - } - - LPKEYBOARD kmxfile; - - if(!LoadKeyboard(infile, &kmxfile)) { - LogError(L"Failed to load keyboard (%d)", GetLastError()); - return 3; - } - - if(DoConvert(kmxfile, kbid, bDeadkeyConversion)) { // I4552 - SaveKeyboard(kmxfile, outfile); - } - - //DeleteReallocatedPointers(kmxfile); :TODO - delete kmxfile; - - return 0; -} - - -// -// Map of all US English virtual key codes that we can translate -// -const WORD VKMap[] = { - 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z', - '0','1','2','3','4','5','6','7','8','9', - VK_SPACE, - VK_ACCENT, VK_HYPHEN, VK_EQUAL, - VK_LBRKT, VK_RBRKT, VK_BKSLASH, - VK_COLON, VK_QUOTE, - VK_COMMA, VK_PERIOD, VK_SLASH, - VK_xDF, VK_OEM_102, - 0 -}; - - -// -// Map of all shift states that we will work with -// -const UINT VKShiftState[] = {0, K_SHIFTFLAG, LCTRLFLAG|RALTFLAG, K_SHIFTFLAG|LCTRLFLAG|RALTFLAG, 0xFFFF}; - -// -// TranslateKey -// -// For each key rule on the keyboard, remap its key to the -// correct shift state and key. Adjust the LCTRL+RALT -> RALT if necessary -// -void TranslateKey(LPKEY key, WORD vk, UINT shift, WCHAR ch) { - - // The weird LCTRL+RALT is Windows' way of mapping the AltGr key. - // We store that as just RALT, and use the option "Simulate RAlt with Ctrl+Alt" - // to provide an alternate.. - if((shift & (LCTRLFLAG|RALTFLAG)) == (LCTRLFLAG|RALTFLAG)) - shift &= ~LCTRLFLAG; - - if(key->ShiftFlags == 0 && key->Key == ch) { - // Key is a mnemonic key with no shift state defined. - // Remap the key according to the character on the key cap. - //LogError(L"Converted mnemonic rule on line %d, + '%c' TO + [%x K_%d]", key->Line, key->Key, shift, vk); - key->ShiftFlags = ISVIRTUALKEY | shift; - key->Key = vk; - } else if(key->ShiftFlags & VIRTUALCHARKEY && key->Key == ch) { - // Key is a virtual character key with a hard-coded shift state. - // Do not remap the shift state, just move the key. - // This will not result in 100% wonderful mappings as there could - // be overlap, depending on how keys are arranged on the target layout. - // But that is up to the designer. - //LogError(L"Converted mnemonic virtual char key rule on line %d, + [%x '%c'] TO + [%x K_%d]", key->Line, key->ShiftFlags, key->Key, key->ShiftFlags & ~VIRTUALCHARKEY, vk); - key->ShiftFlags &= ~VIRTUALCHARKEY; - key->Key = vk; - } -} - -void TranslateGroup(LPGROUP group, WORD vk, UINT shift, WCHAR ch) { - for(unsigned int i = 0; i < group->cxKeyArray; i++) { - TranslateKey(&group->dpKeyArray[i], vk, shift, ch); - } -} - -void TranslateKeyboard(LPKEYBOARD kbd, WORD vk, UINT shift, WCHAR ch) { - for(unsigned int i = 0; i < kbd->cxGroupArray; i++) { - if(kbd->dpGroupArray[i].fUsingKeys) { - TranslateGroup(&kbd->dpGroupArray[i], vk, shift, ch); - } - } -} - -void ReportUnconvertedKeyRule(LPKEY key) { - if(key->ShiftFlags == 0) { - LogError(L"Did not find a match for mnemonic rule on line %d, + '%c' > ...", key->Line, key->Key); - } else if(key->ShiftFlags & VIRTUALCHARKEY) { - LogError(L"Did not find a match for mnemonic virtual character key rule on line %d, + [%x '%c'] > ...", key->Line, key->ShiftFlags, key->Key); - } -} - -void ReportUnconvertedGroupRules(LPGROUP group) { - for(unsigned int i = 0; i < group->cxKeyArray; i++) { - ReportUnconvertedKeyRule(&group->dpKeyArray[i]); - } -} - -void ReportUnconvertedKeyboardRules(LPKEYBOARD kbd) { - for(unsigned int i = 0; i < kbd->cxGroupArray; i++) { - if(kbd->dpGroupArray[i].fUsingKeys) { - ReportUnconvertedGroupRules(&kbd->dpGroupArray[i]); - } - } -} - -void TranslateDeadkeyKey(LPKEY key, WCHAR deadkey, WORD vk, UINT shift, WORD ch) { - if((key->ShiftFlags == 0 || key->ShiftFlags & VIRTUALCHARKEY) && key->Key == ch) { - - // The weird LCTRL+RALT is Windows' way of mapping the AltGr key. - // We store that as just RALT, and use the option "Simulate RAlt with Ctrl+Alt" - // to provide an alternate.. - if((shift & (LCTRLFLAG|RALTFLAG)) == (LCTRLFLAG|RALTFLAG)) // I4327 - shift &= ~LCTRLFLAG; - - if(key->ShiftFlags == 0) { - //LogError("Converted mnemonic rule on line %d, + '%c' TO dk(%d) + [%x K_%d]", key->Line, key->Key, deadkey, shift, vk); - key->ShiftFlags = ISVIRTUALKEY | shift; - } else { - //LogError("Converted mnemonic virtual char key rule on line %d, + [%x '%c'] TO dk(%d) + [%x K_%d]", key->Line, key->ShiftFlags, key->Key, deadkey, key->ShiftFlags & ~VIRTUALCHARKEY, vk); - key->ShiftFlags &= ~VIRTUALCHARKEY; - } - - int len = wcslen(key->dpContext); - PWSTR context = new WCHAR[len + 4]; - memcpy(context, key->dpContext, len * sizeof(WCHAR)); - context[len] = UC_SENTINEL; - context[len+1] = CODE_DEADKEY; - context[len+2] = deadkey; - context[len+3] = 0; - key->dpContext = context; - key->Key = vk; - } -} - -void TranslateDeadkeyGroup(LPGROUP group, WCHAR deadkey, WORD vk, UINT shift, WORD ch) { - for(unsigned int i = 0; i < group->cxKeyArray; i++) { - TranslateDeadkeyKey(&group->dpKeyArray[i], deadkey, vk, shift, ch); - } -} - -void TranslateDeadkeyKeyboard(LPKEYBOARD kbd, WCHAR deadkey, WORD vk, UINT shift, WORD ch) { - for(unsigned int i = 0; i < kbd->cxGroupArray; i++) { - if(kbd->dpGroupArray[i].fUsingKeys) { - TranslateDeadkeyGroup(&kbd->dpGroupArray[i], deadkey, vk, shift, ch); - } - } -} - -void AddDeadkeyRule(LPKEYBOARD kbd, WCHAR deadkey, WORD vk, UINT shift) { - // The weird LCTRL+RALT is Windows' way of mapping the AltGr key. - // We store that as just RALT, and use the option "Simulate RAlt with Ctrl+Alt" - // to provide an alternate.. - if((shift & (LCTRLFLAG|RALTFLAG)) == (LCTRLFLAG|RALTFLAG)) // I4549 - shift &= ~LCTRLFLAG; - - // If the first group is not a matching-keys group, then we need to add into - // each subgroup, otherwise just the match group - for(unsigned int i = 0; i < kbd->cxGroupArray; i++) { - if(kbd->dpGroupArray[i].fUsingKeys) { - LPKEY keys = new KEY[kbd->dpGroupArray[i].cxKeyArray + 1]; - memcpy(keys+1, kbd->dpGroupArray[i].dpKeyArray, kbd->dpGroupArray[i].cxKeyArray * sizeof(KEY)); - keys[0].dpContext = new WCHAR[1]; - keys[0].dpContext[0] = 0; - keys[0].dpOutput = new WCHAR[4]; // UC_SENTINEL, CODE_DEADKEY, deadkey_value, 0 - keys[0].dpOutput[0] = UC_SENTINEL; - keys[0].dpOutput[1] = CODE_DEADKEY; - keys[0].dpOutput[2] = deadkey; // TODO: translate to unique index - keys[0].dpOutput[3] = 0; - keys[0].Key = vk; - keys[0].Line = 0; - keys[0].ShiftFlags = shift | ISVIRTUALKEY; - kbd->dpGroupArray[i].dpKeyArray = keys; - kbd->dpGroupArray[i].cxKeyArray++; - //LogError("Add deadkey rule: + [%d K_%d] > dk(%d)", shift, vk, deadkey); - if(i == kbd->StartGroup[1]) break; // If this is the initial group, that's all we need to do. - } - } -} - -WCHAR ScanXStringForMaxDeadkeyID(LPWSTR str) { - WCHAR dkid = 0; - while(str && *str) { - if(*str == UC_SENTINEL) { - switch(*(str+1)) { - case CODE_DEADKEY: - dkid = max(dkid, *(str+2)); - } - } - str = incxstr(str); - } - return dkid; -} - -struct dkidmap { - WCHAR src_deadkey, dst_deadkey; -}; - -WCHAR GetUniqueDeadkeyID(LPKEYBOARD kbd, WCHAR deadkey) { - LPGROUP gp; - LPKEY kp; - LPSTORE sp; - UINT i, j; - WCHAR dkid = 0; - static WCHAR s_next_dkid = 0; - static dkidmap *s_dkids = NULL; - static int s_ndkids = 0; - - if(!kbd) { - if(s_dkids) { - delete s_dkids; - } - s_dkids = NULL; - s_ndkids = 0; - s_next_dkid = 0; - return 0; - } - - for(int i = 0; i < s_ndkids; i++) { - if(s_dkids[i].src_deadkey == deadkey) { - return s_dkids[i].dst_deadkey; - } - } - - if(s_next_dkid != 0) { - s_dkids = (dkidmap*) realloc(s_dkids, sizeof(dkidmap) * (s_ndkids+1)); - s_dkids[s_ndkids].src_deadkey = deadkey; - return s_dkids[s_ndkids++].dst_deadkey = ++s_next_dkid; - } - - for(i = 0, gp = kbd->dpGroupArray; i < kbd->cxGroupArray; i++, gp++) { - for(j = 0, kp = gp->dpKeyArray; j < gp->cxKeyArray; j++, kp++) { - dkid = max(dkid, ScanXStringForMaxDeadkeyID(kp->dpContext)); - dkid = max(dkid, ScanXStringForMaxDeadkeyID(kp->dpOutput)); - } - dkid = max(dkid, ScanXStringForMaxDeadkeyID(gp->dpMatch)); - dkid = max(dkid, ScanXStringForMaxDeadkeyID(gp->dpNoMatch)); - } - - for(i = 0, sp = kbd->dpStoreArray; i < kbd->cxStoreArray; i++, sp++) { - dkid = max(dkid, ScanXStringForMaxDeadkeyID(sp->dpString)); - } - - s_dkids = (dkidmap*) realloc(s_dkids, sizeof(dkidmap) * (s_ndkids+1)); - s_dkids[s_ndkids].src_deadkey = deadkey; - return s_dkids[s_ndkids++].dst_deadkey = s_next_dkid = ++dkid; -} - - -void ConvertDeadkey(LPKEYBOARD kbd, WORD vk, UINT shift, WCHAR deadkey) { - WORD deadkeys[512], *pdk; - - // Lookup the deadkey table for the deadkey in the physical keyboard - // Then for each character, go through and map it through - - WCHAR dkid = GetUniqueDeadkeyID(kbd, deadkey); - - // Add the deadkey to the mapping table for use in the import rules phase - DeadkeyMapping deadkeyMapping = { deadkey, dkid, shift, vk }; // I4353 - FDeadkeys.push_back(deadkeyMapping); //dkid, vk, shift); // I4353 - - AddDeadkeyRule(kbd, dkid, vk, shift); - - GetDeadkeys(deadkey, pdk = deadkeys); // returns array of [usvk, ch_out] pairs - while(*pdk) { - // Look up the ch - UINT vkUnderlying = VKUnderlyingLayoutToVKUS(*pdk); - TranslateDeadkeyKeyboard(kbd, dkid, vkUnderlying, *(pdk+1), *(pdk+2)); - pdk+=3; - } -} - -BOOL SetKeyboardToPositional(LPKEYBOARD kbd) { - LPSTORE sp; - UINT i; - for(i = 0, sp = kbd->dpStoreArray; i < kbd->cxStoreArray; i++, sp++) { - if(sp->dwSystemID == TSS_MNEMONIC) { - if(!sp->dpString) { - LogError(L"Invalid &mnemoniclayout system store"); - return FALSE; - } - if(wcscmp(sp->dpString, L"1") != 0) { - LogError(L"Keyboard is not a mnemonic layout keyboard"); - return FALSE; - } - *sp->dpString = '0'; - return TRUE; - } - } - - LogError(L"Keyboard is not a mnemonic layout keyboard"); - return FALSE; -} - -BOOL DoConvert(LPKEYBOARD kbd, LPWSTR kbid, BOOL bDeadkeyConversion) { // I4552 - WCHAR DeadKey; - - if(!SetKeyboardToPositional(kbd)) return FALSE; - - // Go through each of the shift states - base, shift, ctrl+alt, ctrl+alt+shift, [caps vs ncaps?] - // Currently, we go in this order so the 102nd key works. But this is not ideal for keyboards without 102nd key: // I4651 - // it catches only the first key that matches a given rule, but multiple keys may match that rule. This is particularly - // evident for the 102nd key on UK, for example, where \ can be generated with VK_OEM_102 or AltGr+VK_QUOTE. - // For now, we get the least shifted version, which is hopefully adequate. - - for(int j = 0; VKShiftState[j] != 0xFFFF; j++) { // I4651 - // Go through each possible key on the keyboard - for(int i = 0; VKMap[i]; i++) { // I4651 - UINT vkUnderlying = VKUSToVKUnderlyingLayout(VKMap[i]); - - WCHAR ch = CharFromVK(vkUnderlying, VKShiftState[j], &DeadKey); - - //LogError("--- VK_%d -> VK_%d [%c] dk=%d", VKMap[i], vkUnderlying, ch == 0 ? 32 : ch, DeadKey); - - if(bDeadkeyConversion) { // I4552 - if(ch == 0xFFFF) { - ch = DeadKey; - } - } - - switch(ch) { - case 0x0000: break; - case 0xFFFF: ConvertDeadkey(kbd, VKMap[i], VKShiftState[j], DeadKey); break; - default: TranslateKeyboard(kbd, VKMap[i], VKShiftState[j], ch); - } - - // - } - } - - ReportUnconvertedKeyboardRules(kbd); - - if(!ImportRules(kbid, kbd, &FDeadkeys, bDeadkeyConversion)) { // I4353 // I4552 - return FALSE; - } - - return TRUE; -} - -void LogError(PWSTR fmt, ...) { - WCHAR fmtbuf[256]; - - va_list vars; - va_start(vars, fmt); - _vsnwprintf_s(fmtbuf, _countof(fmtbuf), _TRUNCATE, fmt, vars); // I2248 // I3547 - fmtbuf[255] = 0; - _putws(fmtbuf); -} -*/ diff --git a/linux/mcompile/keymap/mcompile.h b/linux/mcompile/keymap/mcompile.h deleted file mode 100644 index 3b1e2abad10..00000000000 --- a/linux/mcompile/keymap/mcompile.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - Name: mcompile - Copyright: Copyright (C) 2003-2017 SIL International. - Documentation: - Description: - Create Date: 3 Aug 2014 - - Modified Date: 3 Aug 2014 - Authors: mcdurdin - Related Files: - Dependencies: - - Bugs: - Todo: - Notes: - History: 03 Aug 2014 - mcdurdin - I4353 - V9.0 - mnemonic layout recompiler mixes up deadkey rules - -*/ - - - -#include -#include "km_types.h" - -void LogError(PKMX_WCHART message, ...); - - -struct DeadkeyMapping { // I4353 - KMX_WCHART deadkey, dkid; - KMX_UINT shift; - KMX_WORD vk; -}; - -extern std::vector FDeadkeys; // I4353 - - -//--------------------old -/* -#include - -void LogError(PWSTR message, ...); - - -struct DeadkeyMapping { // I4353 - WCHAR deadkey, dkid; - UINT shift; - WORD vk; -}; - -extern std::vector FDeadkeys; // I4353 -*/ diff --git a/linux/mcompile/keymap/meson.build b/linux/mcompile/keymap/meson.build deleted file mode 100644 index eb1e03783b7..00000000000 --- a/linux/mcompile/keymap/meson.build +++ /dev/null @@ -1,11 +0,0 @@ -project('keymap', 'c', 'cpp', - license: 'MIT', - meson_version: '>=1.0') - -gtk = dependency('gtk+-3.0', version: '>= 2.4') - -keymap = executable( - 'keymap', - sources: ['keymap.cpp'], - dependencies: [gtk] -) From 632f2fc5cecb410042e4fe88b0953820b16512c1 Mon Sep 17 00:00:00 2001 From: Sabine Date: Tue, 22 Oct 2024 10:34:35 +0200 Subject: [PATCH 007/251] feat(developer): kmc-convert-first draft of read/convert/write using Uint8Array --- .../src/kmc-convert/data/MySample.keylayout | 11 + .../keylayout-to-kmn-converter.ts | 214 +++++++++++++----- 2 files changed, 167 insertions(+), 58 deletions(-) diff --git a/developer/src/kmc-convert/data/MySample.keylayout b/developer/src/kmc-convert/data/MySample.keylayout index 23191ad7ebe..2aa7e67fb25 100644 --- a/developer/src/kmc-convert/data/MySample.keylayout +++ b/developer/src/kmc-convert/data/MySample.keylayout @@ -77,6 +77,17 @@ + + + + + + + + + + + diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index a315edd86d1..841ec61d3dd 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -21,6 +21,13 @@ export class KeylayoutToKmnConverter { // be available as class properties } +/** + * @brief run read/convert/write + * @param inputFilename the ukelele .keylayout-file to be converted + * @param outputFilename the resulting keyman .kmn-file + * @param binaryData ... _S2 + * @return + */ async run(inputFilename: string, outputFilename: string, binaryData: Uint8Array): Promise { if(!inputFilename || !outputFilename || !binaryData) { @@ -51,86 +58,101 @@ export class KeylayoutToKmnConverter { throw new Error('Not finished yet'); } -// ............................................................................................................ -// ............................................................................................................ -// ............................................................................................................ +/** + * @brief read filename ( a .keylayout-file) and write contents into Uint8Array keys_all_Layers + * @param filename the ukelele .keylayout-file to be converted + * @return in case of success Uint8Array keys_all_Layers; else null + */ public read(filename: string):Uint8Array[] { -/* -- // _S2 TODO and what about deadkeys??? -- // _S2 TODO which format to use in output ? + [K_A] > 'a' (character code) or + [K_A] > U+0061 (virt Keycode) -- // _S2 which stores? -- // _S2 how to use names of shiftstates*/ + /* + // _S2 TODO and what about deadkeys??? + // _S2 TODO which format to use in output ? + [K_A] > 'a' (character code) or + [K_A] > U+0061 (virt Keycode) + // _S2 which stores? + */ const options = { ignoreAttributes: false, - attributeNamePrefix: '@_', // you have to assign this to use this to access the attribute + attributeNamePrefix: '@_', // to access the attribute }; - - //xml file from https://learn.microsoft.com/en-us/previous-versions/windows/desktop/ms762271(v=vs.85) const xmlFile = readFileSync(`${process.cwd()}/data/MySample.keylayout`, 'utf8'); const parser = new XMLParser(options); const jsonObj = parser.parse(xmlFile); // get plain Object const nrOfStates = jsonObj.keyboard.keyMapSet[0].keyMap.length - const nrOfKeys = jsonObj.keyboard.keyMapSet[0].keyMap[0].key.length + const nrOfKeys_inLayer = jsonObj.keyboard.keyMapSet[0].keyMap[0].key.length + // create Object:any for storing Uint8tarray will be array[Uint8Array] Uint8Array might have several numbers (unicode) - const Keys_all_Layers :any[] = [] + // all keys for all layers + const keys_all_Layers :any[] = [] + const modifier_array: any[] = [] // why not put modifiers into Uint8Array along with values of keys of layer for (let j = 0; j < nrOfStates; j++) { + + modifier_array[j] = jsonObj.keyboard.modifierMap.keyMapSelect[j].modifier['@_keys'] + // create a new keys_in_Layer (type Uint8tarray) - const keys_in_Layer :Uint8Array[] = [] - for (let i = 0; i < nrOfKeys; i++) { - if(jsonObj.keyboard.keyMapSet[0].keyMap[j].key[i]['@_output'] !== "\0" ) { - // textencoder converts string -> bytes ( 'A' -> [ 65 ], '☺' -> [ 226, 152, 186 ]) - // textencoder is of Uint8Array(1) for A and Uint8Array(3) for ☺ - const textencoder = new TextEncoder().encode(jsonObj.keyboard.keyMapSet[0].keyMap[j].key[i]['@_output' ]); - keys_in_Layer[i] = textencoder - } + const keys_single_Layer :Uint8Array[] = [] + + for (let i = 0; i < nrOfKeys_inLayer; i++) { + if(jsonObj.keyboard.keyMapSet[0].keyMap[j].key[i]['@_output'] !== "\0" ) { + // textencoder converts string -> bytes ( 'A' -> [ 65 ], '☺' -> [ 226, 152, 186 ]) + // textencoder is of Uint8Array(1) for A and Uint8Array(3) for ☺ + keys_single_Layer[i] = new TextEncoder().encode(jsonObj.keyboard.keyMapSet[0].keyMap[j].key[i]['@_output' ]); } - // add [nrOfStates] Objects:Uint8tarray to Keys_all_Layers - Keys_all_Layers[j] = keys_in_Layer + } + + keys_all_Layers[j] = keys_single_Layer } + // add the modifiers-> better idea? + keys_all_Layers[nrOfStates] = modifier_array - console.log(" _S2 read finished\n") - return(Keys_all_Layers.length === nrOfStates && Keys_all_Layers[0].length === nrOfKeys) ? Keys_all_Layers : null; + // Keys_all_Layers needs to have nrOfStates entries + 1 for modifiers + return((keys_all_Layers.length === nrOfStates + 1) && keys_all_Layers[0].length === nrOfKeys_inLayer) ? keys_all_Layers : null; } -// ............................................................................................................ +/** + * @brief convert data of .keylayout-file to kmn-file This will convert/rename modifiers, position of Keys and deadkeys and save into an array + * @param data_ukelele (Uint8Array) data of the ukelele .keylayout-file + * @return outArray Uint8Array keys_all_Layers, the converted data for kmn-files if all layers have been converted; else null + */ + public convert(data_ukelele: any[]):any[] { + // sorting order: alphabetically OK? -public convert(inArray: any[]):any[] { + const data_kmn :any[] = []; - const outArray :any[] = []; - const nrOfMaxKeys = 50 + for (let j = 0; j < data_ukelele.length-1 ; j++) { + const keys_singleLayer :Uint8Array[] = [] - for (let j = 0; j < inArray.length ; j++) { - const outkeys_in_Layer :Uint8Array[] = [] + // now convert & sort + keys_singleLayer[0] = data_ukelele[j][0]; + keys_singleLayer[24] = data_ukelele[j][1]; + keys_singleLayer[2] = data_ukelele[j][2]; + keys_singleLayer[1] = data_ukelele[j][3]; + keys_singleLayer[16] = data_ukelele[j][4]; + keys_singleLayer[29] = data_ukelele[j][5]; + keys_singleLayer[38] = data_ukelele[j][6]; + keys_singleLayer[46] = data_ukelele[j][7]; + // later more here... - // initialize keys - for (let i = 0; i < nrOfMaxKeys; i++) { - outkeys_in_Layer[i] = new TextEncoder().encode("\0"); + data_kmn[j] = keys_singleLayer } - // now convert - outkeys_in_Layer[0] = inArray[j][0]; - outkeys_in_Layer[24] = inArray[j][1]; - outkeys_in_Layer[2] = inArray[j][2]; - outkeys_in_Layer[1] = inArray[j][3]; - outkeys_in_Layer[16] = inArray[j][4]; - outkeys_in_Layer[29] = inArray[j][5]; - outkeys_in_Layer[38] = inArray[j][6]; - outkeys_in_Layer[46] = inArray[j][7]; - - outArray[j] = outkeys_in_Layer - } - console.log(" _S2 convert finished\n") - return (outArray.length === inArray.length ) ? outArray : null -} + //copy the modifier states + data_kmn[data_ukelele.length - 1] = data_ukelele[data_ukelele.length - 1] + console.log(" _S2 convert finished\n", data_kmn + ) -public write(writeArray: any[]):boolean { + return (data_kmn.length === data_ukelele.length ) ? data_kmn : null + } - const KeyArray = [ +/** @brief write data to file + * @param kmn_array the array holding keyboard data + * @return true if data has been written; false if not + */ + public write(kmn_array: any[]):boolean { + const kmn_Key_Name = [ 'K_A','K_B','K_C','K_D','K_E','K_F','K_G','K_H','K_I','K_J','K_K','K_L','K_M','K_N','K_O','K_P','K_Q','K_R','K_S','K_T','K_U','K_V','K_W','K_X','K_Y','K_Z', 'K_0','K_1','K_2','K_3','K_4','K_5','K_6','K_7','K_8','K_9', 'K_SPACE', @@ -156,16 +178,92 @@ public write(writeArray: any[]):boolean { data += "group(main) using keys\n" data += "\n" - for (let i = 0; i < writeArray.length; i++) { - for (let j = 0; j < writeArray[0].length; j++) { - const textdecoder = new TextDecoder().decode(writeArray[i][j]) - if (textdecoder !== '\0' ) - data += `+ [` + KeyArray[j] + `] > \'` + textdecoder +'\'\n' + for (let i = 0; i < kmn_array.length-1; i++) { + for (let j = 0; j < kmn_array[0].length; j++) { + + // get the modifier for the layer + const label_modifier = this.create_modifier(kmn_array[kmn_array.length-1][i]) + // get the character that will be written as result in kmn-file + const resulting_character = new TextDecoder().decode(kmn_array[i][j]) + + // remove if-stmt later, only here for better visability + if (resulting_character !== '') + data += `+ [` + label_modifier + ' ' + kmn_Key_Name[j] + `] > \'` + resulting_character +'\'\n' + } data += '\n' } + writeFileSync("data/MyResult.kmn", data, { flag: "w"}) console.log(" _S2 write finished\n") - return true; + + if( data.length > 0) + return true; + else + return false } -} \ No newline at end of file + +/** + * @brief check if search_modifier is available in modifier_array + * @param search_modifier the value that will be searched for in modifier_array + * @param modifier_array the array holding all modifiers used + * @return true if search_modifier is found; false if not + */ + public isInArray(search_modifier:string, modifier_array: string[]):boolean { + for (let i =0; i < modifier_array.length; i++) { + if (search_modifier === String(modifier_array[i])) + return true + } + return false + } + +/** + * @brief create modifier in kmn-style from modifier of .keylayout-file + * @param keylayout_modifier the modifier value used in the .keylayout-file + * @return kmn_modifier the modifier value used in the .kmn-file + */ + public create_modifier(keylayout_modifier:any):string { + let add_modifier = "" + let kmn_modifier = "" + + // copy each modifier into element of array modifier_state + const modifier_state: string[] = keylayout_modifier.split(" "); + + // TODO review these conditions-> what else do I need? + // TODO spelling entries of .keylayout( uppercase/lowercase, control<->ctrl,...) + // TODO anyOption? + // opt?+ LOPT?+ ROPT? -> what will be result?? + + for (let i = 0; i < modifier_state.length; i++) { + + if ( String(modifier_state[i]) === "anyOption") add_modifier = "OPT " + else if ( String(modifier_state[i]) === "anyShift") add_modifier = "SHIFT " + else if ( String(modifier_state[i]) === "anyControl") add_modifier = "CTRL " + + else if ( String(modifier_state[i]) === "anyOption?") add_modifier = "" // does anyOption?... happen? + else if ( String(modifier_state[i]) === "anyShift?") add_modifier = "" + else if ( String(modifier_state[i]) === "anyControl?") add_modifier = "" + + else if( (String(modifier_state[i]) === "shift?" ) && this.isInArray('rshift',modifier_state)) add_modifier = "RSHIFT " + else if( (String(modifier_state[i]) === "shift?" ) && this.isInArray('lshift',modifier_state)) add_modifier = "LSHIFT " + else if( (String(modifier_state[i]) === "shift?" ) && this.isInArray('rshift',modifier_state) && this.isInArray('lshift',modifier_state)) add_modifier = "SHIFT " + + else if( (String(modifier_state[i]) === "option?" ) && this.isInArray('rOption',modifier_state)) add_modifier = "ROPT " + else if( (String(modifier_state[i]) === "option?" ) && this.isInArray('lOption',modifier_state)) add_modifier = "LOPT " + else if( (String(modifier_state[i]) === "option?" ) && this.isInArray('rOption',modifier_state) && this.isInArray('lOption',modifier_state)) add_modifier = "OPT " + + else if( (String(modifier_state[i]) === "ctrl?" ) && this.isInArray('rControl',modifier_state)) add_modifier = "RCTRL " + else if( (String(modifier_state[i]) === "ctrl?" ) && this.isInArray('lControl',modifier_state)) add_modifier = "LCTRL " + else if( (String(modifier_state[i]) === "ctrl?" ) && this.isInArray('rControl',modifier_state) && this.isInArray('lControl',modifier_state)) add_modifier = "CTRL " + + else if( String(modifier_state[i]) === "caps?") add_modifier = "" // capital letters or not? + else if( String(modifier_state[i]) === "shift?") add_modifier = "" + else if( String(modifier_state[i]) === "ctrl?") add_modifier = "" + + else add_modifier = String(modifier_state[i]) + + kmn_modifier += add_modifier + } + return kmn_modifier.trim().toUpperCase() + } +} From 4bfc80e436d4dfad96820f18a0eb6f82fa9cfcb3 Mon Sep 17 00:00:00 2001 From: Sabine Date: Wed, 23 Oct 2024 09:44:59 +0200 Subject: [PATCH 008/251] feat(developer): kmc-convert- add NCAPS to other rules in kmn-file if CAPS is used --- .../keylayout-to-kmn-converter.ts | 49 +++++++++++++++---- 1 file changed, 39 insertions(+), 10 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 841ec61d3dd..1f6d89e84ef 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -178,19 +178,28 @@ export class KeylayoutToKmnConverter { data += "group(main) using keys\n" data += "\n" + // check if caps is used from .keylayout-file + let isCAPSused = false + for (let i= 0 ; i < kmn_array[kmn_array.length-1].length; i++) { + if (kmn_array[kmn_array.length-1][i] === "caps") { + isCAPSused = true + } + } + for (let i = 0; i < kmn_array.length-1; i++) { for (let j = 0; j < kmn_array[0].length; j++) { // get the modifier for the layer - const label_modifier = this.create_modifier(kmn_array[kmn_array.length-1][i]) + const label_modifier = this.create_modifier(kmn_array[kmn_array.length-1][i], isCAPSused) + // get the character that will be written as result in kmn-file const resulting_character = new TextDecoder().decode(kmn_array[i][j]) // remove if-stmt later, only here for better visability if (resulting_character !== '') data += `+ [` + label_modifier + ' ' + kmn_Key_Name[j] + `] > \'` + resulting_character +'\'\n' - } + data += '\n' } @@ -222,9 +231,10 @@ export class KeylayoutToKmnConverter { * @param keylayout_modifier the modifier value used in the .keylayout-file * @return kmn_modifier the modifier value used in the .kmn-file */ - public create_modifier(keylayout_modifier:any):string { + public create_modifier(keylayout_modifier:any, isCAPSused:boolean):string { let add_modifier = "" let kmn_modifier = "" + let kmn_ncaps = "" // copy each modifier into element of array modifier_state const modifier_state: string[] = keylayout_modifier.split(" "); @@ -236,7 +246,12 @@ export class KeylayoutToKmnConverter { for (let i = 0; i < modifier_state.length; i++) { - if ( String(modifier_state[i]) === "anyOption") add_modifier = "OPT " + // marker used for adding NCAPS when CAPS is used somewhere in kmn + if ( isCAPSused && String(modifier_state[i]) !== "caps") + kmn_ncaps = " NCAPS " + + // TODO go over, find more conditions & simplify + if ( String(modifier_state[i]) === "anyOption") add_modifier = "RALT " else if ( String(modifier_state[i]) === "anyShift") add_modifier = "SHIFT " else if ( String(modifier_state[i]) === "anyControl") add_modifier = "CTRL " @@ -256,14 +271,28 @@ export class KeylayoutToKmnConverter { else if( (String(modifier_state[i]) === "ctrl?" ) && this.isInArray('lControl',modifier_state)) add_modifier = "LCTRL " else if( (String(modifier_state[i]) === "ctrl?" ) && this.isInArray('rControl',modifier_state) && this.isInArray('lControl',modifier_state)) add_modifier = "CTRL " - else if( String(modifier_state[i]) === "caps?") add_modifier = "" // capital letters or not? - else if( String(modifier_state[i]) === "shift?") add_modifier = "" - else if( String(modifier_state[i]) === "ctrl?") add_modifier = "" + // remove if modifier contains ? e.g. caps?, ctrl?, ... + else if( String(modifier_state[i]).charAt(modifier_state[i].length-1) === "?") add_modifier = "" - else add_modifier = String(modifier_state[i]) + else add_modifier = String(modifier_state[i]) + " " - kmn_modifier += add_modifier + kmn_modifier += kmn_ncaps + add_modifier } - return kmn_modifier.trim().toUpperCase() + + // replace duplicate entries with "" + const unique_Modifier: string[] = kmn_modifier.split(" ") + + for(let i = 0; i < unique_Modifier.length; i++) { + const modi = unique_Modifier[i] + + for(let j = i + 1; j < unique_Modifier.length; j++) { + const modi_next = unique_Modifier[j] + if (modi_next === modi) + unique_Modifier[j] = "" + } + } + + // remove duplicate whitespace, whitespace before & after, change to uppercase + return unique_Modifier.join(" ").replace(/\s+/g, " ").trim().toUpperCase() } } From 2d6785d984b770a9ee8044a0e1a9e06650a83b33 Mon Sep 17 00:00:00 2001 From: Sabine Date: Sun, 27 Oct 2024 16:17:29 +0100 Subject: [PATCH 009/251] feat(developer): kmc-convert-NCAPS also for entries like caps? --- developer/src/kmc-convert/src/converter.ts | 2 +- .../keylayout-to-kmn-converter.ts | 80 +++++++++---------- .../test/test-keylayout-to-kmn-converter.ts | 6 +- 3 files changed, 43 insertions(+), 45 deletions(-) diff --git a/developer/src/kmc-convert/src/converter.ts b/developer/src/kmc-convert/src/converter.ts index 4492bf254cf..83cc6738ecb 100644 --- a/developer/src/kmc-convert/src/converter.ts +++ b/developer/src/kmc-convert/src/converter.ts @@ -91,7 +91,7 @@ console.log('use run of converter.ts') } const converter = new ConverterClass(this.callbacks, converterOptions); - const artifacts = await converter.run(inputFilename, outputFilename, binaryData); + const artifacts = await converter.run(inputFilename, outputFilename); // Note: any subsequent errors in conversion will have been reported by the converter return artifacts ? { artifacts } : null; } diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 1f6d89e84ef..37ff5422d63 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -11,7 +11,6 @@ import { XMLParser } from 'fast-xml-parser'; // for reading a file import { readFileSync } from 'fs'; import { writeFileSync } from "fs"; // for writing a file - export class KeylayoutToKmnConverter { static readonly INPUT_FILE_EXTENSION = '.keylayout'; static readonly OUTPUT_FILE_EXTENSION = '.kmn'; @@ -28,9 +27,9 @@ export class KeylayoutToKmnConverter { * @param binaryData ... _S2 * @return */ - async run(inputFilename: string, outputFilename: string, binaryData: Uint8Array): Promise { + async run(inputFilename: string, outputFilename: string): Promise { - if(!inputFilename || !outputFilename || !binaryData) { + if(!inputFilename || !outputFilename) { throw new Error('Invalid parameters'); } @@ -126,14 +125,18 @@ export class KeylayoutToKmnConverter { const keys_singleLayer :Uint8Array[] = [] // now convert & sort - keys_singleLayer[0] = data_ukelele[j][0]; - keys_singleLayer[24] = data_ukelele[j][1]; - keys_singleLayer[2] = data_ukelele[j][2]; - keys_singleLayer[1] = data_ukelele[j][3]; - keys_singleLayer[16] = data_ukelele[j][4]; - keys_singleLayer[29] = data_ukelele[j][5]; - keys_singleLayer[38] = data_ukelele[j][6]; - keys_singleLayer[46] = data_ukelele[j][7]; + // a-b-c a-s-d-f-h + keys_singleLayer[0] = data_ukelele[j][0]; // a in a spec keyboard keylayoutfile -> code 0 + keys_singleLayer[24] = data_ukelele[j][1]; // y -> code 6 + keys_singleLayer[2] = data_ukelele[j][2]; // c -> code 8 --> keyman K_..[3] + keys_singleLayer[1] = data_ukelele[j][3]; // b -> code 11 --> keyman K_..[2] no! USVirtualKeyCodes should be [35] USVirtualKeyCodes.K_B + keys_singleLayer[16] = data_ukelele[j][4]; // q -> code 12 + keys_singleLayer[29] = data_ukelele[j][5]; // 3 -> code 20 + keys_singleLayer[38] = data_ukelele[j][6]; // ß -> code 27 + keys_singleLayer[46] = data_ukelele[j][7]; // -> code 47 + + // keyman K_A... code ukelele + // keyman VK-code == mac VK // later more here... data_kmn[j] = keys_singleLayer @@ -141,8 +144,7 @@ export class KeylayoutToKmnConverter { //copy the modifier states data_kmn[data_ukelele.length - 1] = data_ukelele[data_ukelele.length - 1] - console.log(" _S2 convert finished\n", data_kmn - ) + //console.log(" _S2 convert finished\n", data_kmn) return (data_kmn.length === data_ukelele.length ) ? data_kmn : null } @@ -178,10 +180,10 @@ export class KeylayoutToKmnConverter { data += "group(main) using keys\n" data += "\n" - // check if caps is used from .keylayout-file + // if caps is used we need to add NCAPS in kmn-file let isCAPSused = false for (let i= 0 ; i < kmn_array[kmn_array.length-1].length; i++) { - if (kmn_array[kmn_array.length-1][i] === "caps") { + if( String((kmn_array[kmn_array.length-1][i]).indexOf("caps") !== -1 ) ) { isCAPSused = true } } @@ -236,7 +238,7 @@ export class KeylayoutToKmnConverter { let kmn_modifier = "" let kmn_ncaps = "" - // copy each modifier into element of array modifier_state + // copy each modifier seperate element const modifier_state: string[] = keylayout_modifier.split(" "); // TODO review these conditions-> what else do I need? @@ -246,33 +248,35 @@ export class KeylayoutToKmnConverter { for (let i = 0; i < modifier_state.length; i++) { - // marker used for adding NCAPS when CAPS is used somewhere in kmn - if ( isCAPSused && String(modifier_state[i]) !== "caps") + if ( isCAPSused && (String(keylayout_modifier).indexOf("caps") === -1)) kmn_ncaps = " NCAPS " // TODO go over, find more conditions & simplify - if ( String(modifier_state[i]) === "anyOption") add_modifier = "RALT " - else if ( String(modifier_state[i]) === "anyShift") add_modifier = "SHIFT " - else if ( String(modifier_state[i]) === "anyControl") add_modifier = "CTRL " + if ( String(modifier_state[i]) === "anyOption") add_modifier = "RALT " + else if ( String(modifier_state[i]) === "anyShift") add_modifier = "SHIFT " + else if ( String(modifier_state[i]) === "anyControl") add_modifier = "CTRL " - else if ( String(modifier_state[i]) === "anyOption?") add_modifier = "" // does anyOption?... happen? - else if ( String(modifier_state[i]) === "anyShift?") add_modifier = "" - else if ( String(modifier_state[i]) === "anyControl?") add_modifier = "" + else if ( String(modifier_state[i]) === "anyOption?") add_modifier = "" // does anyOption?... happen? + else if ( String(modifier_state[i]) === "anyShift?") add_modifier = "" + else if ( String(modifier_state[i]) === "anyControl?") add_modifier = "" - else if( (String(modifier_state[i]) === "shift?" ) && this.isInArray('rshift',modifier_state)) add_modifier = "RSHIFT " - else if( (String(modifier_state[i]) === "shift?" ) && this.isInArray('lshift',modifier_state)) add_modifier = "LSHIFT " - else if( (String(modifier_state[i]) === "shift?" ) && this.isInArray('rshift',modifier_state) && this.isInArray('lshift',modifier_state)) add_modifier = "SHIFT " + // RSHIFT, rshift, Rshift,...? + else if ( (String(modifier_state[i]) === "shift?" ) && this.isInArray('rshift',modifier_state)) add_modifier = "RSHIFT " + else if ( (String(modifier_state[i]) === "shift?" ) && this.isInArray('lshift',modifier_state)) add_modifier = "LSHIFT " + else if ( (String(modifier_state[i]) === "shift?" ) && this.isInArray('rshift',modifier_state) && this.isInArray('lshift',modifier_state)) add_modifier = "SHIFT " - else if( (String(modifier_state[i]) === "option?" ) && this.isInArray('rOption',modifier_state)) add_modifier = "ROPT " - else if( (String(modifier_state[i]) === "option?" ) && this.isInArray('lOption',modifier_state)) add_modifier = "LOPT " - else if( (String(modifier_state[i]) === "option?" ) && this.isInArray('rOption',modifier_state) && this.isInArray('lOption',modifier_state)) add_modifier = "OPT " + else if ( (String(modifier_state[i]) === "option?" ) && this.isInArray('rOption',modifier_state)) add_modifier = "ROPT " + else if ( (String(modifier_state[i]) === "option?" ) && this.isInArray('lOption',modifier_state)) add_modifier = "LOPT " + else if ( (String(modifier_state[i]) === "option?" ) && this.isInArray('rOption',modifier_state) && this.isInArray('lOption',modifier_state)) add_modifier = "OPT " - else if( (String(modifier_state[i]) === "ctrl?" ) && this.isInArray('rControl',modifier_state)) add_modifier = "RCTRL " - else if( (String(modifier_state[i]) === "ctrl?" ) && this.isInArray('lControl',modifier_state)) add_modifier = "LCTRL " - else if( (String(modifier_state[i]) === "ctrl?" ) && this.isInArray('rControl',modifier_state) && this.isInArray('lControl',modifier_state)) add_modifier = "CTRL " + else if ( (String(modifier_state[i]) === "ctrl?" ) && this.isInArray('rControl',modifier_state)) add_modifier = "RCTRL " + else if ( (String(modifier_state[i]) === "ctrl?" ) && this.isInArray('lControl',modifier_state)) add_modifier = "LCTRL " + else if ( (String(modifier_state[i]) === "ctrl?" ) && this.isInArray('rControl',modifier_state) && this.isInArray('lControl',modifier_state)) add_modifier = "CTRL " - // remove if modifier contains ? e.g. caps?, ctrl?, ... - else if( String(modifier_state[i]).charAt(modifier_state[i].length-1) === "?") add_modifier = "" + // remove if modifier contains '?' except for 'caps?' e.g. 'shift?', 'ctrl?', ... + // is this correct: caps? => caps is not neccessary. If its not neccessary we need to write NCAPS. Correct? + else if ( String(modifier_state[i]) === "caps?" ) add_modifier = "NCAPS " + else if ( String(modifier_state[i]).charAt(modifier_state[i].length-1) === "?") add_modifier = "" else add_modifier = String(modifier_state[i]) + " " @@ -281,18 +285,14 @@ export class KeylayoutToKmnConverter { // replace duplicate entries with "" const unique_Modifier: string[] = kmn_modifier.split(" ") - for(let i = 0; i < unique_Modifier.length; i++) { const modi = unique_Modifier[i] - for(let j = i + 1; j < unique_Modifier.length; j++) { const modi_next = unique_Modifier[j] if (modi_next === modi) unique_Modifier[j] = "" } } - - // remove duplicate whitespace, whitespace before & after, change to uppercase - return unique_Modifier.join(" ").replace(/\s+/g, " ").trim().toUpperCase() + return unique_Modifier.join(" ").replace(/\s+/g, " ").trim().toUpperCase() } } diff --git a/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts index 229b5d55cc0..bfacef2f978 100644 --- a/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts @@ -21,7 +21,7 @@ describe('KeylayoutToKmnConverter', function() { // note, could use 'chai as promised' library to make this more fluent: let threw = false; try { - await converter.run(null, null, null); + await converter.run(null, null); } catch { threw = true; } @@ -38,18 +38,16 @@ describe('KeylayoutToKmnConverter', function() { //const inputFilename = makePathToFixture('../data/My_dk_Keyboard.keylayout'); const outputFilename = makePathToFixture('../data/MyResult.kmn'); - const data = new Uint8Array([1, 2, 3, 4]); // _S2 just to have sth in an array console.log(' inputFilename', inputFilename) console.log(' outputFilename', outputFilename) - console.log(' data', data) // _S2 create obj of derived class-> use derived functions const converter = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); let threw = false; try { - await converter.run(inputFilename, outputFilename, data); + await converter.run(inputFilename, outputFilename); } catch { threw = true; } From f21a7d3f1107cddd797ebfb9db618f15bc72d183 Mon Sep 17 00:00:00 2001 From: Sabine Date: Tue, 29 Oct 2024 10:44:37 +0100 Subject: [PATCH 010/251] feat(developer): kmc-convert-start to use deadkeys(read&map them from .ukelele file) --- .../keylayout-to-kmn-converter.ts | 176 +++++++++++++++--- .../test/test-keylayout-to-kmn-converter.ts | 4 +- 2 files changed, 152 insertions(+), 28 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 37ff5422d63..0ee66a3d282 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -65,9 +65,9 @@ export class KeylayoutToKmnConverter { */ public read(filename: string):Uint8Array[] { /* - // _S2 TODO and what about deadkeys??? // _S2 TODO which format to use in output ? + [K_A] > 'a' (character code) or + [K_A] > U+0061 (virt Keycode) // _S2 which stores? + // _S2 use var a = document.getElementById("target"); */ const options = { @@ -75,42 +75,136 @@ export class KeylayoutToKmnConverter { attributeNamePrefix: '@_', // to access the attribute }; - const xmlFile = readFileSync(`${process.cwd()}/data/MySample.keylayout`, 'utf8'); + //const xmlFile = readFileSync(`${process.cwd()}/data/MySample.keylayout`, 'utf8'); + const xmlFile = readFileSync(`${process.cwd()}/data/My_dk_Keyboard.keylayout`, 'utf8'); const parser = new XMLParser(options); const jsonObj = parser.parse(xmlFile); // get plain Object const nrOfStates = jsonObj.keyboard.keyMapSet[0].keyMap.length - const nrOfKeys_inLayer = jsonObj.keyboard.keyMapSet[0].keyMap[0].key.length + const nrOfKeys_inLayer = jsonObj.keyboard.keyMapSet[0].keyMap[0].key.length // will all have the same length later - // create Object:any for storing Uint8tarray will be array[Uint8Array] Uint8Array might have several numbers (unicode) - // all keys for all layers - const keys_all_Layers :any[] = [] - const modifier_array: any[] = [] // why not put modifiers into Uint8Array along with values of keys of layer + const modifier_array: any[] = [] // array holding all MODIFIER strings e.g. "anyShift caps anyOption" -why not put modifiers into Uint8Array along with values of keys of layer + const keys_action_all_Layers :any[] = [] // array holding all values with ACTION attribute (needed for finding deadkeys) + const deadkeys_all_Layers :any[] = [] // array holding all DEADKEYS for each mod state â, ê, ,.... + const data_all_Layers :any[] = [] // array holds ALL DATA: keys, output, action, dedkeys,... + // loop through all ss-combin for (let j = 0; j < nrOfStates; j++) { - + // get modifier list e.g. "anyshift caps? anyOption" modifier_array[j] = jsonObj.keyboard.modifierMap.keyMapSelect[j].modifier['@_keys'] - // create a new keys_in_Layer (type Uint8tarray) - const keys_single_Layer :Uint8Array[] = [] + // create a new array of keys_in_Layer (type Uint8tarray) + const keys_output_One_Layer :Uint8Array[] = [] + const keys_action_One_Layer :Uint8Array[] = [] - for (let i = 0; i < nrOfKeys_inLayer; i++) { + // ......................................................... + // get all keys for attribute "output" ( y,c,b,...) + // ......................................................... + for (let i = 0; i < jsonObj.keyboard.keyMapSet[0].keyMap[j].key.length; i++) { if(jsonObj.keyboard.keyMapSet[0].keyMap[j].key[i]['@_output'] !== "\0" ) { // textencoder converts string -> bytes ( 'A' -> [ 65 ], '☺' -> [ 226, 152, 186 ]) // textencoder is of Uint8Array(1) for A and Uint8Array(3) for ☺ - keys_single_Layer[i] = new TextEncoder().encode(jsonObj.keyboard.keyMapSet[0].keyMap[j].key[i]['@_output' ]); + keys_output_One_Layer[i] = new TextEncoder().encode(jsonObj.keyboard.keyMapSet[0].keyMap[j].key[i]['@_output' ]); } - } - keys_all_Layers[j] = keys_single_Layer + // ......................................................... + // get all keys for attribute "action" ( ^,a,e,i,...) + // ......................................................... + if(jsonObj.keyboard.keyMapSet[0].keyMap[j].key[i]['@_action'] !== "\0" ) { + keys_action_One_Layer[i] = new TextEncoder().encode(jsonObj.keyboard.keyMapSet[0].keyMap[j].key[i]['@_action' ]); + } + } + // ......................................................... + // create array of "action" and array of "output" + // ......................................................... + data_all_Layers[j] = keys_output_One_Layer // save all @output data ( will be used for conversion, write...) + keys_action_all_Layers[j] = keys_action_One_Layer // save all @action data ( will be used for deadkeys) } - // add the modifiers-> better idea? - keys_all_Layers[nrOfStates] = modifier_array - // Keys_all_Layers needs to have nrOfStates entries + 1 for modifiers - return((keys_all_Layers.length === nrOfStates + 1) && keys_all_Layers[0].length === nrOfKeys_inLayer) ? keys_all_Layers : null; + console.log('modifiers: ', modifier_array) + console.log('********************************************************') + // ......................................................... + // create array of "deadkey" / "deadkey names" + // ......................................................... + const dk_vec2d:string[][] = [] + for (let jj= 0; jj< jsonObj.keyboard.actions.action.length; jj++ ) { + // if there is a "next" attribute-> it is a dk + if(jsonObj.keyboard.actions.action[jj].when['@_next'] !== undefined ) { + const vec1d:string[] = [] + vec1d.push(jsonObj.keyboard.actions.action[jj].when['@_next']) + vec1d.push(jsonObj.keyboard.actions.action[jj]['@_id']) + dk_vec2d.push(vec1d) + } + } + console.log('dk_vec2d',dk_vec2d ) + console.log('********************************************************') + + // ......................................................... + // create array of deadkey base ^ ´ ` + // ......................................................... + const dk :string[] = []; + for ( let k=0; k < dk_vec2d.length; k++) { + dk.push(dk_vec2d[k][1] ) + } + console.log('dk: ', dk) + console.log('********************************************************') + + // ......................................................... + // create array of "deadkeyables" + // ......................................................... + const deadkeyables :string[][]=[] + for ( let j=0; j plain deadkeyables ( a,^, e,i,´,u => a,e,i,u) + deadkeyables[j] = deadkeyables[j].filter( function( el ) { + return dk.indexOf( el ) < 0; + }); + } + console.log('deadkeyables per modifier state: ', deadkeyables) + console.log('********************************************************') + + // ......................................................... + // create deadkeys-array + // ......................................................... + // for all 'dk' + for ( let k=0; k '^' ) + data_all_Layers.push(dk) // add plain dk ( '^', '´','`') + data_all_Layers.push(deadkeyables) // add char that can be modified with dk ( a,e,i,o,u) + data_all_Layers.push(deadkeys_all_Layers) // add modified keys ( â,ê,î,ô,û) + + return data_all_Layers + return((data_all_Layers.length === nrOfStates + 5) && data_all_Layers[0].length === nrOfKeys_inLayer) ? data_all_Layers : null; } +/*public fill_singleLayer_AllKeys(index_kmn:any):any { + + return kk.index_kmn +}*/ /** * @brief convert data of .keylayout-file to kmn-file This will convert/rename modifiers, position of Keys and deadkeys and save into an array * @param data_ukelele (Uint8Array) data of the ukelele .keylayout-file @@ -121,7 +215,7 @@ export class KeylayoutToKmnConverter { const data_kmn :any[] = []; - for (let j = 0; j < data_ukelele.length-1 ; j++) { + for (let j = 0; j < data_ukelele.length-5 ; j++) { const keys_singleLayer :Uint8Array[] = [] // now convert & sort @@ -139,14 +233,21 @@ export class KeylayoutToKmnConverter { // keyman VK-code == mac VK // later more here... + //console.log("data_ukelele[j][1]", data_ukelele[0][1] , '--> keys_singleLayer[24]',keys_singleLayer[24] ) data_kmn[j] = keys_singleLayer } - //copy the modifier states + //copy the modifier states __ better idea? + //data_kmn[data_ukelele.length - 1] = data_ukelele[data_ukelele.length - 1] + data_kmn[data_ukelele.length - 5] = data_ukelele[data_ukelele.length - 5] + data_kmn[data_ukelele.length - 4] = data_ukelele[data_ukelele.length - 4] + data_kmn[data_ukelele.length - 3] = data_ukelele[data_ukelele.length - 3] + data_kmn[data_ukelele.length - 2] = data_ukelele[data_ukelele.length - 2] data_kmn[data_ukelele.length - 1] = data_ukelele[data_ukelele.length - 1] //console.log(" _S2 convert finished\n", data_kmn) - return (data_kmn.length === data_ukelele.length ) ? data_kmn : null + return data_kmn + //return (data_kmn.length === data_ukelele.length ) ? data_kmn : null } /** @brief write data to file @@ -154,6 +255,7 @@ export class KeylayoutToKmnConverter { * @return true if data has been written; false if not */ public write(kmn_array: any[]):boolean { + const kmn_Key_Name = [ 'K_A','K_B','K_C','K_D','K_E','K_F','K_G','K_H','K_I','K_J','K_K','K_L','K_M','K_N','K_O','K_P','K_Q','K_R','K_S','K_T','K_U','K_V','K_W','K_X','K_Y','K_Z', 'K_0','K_1','K_2','K_3','K_4','K_5','K_6','K_7','K_8','K_9', @@ -165,6 +267,9 @@ export class KeylayoutToKmnConverter { 'K_xDF', 'K_OEM_102' ] + // ************************************************************* + // **** write stores ******************************************* + // ************************************************************* let data = "\n" data += "c\n" data += "c Keyman keyboard generated by kmn-convert\n" @@ -180,19 +285,25 @@ export class KeylayoutToKmnConverter { data += "group(main) using keys\n" data += "\n" + // ************************************************************* + // **** write rules ******************************************** + // ************************************************************* // if caps is used we need to add NCAPS in kmn-file + console.log("kmn_array",kmn_array) let isCAPSused = false for (let i= 0 ; i < kmn_array[kmn_array.length-1].length; i++) { - if( String((kmn_array[kmn_array.length-1][i]).indexOf("caps") !== -1 ) ) { + if ( String((kmn_array[kmn_array.length-1][i]).indexOf("caps") !== -1 ) ) { isCAPSused = true } } - for (let i = 0; i < kmn_array.length-1; i++) { + //for (let i = 0; i < kmn_array.length-1; i++) { + for (let i = 0; i < kmn_array.length-5; i++) { for (let j = 0; j < kmn_array[0].length; j++) { // get the modifier for the layer - const label_modifier = this.create_modifier(kmn_array[kmn_array.length-1][i], isCAPSused) + //const label_modifier = this.create_modifier(kmn_array[kmn_array.length-1][i], isCAPSused) + const label_modifier = this.create_modifier(kmn_array[kmn_array.length-5][i], isCAPSused) // get the character that will be written as result in kmn-file const resulting_character = new TextDecoder().decode(kmn_array[i][j]) @@ -201,10 +312,23 @@ export class KeylayoutToKmnConverter { if (resulting_character !== '') data += `+ [` + label_modifier + ' ' + kmn_Key_Name[j] + `] > \'` + resulting_character +'\'\n' } - data += '\n' } + // ************************************************************* + // **** write deadkeys ***************************************** + // ************************************************************* + // val vk dk + /*+ [K_BKQUOTE] > dk(005e) + + + [K_EQUAL] > dk(00b4) + + [SHIFT K_EQUAL] > dk(0060)*/ + + data += "match > use(deadkeys)\n\n" + data += "group(deadkeys)\n" + data += "store(" + ".....)\n" + data += '\n' + writeFileSync("data/MyResult.kmn", data, { flag: "w"}) console.log(" _S2 write finished\n") @@ -295,4 +419,4 @@ export class KeylayoutToKmnConverter { } return unique_Modifier.join(" ").replace(/\s+/g, " ").trim().toUpperCase() } -} +} \ No newline at end of file diff --git a/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts index bfacef2f978..dbe813f0dc9 100644 --- a/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts @@ -33,9 +33,9 @@ describe('KeylayoutToKmnConverter', function() { it('should throw on all elements loaded', async function () { // some keys, no deadkeys - const inputFilename = makePathToFixture('../data/Mysample.keylayout'); + //const inputFilename = makePathToFixture('../data/Mysample.keylayout'); // all keys, some deadkeys - //const inputFilename = makePathToFixture('../data/My_dk_Keyboard.keylayout'); + const inputFilename = makePathToFixture('../data/My_dk_Keyboard.keylayout'); const outputFilename = makePathToFixture('../data/MyResult.kmn'); From 8873228ba6ddc51468d0c922359e66aed79b04d2 Mon Sep 17 00:00:00 2001 From: Sabine Date: Wed, 30 Oct 2024 03:34:50 +0100 Subject: [PATCH 011/251] feat(developer): kmc-convert-sorting order of dk the same for action() and action() --- .../keylayout-to-kmn-converter.ts | 78 +++++++++++++++---- 1 file changed, 61 insertions(+), 17 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 0ee66a3d282..0a3ac3cea69 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -55,6 +55,7 @@ export class KeylayoutToKmnConverter { return null; } + console.log(';;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; FINISHED OK ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;'); throw new Error('Not finished yet'); } @@ -77,6 +78,7 @@ export class KeylayoutToKmnConverter { //const xmlFile = readFileSync(`${process.cwd()}/data/MySample.keylayout`, 'utf8'); const xmlFile = readFileSync(`${process.cwd()}/data/My_dk_Keyboard.keylayout`, 'utf8'); + const parser = new XMLParser(options); const jsonObj = parser.parse(xmlFile); // get plain Object @@ -170,25 +172,43 @@ export class KeylayoutToKmnConverter { console.log('deadkeyables per modifier state: ', deadkeyables) console.log('********************************************************') - // ......................................................... - // create deadkeys-array - // ......................................................... + console.log('keys_action_all_Layers ', keys_action_all_Layers) + + // ......................................................... + // loop through all dk, key-actions and find @_action + // find this value in + // in their 'when' find output for dk + // for all 'dk' - for ( let k=0; k + for (let k= 0; k< keys_action_all_Layers[j].length; k++ ) { + const toFind = new TextDecoder().decode(keys_action_all_Layers[j][k]) + + if( toFind !== "") { + // find the same id (e.g. ) in actions + for (let l= 0; l< jsonObj.keyboard.actions.action.length; l++ ) { + if (jsonObj.keyboard.actions.action[l]['@_id'] === toFind ) { + // loop through when until dk name (e.g. dk s0) + for (let m= 0; m< jsonObj.keyboard.actions.action[l].when.length; m++ ) { + // get their @_output + if (jsonObj.keyboard.actions.action[l].when[m]['@_state'] === dk_vec2d[i][0] ) { + deadkeys_One_dk.push(jsonObj.keyboard.actions.action[l].when[m]['@_output']) + } + } + } } } } - deadkeys_all_Layers.push(deadkeys_One_dk) } - console.log('deadkeys per modifier state: ', deadkeys_all_Layers ) - console.log('********************************************************') + deadkeys_all_Layers.push(deadkeys_One_dk) + } + + console.log('deadkeys per modifier state: ', deadkeys_all_Layers ) + console.log('********************************************************') // is there a better way?? data_all_Layers[nrOfStates] = modifier_array // add all normal key data @@ -223,12 +243,12 @@ export class KeylayoutToKmnConverter { keys_singleLayer[0] = data_ukelele[j][0]; // a in a spec keyboard keylayoutfile -> code 0 keys_singleLayer[24] = data_ukelele[j][1]; // y -> code 6 keys_singleLayer[2] = data_ukelele[j][2]; // c -> code 8 --> keyman K_..[3] - keys_singleLayer[1] = data_ukelele[j][3]; // b -> code 11 --> keyman K_..[2] no! USVirtualKeyCodes should be [35] USVirtualKeyCodes.K_B + keys_singleLayer[52] = data_ukelele[j][3]; // b -> code 11 --> keyman K_..[2] no! USVirtualKeyCodes should be [35] USVirtualKeyCodes.K_B keys_singleLayer[16] = data_ukelele[j][4]; // q -> code 12 keys_singleLayer[29] = data_ukelele[j][5]; // 3 -> code 20 keys_singleLayer[38] = data_ukelele[j][6]; // ß -> code 27 keys_singleLayer[46] = data_ukelele[j][7]; // -> code 47 - + keys_singleLayer[27] = data_ukelele[j][9]; // -> code 47 // keyman K_A... code ukelele // keyman VK-code == mac VK // later more here... @@ -324,10 +344,26 @@ export class KeylayoutToKmnConverter { + [K_EQUAL] > dk(00b4) + [SHIFT K_EQUAL] > dk(0060)*/ + + for ( let i=0; i Date: Thu, 31 Oct 2024 03:33:59 +0100 Subject: [PATCH 012/251] feat(developer): kmc-convert tidy up, add TODO labels --- .../kmc-convert/data/My_dk_Keyboard.keylayout | 472 +++++++-------- .../keylayout-to-kmn-converter.ts | 558 ++++++++++-------- 2 files changed, 520 insertions(+), 510 deletions(-) diff --git a/developer/src/kmc-convert/data/My_dk_Keyboard.keylayout b/developer/src/kmc-convert/data/My_dk_Keyboard.keylayout index 39c4ce0966a..b7c724e0110 100644 --- a/developer/src/kmc-convert/data/My_dk_Keyboard.keylayout +++ b/developer/src/kmc-convert/data/My_dk_Keyboard.keylayout @@ -35,95 +35,98 @@ - - - - - + + + + + - + - - + + - + - - - + + + - + - - - - - - - - - - + + + + + + + + + + - + - + - - - - - - - - - - + + + + + + + + + + - - + + + - - + - - + + - + - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + @@ -140,96 +143,99 @@ - - - - - - + + + + + + - + - - + + - - - - - + + + + + - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + - - - - - - - - - - - + + + + + + + + + + + - - + + + - - - - - - + + + + + - - + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + @@ -246,96 +252,99 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - + + + + + + + + + + + - - + + + - - + - - + + - + - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + @@ -353,87 +362,10 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 0a3ac3cea69..226b2363774 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -15,27 +15,27 @@ export class KeylayoutToKmnConverter { static readonly INPUT_FILE_EXTENSION = '.keylayout'; static readonly OUTPUT_FILE_EXTENSION = '.kmn'; + // TODO use callbacks constructor(/*private*/ _callbacks: CompilerCallbacks, /*private*/ _options: CompilerOptions) { // TODO: if these are needed, uncomment /*private*/ and remove _, and they will then // be available as class properties } -/** - * @brief run read/convert/write - * @param inputFilename the ukelele .keylayout-file to be converted - * @param outputFilename the resulting keyman .kmn-file - * @param binaryData ... _S2 - * @return - */ + /** + * @brief member function to run read/convert/write + * @param inputFilename the ukelele .keylayout-file to be converted + * @param outputFilename the resulting keyman .kmn-file + * @param binaryData ... _S2 + * @return + */ async run(inputFilename: string, outputFilename: string): Promise { - if(!inputFilename || !outputFilename) { + if (!inputFilename || !outputFilename) { throw new Error('Invalid parameters'); } console.log(' _S2 first READ file ........................................'); - const inArray = this.read(inputFilename) - // console.log(' inArray:',inArray) + const inArray = this.read(inputFilename) if (!inArray) { return null; @@ -44,7 +44,6 @@ export class KeylayoutToKmnConverter { console.log(' _S2 then CONVERT ........................................'); const outArray = await this.convert(inArray); - //console.log(' outArray:',outArray) if (!outArray) { return null; } @@ -55,148 +54,153 @@ export class KeylayoutToKmnConverter { return null; } + // TODO throws console.log(';;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; FINISHED OK ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;'); throw new Error('Not finished yet'); } -/** - * @brief read filename ( a .keylayout-file) and write contents into Uint8Array keys_all_Layers - * @param filename the ukelele .keylayout-file to be converted - * @return in case of success Uint8Array keys_all_Layers; else null - */ - public read(filename: string):Uint8Array[] { + /** + * @brief member function to read filename ( a .keylayout-file) and write contents into Uint8Array keys_all_Layers + * @param filename the ukelele .keylayout-file to be converted + * @return in case of success Uint8Array keys_all_Layers; else null + */ + public read(filename: string): Uint8Array[] { /* - // _S2 TODO which format to use in output ? + [K_A] > 'a' (character code) or + [K_A] > U+0061 (virt Keycode) - // _S2 which stores? + // _S2 answer : + [K_A] > 'a' is OK / TODO which format to use in output ? + [K_A] > 'a' (character code) or + [K_A] > U+0061 (virt Keycode) + // _S2 TODO which stores? // _S2 use var a = document.getElementById("target"); */ - const options = { - ignoreAttributes: false, - attributeNamePrefix: '@_', // to access the attribute - }; - - //const xmlFile = readFileSync(`${process.cwd()}/data/MySample.keylayout`, 'utf8'); - const xmlFile = readFileSync(`${process.cwd()}/data/My_dk_Keyboard.keylayout`, 'utf8'); - - const parser = new XMLParser(options); - const jsonObj = parser.parse(xmlFile); // get plain Object - - const nrOfStates = jsonObj.keyboard.keyMapSet[0].keyMap.length - const nrOfKeys_inLayer = jsonObj.keyboard.keyMapSet[0].keyMap[0].key.length // will all have the same length later - - const modifier_array: any[] = [] // array holding all MODIFIER strings e.g. "anyShift caps anyOption" -why not put modifiers into Uint8Array along with values of keys of layer - const keys_action_all_Layers :any[] = [] // array holding all values with ACTION attribute (needed for finding deadkeys) - const deadkeys_all_Layers :any[] = [] // array holding all DEADKEYS for each mod state â, ê, ,.... - const data_all_Layers :any[] = [] // array holds ALL DATA: keys, output, action, dedkeys,... - - // loop through all ss-combin - for (let j = 0; j < nrOfStates; j++) { - // get modifier list e.g. "anyshift caps? anyOption" - modifier_array[j] = jsonObj.keyboard.modifierMap.keyMapSelect[j].modifier['@_keys'] - - // create a new array of keys_in_Layer (type Uint8tarray) - const keys_output_One_Layer :Uint8Array[] = [] - const keys_action_One_Layer :Uint8Array[] = [] - - // ......................................................... - // get all keys for attribute "output" ( y,c,b,...) - // ......................................................... - for (let i = 0; i < jsonObj.keyboard.keyMapSet[0].keyMap[j].key.length; i++) { - if(jsonObj.keyboard.keyMapSet[0].keyMap[j].key[i]['@_output'] !== "\0" ) { - // textencoder converts string -> bytes ( 'A' -> [ 65 ], '☺' -> [ 226, 152, 186 ]) - // textencoder is of Uint8Array(1) for A and Uint8Array(3) for ☺ - keys_output_One_Layer[i] = new TextEncoder().encode(jsonObj.keyboard.keyMapSet[0].keyMap[j].key[i]['@_output' ]); - } + const options = { + ignoreAttributes: false, + attributeNamePrefix: '@_', // to access the attribute + }; + + // TODO create path from "filename" + //const xmlFile = readFileSync(`${process.cwd()}/data/MySample.keylayout`, 'utf8'); + const xmlFile = readFileSync(`${process.cwd()}/data/My_dk_Keyboard.keylayout`, 'utf8'); + const parser = new XMLParser(options); + const jsonObj = parser.parse(xmlFile); // get plain Object + + const nrOfStates = jsonObj.keyboard.keyMapSet[0].keyMap.length + const nrOfKeys_inLayer = jsonObj.keyboard.keyMapSet[0].keyMap[0].key.length // will they all have the same length later ? + + // TODO array-> object + const modifier_array: any[] = [] // array holding all MODIFIER strings e.g. "anyShift caps anyOption" -why not put modifiers into Uint8Array along with values of keys of layer + const keys_action_all_Layers: any[] = [] // array holding all values with ACTION attribute (needed for finding deadkeys) + const deadkeys_all_Layers: any[] = [] // array holding all DEADKEYS for each mod state â, ê, ,.... + const data_all_Layers: any[] = [] // array holds ALL DATA: keys, output, action, dedkeys,... + + // get data separated into data for output/action + // loop through all ss-combin + for (let j = 0; j < nrOfStates; j++) { + // get modifier list e.g. "anyshift caps? anyOption" + modifier_array[j] = jsonObj.keyboard.modifierMap.keyMapSelect[j].modifier['@_keys'] + + // create a new array of keys_in_Layer (type Uint8tarray) + const keys_output_One_Layer: Uint8Array[] = [] + const keys_action_One_Layer: Uint8Array[] = [] + + // ......................................................... + // get all keys for attribute "output" ( y,c,b,...) - TODO can i use shorter function? + // ......................................................... + for (let i = 0; i < jsonObj.keyboard.keyMapSet[0].keyMap[j].key.length; i++) { + if (jsonObj.keyboard.keyMapSet[0].keyMap[j].key[i]['@_output'] !== "\0") { + // textencoder converts string -> bytes ( 'A' -> [ 65 ], '☺' -> [ 226, 152, 186 ]) + // textencoder is of Uint8Array(1) for A and Uint8Array(3) for ☺ + keys_output_One_Layer[i] = new TextEncoder().encode(jsonObj.keyboard.keyMapSet[0].keyMap[j].key[i]['@_output']); + } - // ......................................................... - // get all keys for attribute "action" ( ^,a,e,i,...) - // ......................................................... - if(jsonObj.keyboard.keyMapSet[0].keyMap[j].key[i]['@_action'] !== "\0" ) { - keys_action_One_Layer[i] = new TextEncoder().encode(jsonObj.keyboard.keyMapSet[0].keyMap[j].key[i]['@_action' ]); + // ......................................................... + // get all keys for attribute "action" ( ^,a,e,i,...) - TODO can i use shorter function? + // ......................................................... + if (jsonObj.keyboard.keyMapSet[0].keyMap[j].key[i]['@_action'] !== "\0") { + keys_action_One_Layer[i] = new TextEncoder().encode(jsonObj.keyboard.keyMapSet[0].keyMap[j].key[i]['@_action']); + } } + // ......................................................... + // create array of "action" and array of "output" + // ......................................................... + data_all_Layers[j] = keys_output_One_Layer // save all @output data ( will be used for conversion, write...) + keys_action_all_Layers[j] = keys_action_One_Layer // save all @action data ( will be used for deadkeys) } - // ......................................................... - // create array of "action" and array of "output" - // ......................................................... - data_all_Layers[j] = keys_output_One_Layer // save all @output data ( will be used for conversion, write...) - keys_action_all_Layers[j] = keys_action_One_Layer // save all @action data ( will be used for deadkeys) - } - console.log('modifiers: ', modifier_array) - console.log('********************************************************') - // ......................................................... - // create array of "deadkey" / "deadkey names" - // ......................................................... - const dk_vec2d:string[][] = [] - for (let jj= 0; jj< jsonObj.keyboard.actions.action.length; jj++ ) { + console.log('modifiers: ', modifier_array) + console.log('********************************************************') + // ......................................................... + // create array of "deadkey" / "deadkey names" - TODO can i use shorter function? + // ......................................................... + const dk_vec2d: string[][] = [] + for (let jj = 0; jj < jsonObj.keyboard.actions.action.length; jj++) { // if there is a "next" attribute-> it is a dk - if(jsonObj.keyboard.actions.action[jj].when['@_next'] !== undefined ) { - const vec1d:string[] = [] + if (jsonObj.keyboard.actions.action[jj].when['@_next'] !== undefined) { + const vec1d: string[] = [] vec1d.push(jsonObj.keyboard.actions.action[jj].when['@_next']) vec1d.push(jsonObj.keyboard.actions.action[jj]['@_id']) dk_vec2d.push(vec1d) } } - console.log('dk_vec2d',dk_vec2d ) + console.log('dk_vec2d', dk_vec2d) console.log('********************************************************') - // ......................................................... - // create array of deadkey base ^ ´ ` - // ......................................................... - const dk :string[] = []; - for ( let k=0; k < dk_vec2d.length; k++) { - dk.push(dk_vec2d[k][1] ) + // ......................................................... + // create array of deadkey base ^ ´ ` // TODO needed to add and distribute? + // ......................................................... + const dk: string[] = []; + for (let k = 0; k < dk_vec2d.length; k++) { + dk.push(dk_vec2d[k][1]) } console.log('dk: ', dk) console.log('********************************************************') - // ......................................................... - // create array of "deadkeyables" - // ......................................................... - const deadkeyables :string[][]=[] - for ( let j=0; j plain deadkeyables ( a,^, e,i,´,u => a,e,i,u) - deadkeyables[j] = deadkeyables[j].filter( function( el ) { - return dk.indexOf( el ) < 0; - }); + // ......................................................... + // create array of "deadkeyables" - TODO can i use shorter function? + // ......................................................... + const deadkeyables: string[][] = [] + for (let j = 0; j < jsonObj.keyboard.keyMapSet[0].keyMap.length; j++) { + const deadkeyables_one: string[] = [] + for (let i = 0; i < jsonObj.keyboard.keyMapSet[0].keyMap[0].key.length; i++) { + const resulting_character = new TextDecoder().decode(keys_action_all_Layers[j][i]) + if (resulting_character !== "") + deadkeyables_one.push(resulting_character) } - console.log('deadkeyables per modifier state: ', deadkeyables) - console.log('********************************************************') + deadkeyables.push(deadkeyables_one) - console.log('keys_action_all_Layers ', keys_action_all_Layers) + // filter out dk -> plain deadkeyables ( a,^, e,i,´,u => a,e,i,u) + // return all that don`t find ^,´, ` + deadkeyables[j] = deadkeyables[j].filter(function (el) { + return dk.indexOf(el) < 0; + }); + } + console.log('deadkeyables per modifier state: ', deadkeyables) + console.log('********************************************************') + + console.log('keys_action_all_Layers ', keys_action_all_Layers) // ......................................................... + // TODO can i use shorter function? // loop through all dk, key-actions and find @_action // find this value in // in their 'when' find output for dk // for all 'dk' - for ( let i=0; i - for (let k= 0; k< keys_action_all_Layers[j].length; k++ ) { - const toFind = new TextDecoder().decode(keys_action_all_Layers[j][k]) + for (let k = 0; k < keys_action_all_Layers[j].length; k++) { + const action_from_keys_prargraph = new TextDecoder().decode(keys_action_all_Layers[j][k]) - if( toFind !== "") { - // find the same id (e.g. ) in actions - for (let l= 0; l< jsonObj.keyboard.actions.action.length; l++ ) { - if (jsonObj.keyboard.actions.action[l]['@_id'] === toFind ) { + if (action_from_keys_prargraph !== "") { + // find the same id (e.g. ) in the actions-paragraph + for (let l = 0; l < jsonObj.keyboard.actions.action.length; l++) { + if (jsonObj.keyboard.actions.action[l]['@_id'] === action_from_keys_prargraph) { // loop through when until dk name (e.g. dk s0) - for (let m= 0; m< jsonObj.keyboard.actions.action[l].when.length; m++ ) { - // get their @_output - if (jsonObj.keyboard.actions.action[l].when[m]['@_state'] === dk_vec2d[i][0] ) { - deadkeys_One_dk.push(jsonObj.keyboard.actions.action[l].when[m]['@_output']) + for (let m = 0; m < jsonObj.keyboard.actions.action[l].when.length; m++) { + // and get their @_output + if (jsonObj.keyboard.actions.action[l].when[m]['@_state'] === dk_vec2d[i][0]) { + deadkeys_One_dk.push(jsonObj.keyboard.actions.action[l].when[m]['@_output']) } } } @@ -204,61 +208,51 @@ export class KeylayoutToKmnConverter { } } } - deadkeys_all_Layers.push(deadkeys_One_dk) + deadkeys_all_Layers.push(deadkeys_One_dk) } - - console.log('deadkeys per modifier state: ', deadkeys_all_Layers ) + // TODO data is in array multiple times?? + console.log('deadkeys per modifier state: ', deadkeys_all_Layers) console.log('********************************************************') // is there a better way?? + // TODO do we need dk? data_all_Layers[nrOfStates] = modifier_array // add all normal key data data_all_Layers.push(dk_vec2d) // add dk-mapping ( dk1 <-> '^' ) data_all_Layers.push(dk) // add plain dk ( '^', '´','`') data_all_Layers.push(deadkeyables) // add char that can be modified with dk ( a,e,i,o,u) data_all_Layers.push(deadkeys_all_Layers) // add modified keys ( â,ê,î,ô,û) - return data_all_Layers - return((data_all_Layers.length === nrOfStates + 5) && data_all_Layers[0].length === nrOfKeys_inLayer) ? data_all_Layers : null; -} - -/*public fill_singleLayer_AllKeys(index_kmn:any):any { + // TODO review condition + return data_all_Layers + return ((data_all_Layers.length === nrOfStates + 5) && data_all_Layers[0].length === nrOfKeys_inLayer) ? data_all_Layers : null; + } - return kk.index_kmn -}*/ -/** - * @brief convert data of .keylayout-file to kmn-file This will convert/rename modifiers, position of Keys and deadkeys and save into an array - * @param data_ukelele (Uint8Array) data of the ukelele .keylayout-file - * @return outArray Uint8Array keys_all_Layers, the converted data for kmn-files if all layers have been converted; else null - */ - public convert(data_ukelele: any[]):any[] { - // sorting order: alphabetically OK? - - const data_kmn :any[] = []; - - for (let j = 0; j < data_ukelele.length-5 ; j++) { - const keys_singleLayer :Uint8Array[] = [] - - // now convert & sort - // a-b-c a-s-d-f-h - keys_singleLayer[0] = data_ukelele[j][0]; // a in a spec keyboard keylayoutfile -> code 0 - keys_singleLayer[24] = data_ukelele[j][1]; // y -> code 6 - keys_singleLayer[2] = data_ukelele[j][2]; // c -> code 8 --> keyman K_..[3] - keys_singleLayer[52] = data_ukelele[j][3]; // b -> code 11 --> keyman K_..[2] no! USVirtualKeyCodes should be [35] USVirtualKeyCodes.K_B - keys_singleLayer[16] = data_ukelele[j][4]; // q -> code 12 - keys_singleLayer[29] = data_ukelele[j][5]; // 3 -> code 20 - keys_singleLayer[38] = data_ukelele[j][6]; // ß -> code 27 - keys_singleLayer[46] = data_ukelele[j][7]; // -> code 47 - keys_singleLayer[27] = data_ukelele[j][9]; // -> code 47 - // keyman K_A... code ukelele - // keyman VK-code == mac VK - // later more here... - - //console.log("data_ukelele[j][1]", data_ukelele[0][1] , '--> keys_singleLayer[24]',keys_singleLayer[24] ) + /** + * @brief member function to convert data of .keylayout-file to kmn-file This will convert/rename modifiers, position of Keys and deadkeys and save into an array + * @param data_ukelele (Uint8Array) data of the ukelele .keylayout-file + * @return outArray Uint8Array keys_all_Layers, the converted data for kmn-files if all layers have been converted; else null + */ + public convert(data_ukelele: any[]): any[] { + //TODO sorting order: alphabetically OK? + + const data_kmn: any[] = []; + + // TODO get rid og magic number 5 etc + for (let j = 0; j < data_ukelele.length - 5; j++) { + const keys_singleLayer: Uint8Array[] = [] + // map Ukelele Keycodes to the position of the key in kmn_Key_Name + for (let i = 0; i < data_ukelele[j].length; i++) { + // TODO use mapping from standard constants + keys_singleLayer[this.map_UkeleleKC_To_kmn_Key_Name_Array_Position(data_ukelele[j][i], i)] = data_ukelele[j][i] + } data_kmn[j] = keys_singleLayer } - //copy the modifier states __ better idea? + // TODO use object !!! + //TODO copy the modifier states __ better idea? //data_kmn[data_ukelele.length - 1] = data_ukelele[data_ukelele.length - 1] + + // TODO get rid og magic number 5 etc etc data_kmn[data_ukelele.length - 5] = data_ukelele[data_ukelele.length - 5] data_kmn[data_ukelele.length - 4] = data_ukelele[data_ukelele.length - 4] data_kmn[data_ukelele.length - 3] = data_ukelele[data_ukelele.length - 3] @@ -266,25 +260,42 @@ export class KeylayoutToKmnConverter { data_kmn[data_ukelele.length - 1] = data_ukelele[data_ukelele.length - 1] //console.log(" _S2 convert finished\n", data_kmn) + // TODO add condition again return data_kmn //return (data_kmn.length === data_ukelele.length ) ? data_kmn : null } -/** @brief write data to file - * @param kmn_array the array holding keyboard data - * @return true if data has been written; false if not - */ - public write(kmn_array: any[]):boolean { - + /** + * @brief member function to write data to file + * @param kmn_array the array holding keyboard data + * @return true if data has been written; false if not + */ + //TODO need to use export const USVirtualKeyCodes here + public write(kmn_array: any[]): boolean { const kmn_Key_Name = [ - 'K_A','K_B','K_C','K_D','K_E','K_F','K_G','K_H','K_I','K_J','K_K','K_L','K_M','K_N','K_O','K_P','K_Q','K_R','K_S','K_T','K_U','K_V','K_W','K_X','K_Y','K_Z', - 'K_0','K_1','K_2','K_3','K_4','K_5','K_6','K_7','K_8','K_9', - 'K_SPACE', - 'K_ACCENT','K_HYPHEN','K_EQUAL', - 'K_LBRKT','KRBRKT','K_BKSLASH', - 'K_COLON','KQUOTE', - 'K_COMMA','K_PERIOD','K_SLASH', - 'K_xDF', 'K_OEM_102' + 'K_BKSP', 'K_TAB', 'K_ENTER', 'K_SHIFT', 'K_CONTROL', 'K_ALT', 'K_PAUSE', 'K_CAPS', //7 + 'K_ESC', 'K_SPACE', 'K_PGUP', 'K_PGDN', 'K_END', 'K_HOME', 'K_LEFT', 'K_UP', 'K_RIGHT', //16 + 'K_DOWN', 'K_SEL', 'K_PRINT', 'K_EXEC', 'K_INS', 'K_DEL', 'K_HELP', //23 + + 'K_0', 'K_1', 'K_2', 'K_3', 'K_4', 'K_5', 'K_6', 'K_7', 'K_8', 'K_9', //33 + + 'K_A', 'K_B', 'K_C', 'K_D', 'K_E', 'K_F', 'K_G', 'K_H', 'K_I', 'K_J', 'K_K', 'K_L', 'K_M', //46 + 'K_N', 'K_O', 'K_P', 'K_Q', 'K_R', 'K_S', 'K_T', 'K_U', 'K_V', 'K_W', 'K_X', 'K_Y', 'K_Z', //59 + + 'K_NP0', 'K_NP1', 'K_NP2', 'K_NP3', 'K_NP4', + 'K_NP5', 'K_NP6', 'K_NP7', 'K_NP8', 'K_NP9', + + 'K_NPSTAR', 'K_NPPLUS', 'K_SEPARATOR', 'K_NPMINUS', 'K_NPDOT', 'K_NPSLASH', + + 'K_F1', 'K_F2', 'K_F3', 'K_F4', 'K_F5', 'K_F6', + 'K_F7', 'K_F8', 'K_F9', 'K_F10', 'K_F11', 'K_F12', + + 'K_NUMLOCK', 'K_SCROLL', 'K_LSHIFT', + 'K_RSHIFT', 'K_LCONTROL', 'K_RCONTROL', + 'K_LALT', 'K_RALT', + + 'K_COLON', 'K_EQUAL', 'K_COMMA', 'K_HYPHEN', + 'K_PERIOD', 'K_SLASH', 'K_BKQUOTE', 'K_LBRKT', ] // ************************************************************* @@ -299,76 +310,85 @@ export class KeylayoutToKmnConverter { data += "store(&TARGETS) \'any\'\n" data += "store(&KEYBOARDVERSION) \'...\'\n" data += "store(©RIGHT) '© 2024 SIL International\n" - // what else ?? + // TODO what else ?? data += "begin Unicode > use(main)\n\n" data += "group(main) using keys\n" - data += "\n" // ************************************************************* // **** write rules ******************************************** // ************************************************************* - // if caps is used we need to add NCAPS in kmn-file - console.log("kmn_array",kmn_array) + + // if caps is used in .keylayout-file we need to add NCAPS in kmn-file + console.log("kmn_array", kmn_array) let isCAPSused = false - for (let i= 0 ; i < kmn_array[kmn_array.length-1].length; i++) { - if ( String((kmn_array[kmn_array.length-1][i]).indexOf("caps") !== -1 ) ) { + for (let i = 0; i < kmn_array[kmn_array.length - 1].length; i++) { + if (String((kmn_array[kmn_array.length - 1][i]).indexOf("caps") !== -1)) { isCAPSused = true } } - //for (let i = 0; i < kmn_array.length-1; i++) { - for (let i = 0; i < kmn_array.length-5; i++) { - for (let j = 0; j < kmn_array[0].length; j++) { + // TODO good explanation + // find all modifiers used per modifier combination + // find resulting character from + // loop through keys + for (let j = 0; j < kmn_array[0].length; j++) { + // loop through modigfiers + // TODO get rid og magic number 5 etc + for (let i = 0; i < kmn_array.length - 5; i++) { // get the modifier for the layer + // TODO get rid og magic number 5 etc //const label_modifier = this.create_modifier(kmn_array[kmn_array.length-1][i], isCAPSused) - const label_modifier = this.create_modifier(kmn_array[kmn_array.length-5][i], isCAPSused) + const label_modifier = this.create_modifier(kmn_array[kmn_array.length - 5][i], isCAPSused) - // get the character that will be written as result in kmn-file + // get the character from keymap-section of .keylayout-file that will be written as result in kmn-file const resulting_character = new TextDecoder().decode(kmn_array[i][j]) // remove if-stmt later, only here for better visability - if (resulting_character !== '') - data += `+ [` + label_modifier + ' ' + kmn_Key_Name[j] + `] > \'` + resulting_character +'\'\n' + if (resulting_character !== '') { + if (i === 0) + data += '\n' + data += `+ [` + label_modifier + ' ' + kmn_Key_Name[j] + `] > \'` + resulting_character + '\'\n' + } } - data += '\n' } + data += '\n' // ************************************************************* // **** write deadkeys ***************************************** // ************************************************************* - // val vk dk + // val vk dk /*+ [K_BKQUOTE] > dk(005e) + [K_EQUAL] > dk(00b4) + [SHIFT K_EQUAL] > dk(0060)*/ - - for ( let i=0; i 0) + // ToDo conditions? + if (data.length > 0) return true; else return false @@ -376,37 +396,45 @@ export class KeylayoutToKmnConverter { - public createHexFromChar(character :string ):string { - return '00' + character.charCodeAt(0).toString(16).slice(-4).toLowerCase() - } + //... helpers ............................................................................................. + // TODO move outside of class? + /** + * @brief member function to return the unicode value of a character + * @param character the value that will converted + * @return headecimal value of a character + */ + public getHexFromChar(character: string): string { + return '00' + character.charCodeAt(0).toString(16).slice(-4).toLowerCase() + } -/** - * @brief check if search_modifier is available in modifier_array - * @param search_modifier the value that will be searched for in modifier_array - * @param modifier_array the array holding all modifiers used - * @return true if search_modifier is found; false if not - */ - public isInArray(search_modifier:string, modifier_array: string[]):boolean { - for (let i =0; i < modifier_array.length; i++) { + /** + * @brief member function to check if search_modifier is already available in modifier_array + * @param search_modifier the value that will be searched for in modifier_array + * @param modifier_array the array holding all modifiers used in kmc-convert + * @return true if search_modifier is found; false if not + */ + // TODO better function? + public isInArray(search_modifier: string, modifier_array: string[]): boolean { + for (let i = 0; i < modifier_array.length; i++) { if (search_modifier === String(modifier_array[i])) return true } return false } -/** - * @brief create modifier in kmn-style from modifier of .keylayout-file - * @param keylayout_modifier the modifier value used in the .keylayout-file - * @return kmn_modifier the modifier value used in the .kmn-file - */ - public create_modifier(keylayout_modifier:any, isCAPSused:boolean):string { + /** + * @brief member function to create a string of modifiers in kmn-style from the modifierMap section of .keylayout-file + * @param keylayout_modifier the modifier value used in the .keylayout-file + * @return kmn_modifier the modifier value used in the .kmn-file + */ + public create_modifier(keylayout_modifier: any, isCAPSused: boolean): string { let add_modifier = "" let kmn_modifier = "" let kmn_ncaps = "" - // copy each modifier seperate element + // copy each modifier seperate element of array const modifier_state: string[] = keylayout_modifier.split(" "); // TODO review these conditions-> what else do I need? @@ -416,46 +444,46 @@ export class KeylayoutToKmnConverter { for (let i = 0; i < modifier_state.length; i++) { - if ( isCAPSused && (String(keylayout_modifier).indexOf("caps") === -1)) + if (isCAPSused && (String(keylayout_modifier).indexOf("caps") === -1)) kmn_ncaps = " NCAPS " // TODO go over, find more conditions & simplify - if ( String(modifier_state[i]) === "anyOption") add_modifier = "RALT " - else if ( String(modifier_state[i]) === "anyShift") add_modifier = "SHIFT " - else if ( String(modifier_state[i]) === "anyControl") add_modifier = "CTRL " + if (String(modifier_state[i]) === "anyOption") add_modifier = "RALT " + else if (String(modifier_state[i]) === "anyShift") add_modifier = "SHIFT " + else if (String(modifier_state[i]) === "anyControl") add_modifier = "CTRL " - else if ( String(modifier_state[i]) === "anyOption?") add_modifier = "" // does anyOption?... happen? - else if ( String(modifier_state[i]) === "anyShift?") add_modifier = "" - else if ( String(modifier_state[i]) === "anyControl?") add_modifier = "" + else if (String(modifier_state[i]) === "anyOption?") add_modifier = "" // does anyOption?... happen? + else if (String(modifier_state[i]) === "anyShift?") add_modifier = "" + else if (String(modifier_state[i]) === "anyControl?") add_modifier = "" - // RSHIFT, rshift, Rshift,...? - else if ( (String(modifier_state[i]) === "shift?" ) && this.isInArray('rshift',modifier_state)) add_modifier = "RSHIFT " - else if ( (String(modifier_state[i]) === "shift?" ) && this.isInArray('lshift',modifier_state)) add_modifier = "LSHIFT " - else if ( (String(modifier_state[i]) === "shift?" ) && this.isInArray('rshift',modifier_state) && this.isInArray('lshift',modifier_state)) add_modifier = "SHIFT " + // TODO naming RSHIFT, rshift, Rshift,...? + else if ((String(modifier_state[i]) === "shift?") && this.isInArray('rshift', modifier_state)) add_modifier = "RSHIFT " + else if ((String(modifier_state[i]) === "shift?") && this.isInArray('lshift', modifier_state)) add_modifier = "LSHIFT " + else if ((String(modifier_state[i]) === "shift?") && this.isInArray('rshift', modifier_state) && this.isInArray('lshift', modifier_state)) add_modifier = "SHIFT " - else if ( (String(modifier_state[i]) === "option?" ) && this.isInArray('rOption',modifier_state)) add_modifier = "ROPT " - else if ( (String(modifier_state[i]) === "option?" ) && this.isInArray('lOption',modifier_state)) add_modifier = "LOPT " - else if ( (String(modifier_state[i]) === "option?" ) && this.isInArray('rOption',modifier_state) && this.isInArray('lOption',modifier_state)) add_modifier = "OPT " + else if ((String(modifier_state[i]) === "option?") && this.isInArray('rOption', modifier_state)) add_modifier = "ROPT " + else if ((String(modifier_state[i]) === "option?") && this.isInArray('lOption', modifier_state)) add_modifier = "LOPT " + else if ((String(modifier_state[i]) === "option?") && this.isInArray('rOption', modifier_state) && this.isInArray('lOption', modifier_state)) add_modifier = "OPT " - else if ( (String(modifier_state[i]) === "ctrl?" ) && this.isInArray('rControl',modifier_state)) add_modifier = "RCTRL " - else if ( (String(modifier_state[i]) === "ctrl?" ) && this.isInArray('lControl',modifier_state)) add_modifier = "LCTRL " - else if ( (String(modifier_state[i]) === "ctrl?" ) && this.isInArray('rControl',modifier_state) && this.isInArray('lControl',modifier_state)) add_modifier = "CTRL " + else if ((String(modifier_state[i]) === "ctrl?") && this.isInArray('rControl', modifier_state)) add_modifier = "RCTRL " + else if ((String(modifier_state[i]) === "ctrl?") && this.isInArray('lControl', modifier_state)) add_modifier = "LCTRL " + else if ((String(modifier_state[i]) === "ctrl?") && this.isInArray('rControl', modifier_state) && this.isInArray('lControl', modifier_state)) add_modifier = "CTRL " // remove if modifier contains '?' except for 'caps?' e.g. 'shift?', 'ctrl?', ... - // is this correct: caps? => caps is not neccessary. If its not neccessary we need to write NCAPS. Correct? - else if ( String(modifier_state[i]) === "caps?" ) add_modifier = "NCAPS " - else if ( String(modifier_state[i]).charAt(modifier_state[i].length-1) === "?") add_modifier = "" + // TODO is this correct: caps? => caps is not neccessary. If its not neccessary we need to write NCAPS. Correct? + else if (String(modifier_state[i]) === "caps?") add_modifier = "NCAPS " + else if (String(modifier_state[i]).charAt(modifier_state[i].length - 1) === "?") add_modifier = "" else add_modifier = String(modifier_state[i]) + " " kmn_modifier += kmn_ncaps + add_modifier } - // replace duplicate entries with "" + // replace duplicate entries with "" // TODO better function const unique_Modifier: string[] = kmn_modifier.split(" ") - for(let i = 0; i < unique_Modifier.length; i++) { + for (let i = 0; i < unique_Modifier.length; i++) { const modi = unique_Modifier[i] - for(let j = i + 1; j < unique_Modifier.length; j++) { + for (let j = i + 1; j < unique_Modifier.length; j++) { const modi_next = unique_Modifier[j] if (modi_next === modi) unique_Modifier[j] = "" @@ -463,4 +491,54 @@ export class KeylayoutToKmnConverter { } return unique_Modifier.join(" ").replace(/\s+/g, " ").trim().toUpperCase() } -} \ No newline at end of file + + /** + * @brief member function to map Ukelele keycodes to a position of Key_Name_Arra + * @param in_from_ukelele Ukelele (=mac) keycodes + * @return position of Key_Name_Array ( the array holding all keynames) + */ + // TODO add all other keys + // TODO replace with mapping from constants + public map_UkeleleKC_To_kmn_Key_Name_Array_Position(in_from_ukelele: Uint16Array, pos: any): any { + // ukelele kc --> // kmn-Array kmn_Key_Name + // .keylayout-file // position in list + // code = .. // zerobased 0-... + if (pos === 0) return 34 // a + if (pos === 11) return 35 // b + if (pos === 8) return 36 // c + if (pos === 2) return 37 // d + if (pos === 14) return 38 // e + if (pos === 3) return 39 // f + if (pos === 5) return 40 // g + if (pos === 4) return 41 // h + if (pos === 34) return 42 // i + if (pos === 38) return 43 // j + if (pos === 40) return 44 // k + if (pos === 37) return 45 // l + if (pos === 46) return 46 // m + if (pos === 45) return 47 // n + if (pos === 31) return 48 // o + if (pos === 35) return 49 // p + if (pos === 12) return 50 // q + if (pos === 15) return 51 // r + if (pos === 1) return 52 // s + if (pos === 17) return 53 // t + if (pos === 32) return 54 // u + if (pos === 9) return 55 // v + if (pos === 13) return 56 // w + if (pos === 7) return 57 // x + if (pos === 6) return 58 // y + if (pos === 16) return 59 // z + if (pos === 18) return 25 // 1 + if (pos === 19) return 26 // 2 + if (pos === 20) return 27 // 3 + if (pos === 21) return 28 // 4 + if (pos === 22) return 29 // 5 + if (pos === 23) return 30 // 6 + if (pos === 26) return 31 // 7 + if (pos === 28) return 32 // 8 + if (pos === 25) return 33 // 9 + if (pos === 29) return 34 // 0 + return + } +} From d8f85d5cf5c538728ff08b321de0b7220123cc83 Mon Sep 17 00:00:00 2001 From: Sabine Date: Sun, 3 Nov 2024 08:51:32 +0100 Subject: [PATCH 013/251] Signed-off-by: Sabine feat(developer): kmc-convert: tidy up; kmn is written OK (for german) --- .../keylayout-to-kmn-converter.ts | 661 ++++++++++++++---- 1 file changed, 524 insertions(+), 137 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 226b2363774..eaa2367b8c0 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -35,14 +35,14 @@ export class KeylayoutToKmnConverter { } console.log(' _S2 first READ file ........................................'); - const inArray = this.read(inputFilename) + const inArray: object = this.read(inputFilename) if (!inArray) { return null; } console.log(' _S2 then CONVERT ........................................'); - const outArray = await this.convert(inArray); + const outArray: any = await this.convert(inArray); if (!outArray) { return null; @@ -64,7 +64,7 @@ export class KeylayoutToKmnConverter { * @param filename the ukelele .keylayout-file to be converted * @return in case of success Uint8Array keys_all_Layers; else null */ - public read(filename: string): Uint8Array[] { + public read(filename: string): object { /* // _S2 answer : + [K_A] > 'a' is OK / TODO which format to use in output ? + [K_A] > 'a' (character code) or + [K_A] > U+0061 (virt Keycode) // _S2 TODO which stores? @@ -87,9 +87,10 @@ export class KeylayoutToKmnConverter { // TODO array-> object const modifier_array: any[] = [] // array holding all MODIFIER strings e.g. "anyShift caps anyOption" -why not put modifiers into Uint8Array along with values of keys of layer + const data_output_all_Layers: any[] = [] const keys_action_all_Layers: any[] = [] // array holding all values with ACTION attribute (needed for finding deadkeys) - const deadkeys_all_Layers: any[] = [] // array holding all DEADKEYS for each mod state â, ê, ,.... - const data_all_Layers: any[] = [] // array holds ALL DATA: keys, output, action, dedkeys,... + const deadkeyedChars_all_Layers: any[] = [] // array holding all DEADKEYS for each mod state â, ê, ,.... + //const data_all_Layers: any[] = [] // array holds ALL DATA: keys, output, action, dedkeys,... // get data separated into data for output/action // loop through all ss-combin @@ -120,43 +121,35 @@ export class KeylayoutToKmnConverter { } // ......................................................... // create array of "action" and array of "output" - // ......................................................... - data_all_Layers[j] = keys_output_One_Layer // save all @output data ( will be used for conversion, write...) - keys_action_all_Layers[j] = keys_action_One_Layer // save all @action data ( will be used for deadkeys) + // data_all_Layers.push(keys_output_One_Layer) // save all @output data ( will be used for conversion, write...) + data_output_all_Layers.push(keys_output_One_Layer) // save all @output data ( will be used for conversion, write...) + keys_action_all_Layers.push(keys_action_One_Layer) // save all @action data ( will be used for deadkeys) } - - console.log('modifiers: ', modifier_array) - console.log('********************************************************') // ......................................................... // create array of "deadkey" / "deadkey names" - TODO can i use shorter function? // ......................................................... - const dk_vec2d: string[][] = [] + const dk_pairs_all_Layers: string[][] = [] for (let jj = 0; jj < jsonObj.keyboard.actions.action.length; jj++) { // if there is a "next" attribute-> it is a dk if (jsonObj.keyboard.actions.action[jj].when['@_next'] !== undefined) { const vec1d: string[] = [] vec1d.push(jsonObj.keyboard.actions.action[jj].when['@_next']) vec1d.push(jsonObj.keyboard.actions.action[jj]['@_id']) - dk_vec2d.push(vec1d) + dk_pairs_all_Layers.push(vec1d) } } - console.log('dk_vec2d', dk_vec2d) - console.log('********************************************************') // ......................................................... // create array of deadkey base ^ ´ ` // TODO needed to add and distribute? // ......................................................... const dk: string[] = []; - for (let k = 0; k < dk_vec2d.length; k++) { - dk.push(dk_vec2d[k][1]) + for (let k = 0; k < dk_pairs_all_Layers.length; k++) { + dk.push(dk_pairs_all_Layers[k][1]) } - console.log('dk: ', dk) - console.log('********************************************************') - // ......................................................... - // create array of "deadkeyables" - TODO can i use shorter function? + // create array of "deadkeyables_all_Layers" - TODO can i use shorter function? // ......................................................... - const deadkeyables: string[][] = [] + const deadkeyables_all_Layers: string[][] = [] for (let j = 0; j < jsonObj.keyboard.keyMapSet[0].keyMap.length; j++) { const deadkeyables_one: string[] = [] for (let i = 0; i < jsonObj.keyboard.keyMapSet[0].keyMap[0].key.length; i++) { @@ -164,67 +157,61 @@ export class KeylayoutToKmnConverter { if (resulting_character !== "") deadkeyables_one.push(resulting_character) } - deadkeyables.push(deadkeyables_one) - // filter out dk -> plain deadkeyables ( a,^, e,i,´,u => a,e,i,u) - // return all that don`t find ^,´, ` - deadkeyables[j] = deadkeyables[j].filter(function (el) { - return dk.indexOf(el) < 0; - }); + if (deadkeyables_one.length !== 0) { + deadkeyables_all_Layers.push(deadkeyables_one) + // filter out dk -> plain deadkeyables_all_Layers ( a,^, e,i,´,u => a,e,i,u) + // return all that don`t find ^,´, ` + deadkeyables_all_Layers[j] = deadkeyables_all_Layers[j].filter(function (el) { + return dk.indexOf(el) < 0; + }); + } } - console.log('deadkeyables per modifier state: ', deadkeyables) - console.log('********************************************************') - - console.log('keys_action_all_Layers ', keys_action_all_Layers) // ......................................................... - // TODO can i use shorter function? + // TODO can i use shorter function? -> yes use terminators // loop through all dk, key-actions and find @_action // find this value in // in their 'when' find output for dk - - // for all 'dk' - for (let i = 0; i < dk_vec2d.length; i++) { + // for all 'action' at keys paragraph + for (let j = 0; j < dk_pairs_all_Layers.length; j++) { const deadkeys_One_dk: any[] = [] - // for all 'action' at keys paragraph - for (let j = 0; j < keys_action_all_Layers.length; j++) { - // find in action e.g. - for (let k = 0; k < keys_action_all_Layers[j].length; k++) { - const action_from_keys_prargraph = new TextDecoder().decode(keys_action_all_Layers[j][k]) - - if (action_from_keys_prargraph !== "") { - // find the same id (e.g. ) in the actions-paragraph - for (let l = 0; l < jsonObj.keyboard.actions.action.length; l++) { - if (jsonObj.keyboard.actions.action[l]['@_id'] === action_from_keys_prargraph) { - // loop through when until dk name (e.g. dk s0) - for (let m = 0; m < jsonObj.keyboard.actions.action[l].when.length; m++) { - // and get their @_output - if (jsonObj.keyboard.actions.action[l].when[m]['@_state'] === dk_vec2d[i][0]) { - deadkeys_One_dk.push(jsonObj.keyboard.actions.action[l].when[m]['@_output']) - } + // find in action e.g. + for (let k = 0; k < keys_action_all_Layers[j].length; k++) { + const action_from_keys_prargraph = new TextDecoder().decode(keys_action_all_Layers[j][k]) + if (action_from_keys_prargraph !== "") { + // find the same id (e.g. ) in the actions-paragraph + for (let l = 0; l < jsonObj.keyboard.actions.action.length; l++) { + if (jsonObj.keyboard.actions.action[l]['@_id'] === action_from_keys_prargraph) { + // loop through when until dk name (e.g. dk s0) + for (let m = 0; m < jsonObj.keyboard.actions.action[l].when.length; m++) { + // and get their @_output + if (jsonObj.keyboard.actions.action[l].when[m]['@_state'] === dk_pairs_all_Layers[j][0]) { + deadkeys_One_dk.push(jsonObj.keyboard.actions.action[l].when[m]['@_output']) } } } } } } - deadkeys_all_Layers.push(deadkeys_One_dk) + deadkeyedChars_all_Layers.push(deadkeys_One_dk) } - // TODO data is in array multiple times?? - console.log('deadkeys per modifier state: ', deadkeys_all_Layers) - console.log('********************************************************') - - // is there a better way?? - // TODO do we need dk? - data_all_Layers[nrOfStates] = modifier_array // add all normal key data - data_all_Layers.push(dk_vec2d) // add dk-mapping ( dk1 <-> '^' ) - data_all_Layers.push(dk) // add plain dk ( '^', '´','`') - data_all_Layers.push(deadkeyables) // add char that can be modified with dk ( a,e,i,o,u) - data_all_Layers.push(deadkeys_all_Layers) // add modified keys ( â,ê,î,ô,û) + + const DataObject = { + name: "Ukelele-kmn", + ArrayOf_Ukelele_output: data_output_all_Layers, + ArrayOf_Ukelele_action: keys_action_all_Layers, + ArrayOf_Modifiers: modifier_array, + ArrayOf_VK_US: "", + ArrayOf_dk: dk_pairs_all_Layers, // add dk-mapping ( dk1 <-> '^' ) + ArrayOf_Dk: dk, // add plain dk ( '^', '´','`') + ArrayOf_deadkeyables: deadkeyables_all_Layers, // add char that can be modified with dk ( a,e,i,o,u) + ArrayOf_deadkeyedChar: deadkeyedChars_all_Layers // add modified keys ( â,ê,î,ô,û) + }; // TODO review condition - return data_all_Layers - return ((data_all_Layers.length === nrOfStates + 5) && data_all_Layers[0].length === nrOfKeys_inLayer) ? data_all_Layers : null; + return DataObject + return ((data_output_all_Layers.length === nrOfStates + 5) && data_output_all_Layers[0].length === nrOfKeys_inLayer) ? data_output_all_Layers : null; } /** @@ -232,37 +219,56 @@ export class KeylayoutToKmnConverter { * @param data_ukelele (Uint8Array) data of the ukelele .keylayout-file * @return outArray Uint8Array keys_all_Layers, the converted data for kmn-files if all layers have been converted; else null */ - public convert(data_ukelele: any[]): any[] { - //TODO sorting order: alphabetically OK? - - const data_kmn: any[] = []; - - // TODO get rid og magic number 5 etc - for (let j = 0; j < data_ukelele.length - 5; j++) { - const keys_singleLayer: Uint8Array[] = [] - // map Ukelele Keycodes to the position of the key in kmn_Key_Name - for (let i = 0; i < data_ukelele[j].length; i++) { - // TODO use mapping from standard constants - keys_singleLayer[this.map_UkeleleKC_To_kmn_Key_Name_Array_Position(data_ukelele[j][i], i)] = data_ukelele[j][i] - } - data_kmn[j] = keys_singleLayer + public convert(data_ukelele: any): any { + + const kmn_Key_Name1 = [ + 'K_BKSP', 'K_TAB', 'K_ENTER', 'K_SHIFT', 'K_CONTROL', 'K_ALT', 'K_PAUSE', 'K_CAPS', //7 + 'K_ESC', 'K_SPACE', 'K_PGUP', 'K_PGDN', 'K_END', 'K_HOME', 'K_LEFT', 'K_UP', 'K_RIGHT', //16 + 'K_DOWN', 'K_SEL', 'K_PRINT', 'K_EXEC', 'K_INS', 'K_DEL', 'K_HELP', //23 + + 'K_0', 'K_1', 'K_2', 'K_3', 'K_4', 'K_5', 'K_6', 'K_7', 'K_8', 'K_9', //33 + + 'K_A', 'K_B', 'K_C', 'K_D', 'K_E', 'K_F', 'K_G', 'K_H', 'K_I', 'K_J', 'K_K', 'K_L', 'K_M', //46 + 'K_N', 'K_O', 'K_P', 'K_Q', 'K_R', 'K_S', 'K_T', 'K_U', 'K_V', 'K_W', 'K_X', 'K_Y', 'K_Z', //59 + + 'K_NP0', 'K_NP1', 'K_NP2', 'K_NP3', 'K_NP4', + 'K_NP5', 'K_NP6', 'K_NP7', 'K_NP8', 'K_NP9', //69 + + 'K_NPSTAR', 'K_NPPLUS', 'K_SEPARATOR', 'K_NPMINUS', 'K_NPDOT', 'K_NPSLASH', //75 + + 'K_F1', 'K_F2', 'K_F3', 'K_F4', 'K_F5', 'K_F6', + 'K_F7', 'K_F8', 'K_F9', 'K_F10', 'K_F11', 'K_F12', // 87 + + 'K_NUMLOCK', 'K_SCROLL', 'K_LSHIFT', + 'K_RSHIFT', 'K_LCONTROL', 'K_RCONTROL', + 'K_LALT', 'K_RALT', //95 + + 'K_COLON', 'K_EQUAL', 'K_COMMA', 'K_HYPHEN', //99 + 'K_PERIOD', 'K_SLASH', 'K_BKQUOTE', 'K_LBRKT', 'K_RBRKT', //104 + ] + + const data_VKUS: any[][] = []; + const data_kmn: any[][] = []; + //const keys_singleLayer: Uint8Array[] = [] + + + for (let i = 0; i < data_ukelele.ArrayOf_Ukelele_output[0].length; i++) { + const data_VKUS_pos_pair: any[] = []; + const data_kmn_pair: any[] = []; + const keyName = kmn_Key_Name1[this.map_UkeleleKC_To_kmn_Key_Name_Array_Position_n(i)] + data_kmn_pair.push(i) + data_kmn_pair.push(this.map_UkeleleKC_To_kmn_Key_Name_Array_Position_n(i)) + data_VKUS_pos_pair.push(this.map_UkeleleKC_To_kmn_Key_Name_Array_Position_n(i)) + data_VKUS_pos_pair.push(keyName) + + data_VKUS.push(data_VKUS_pos_pair) + data_kmn.push(data_kmn_pair) } - // TODO use object !!! - //TODO copy the modifier states __ better idea? - //data_kmn[data_ukelele.length - 1] = data_ukelele[data_ukelele.length - 1] - - // TODO get rid og magic number 5 etc etc - data_kmn[data_ukelele.length - 5] = data_ukelele[data_ukelele.length - 5] - data_kmn[data_ukelele.length - 4] = data_ukelele[data_ukelele.length - 4] - data_kmn[data_ukelele.length - 3] = data_ukelele[data_ukelele.length - 3] - data_kmn[data_ukelele.length - 2] = data_ukelele[data_ukelele.length - 2] - data_kmn[data_ukelele.length - 1] = data_ukelele[data_ukelele.length - 1] - //console.log(" _S2 convert finished\n", data_kmn) - - // TODO add condition again - return data_kmn - //return (data_kmn.length === data_ukelele.length ) ? data_kmn : null + data_ukelele.ArrayOf_VK_US = data_VKUS + data_ukelele.ArrayOf_Kmn = data_kmn + + return data_ukelele } /** @@ -271,8 +277,8 @@ export class KeylayoutToKmnConverter { * @return true if data has been written; false if not */ //TODO need to use export const USVirtualKeyCodes here - public write(kmn_array: any[]): boolean { - const kmn_Key_Name = [ + public write(kmn_array: any): boolean { + /*const kmn_Key_Name = [ 'K_BKSP', 'K_TAB', 'K_ENTER', 'K_SHIFT', 'K_CONTROL', 'K_ALT', 'K_PAUSE', 'K_CAPS', //7 'K_ESC', 'K_SPACE', 'K_PGUP', 'K_PGDN', 'K_END', 'K_HOME', 'K_LEFT', 'K_UP', 'K_RIGHT', //16 'K_DOWN', 'K_SEL', 'K_PRINT', 'K_EXEC', 'K_INS', 'K_DEL', 'K_HELP', //23 @@ -285,18 +291,18 @@ export class KeylayoutToKmnConverter { 'K_NP0', 'K_NP1', 'K_NP2', 'K_NP3', 'K_NP4', 'K_NP5', 'K_NP6', 'K_NP7', 'K_NP8', 'K_NP9', - 'K_NPSTAR', 'K_NPPLUS', 'K_SEPARATOR', 'K_NPMINUS', 'K_NPDOT', 'K_NPSLASH', + 'K_NPSTAR', 'K_NPPLUS', 'K_SEPARATOR', 'K_NPMINUS', 'K_NPDOT', 'K_NPSLASH', //75 'K_F1', 'K_F2', 'K_F3', 'K_F4', 'K_F5', 'K_F6', - 'K_F7', 'K_F8', 'K_F9', 'K_F10', 'K_F11', 'K_F12', + 'K_F7', 'K_F8', 'K_F9', 'K_F10', 'K_F11', 'K_F12', // 85 'K_NUMLOCK', 'K_SCROLL', 'K_LSHIFT', 'K_RSHIFT', 'K_LCONTROL', 'K_RCONTROL', - 'K_LALT', 'K_RALT', + 'K_LALT', 'K_RALT', //93 - 'K_COLON', 'K_EQUAL', 'K_COMMA', 'K_HYPHEN', - 'K_PERIOD', 'K_SLASH', 'K_BKQUOTE', 'K_LBRKT', - ] + 'K_COLON', 'K_EQUAL', 'K_COMMA', 'K_HYPHEN', //97 + 'K_PERIOD', 'K_SLASH', 'K_BKQUOTE', 'K_LBRKT', //101 + ]*/ // ************************************************************* // **** write stores ******************************************* @@ -313,17 +319,21 @@ export class KeylayoutToKmnConverter { // TODO what else ?? data += "begin Unicode > use(main)\n\n" - data += "group(main) using keys\n" + data += "group(main) using keys\n\n" + + data += "Tipp: if K_? is replaced by undefined-> no enry in kmn_Key_Name=> add K_? there and it will be shown here" + data += "Tipp: keys that are marked with sction do not aoear in ukelele_Array_output->do not appear in kmn" + // ************************************************************* // **** write rules ******************************************** - // ************************************************************* + // *************************************************************^ // if caps is used in .keylayout-file we need to add NCAPS in kmn-file - console.log("kmn_array", kmn_array) let isCAPSused = false - for (let i = 0; i < kmn_array[kmn_array.length - 1].length; i++) { - if (String((kmn_array[kmn_array.length - 1][i]).indexOf("caps") !== -1)) { + for (let i = 0; i < kmn_array.ArrayOf_Modifiers.length; i++) { + isCAPSused = false + if (String((kmn_array.ArrayOf_Modifiers[i])).indexOf("caps") !== -1) { isCAPSused = true } } @@ -331,61 +341,75 @@ export class KeylayoutToKmnConverter { // TODO good explanation // find all modifiers used per modifier combination // find resulting character from + // loop through keys - for (let j = 0; j < kmn_array[0].length; j++) { - // loop through modigfiers - // TODO get rid og magic number 5 etc - for (let i = 0; i < kmn_array.length - 5; i++) { + //for (let j = 0; j \'` + resulting_character + '\'\n' + // TODO remove j + data += j + `+ [` + label_modifier + ' ' + vk_label + `] > \'` + resulting_character + '\'\n' } } } + data += '\n' // ************************************************************* // **** write deadkeys ***************************************** // ************************************************************* - // val vk dk - /*+ [K_BKQUOTE] > dk(005e) - + [K_EQUAL] > dk(00b4) - + [SHIFT K_EQUAL] > dk(0060)*/ + for (let i = 0; i < kmn_array.ArrayOf_Ukelele_action[0].length; i++) { + // loop through modifiers + for (let j = 0; j < kmn_array.ArrayOf_Modifiers.length; j++) { + + // get the modifier for the layer + const label_modifier = this.create_modifier(kmn_array.ArrayOf_Modifiers[j], isCAPSused) + + // get the character from keymap-section of .keylayout-file that will be written as result in kmn-file + const resulting_character = new TextDecoder().decode(kmn_array.ArrayOf_Ukelele_action[j][i]) + + if (resulting_character !== "") { + //get the VK_ - label + const vk_label = this.find_VK_X_in_ArrayOf_VK_US(kmn_array.ArrayOf_VK_US[i][0], kmn_array) - for (let i = 0; i < kmn_array[kmn_array.length - 3].length; i++) { - data += "+ [TODO] > dk(" + this.getHexFromChar(kmn_array[kmn_array.length - 3][i]) + ")\n" + for (let k = 0; k < kmn_array.ArrayOf_dk.length; k++) { + if ((resulting_character !== "") && (resulting_character === kmn_array.ArrayOf_dk[k][1])) { + data += '[' + label_modifier + vk_label + '] ' + "> dk(" + this.getHexFromChar(kmn_array.ArrayOf_dk[k][1]) + ") " + '\n' + } + } + } + } } - data += "\n" data += "\n" data += "match > use(deadkeys)\n\n" data += "group(deadkeys)\n" data += "\n" - // TODO n times dk, deadkeyables?? - for (let i = 0; i < (kmn_array[kmn_array.length - 2]).length; i++) { - if (kmn_array[kmn_array.length - 1][i] !== undefined) { - - data += "store(dkf" + this.getHexFromChar(kmn_array[kmn_array.length - 4][i][1]) + ") " + ("\'" + String(kmn_array[kmn_array.length - 2])).replace(/\,+/g, "' '").slice(0, -1) + "\n" - data += "store(dkt" + this.getHexFromChar(kmn_array[kmn_array.length - 4][i][1]) + ") " + ("\'" + String(kmn_array[kmn_array.length - 1][i])).replace(/\,+/g, "' '") + "'\n" + for (let i = 0; i < kmn_array.ArrayOf_deadkeyables.length; i++) { + if (kmn_array.ArrayOf_deadkeyedChar[i] !== undefined) { + data += "store(dkf" + this.getHexFromChar(kmn_array.ArrayOf_dk[i][1]) + ") " + ("\'" + String(kmn_array.ArrayOf_deadkeyables[i])).replace(/\,+/g, "' '") + "'\n" + data += "store(dkt" + this.getHexFromChar(kmn_array.ArrayOf_dk[i][1]) + ") " + ("\'" + String(kmn_array.ArrayOf_deadkeyedChar[i])).replace(/\,+/g, "' '") + "'\n" data += '\n' } } + // Todo use writefile from elsewhere writeFileSync("data/MyResult.kmn", data, { flag: "w" }) - console.log(" _S2 write finished\n") // ToDo conditions? if (data.length > 0) @@ -394,11 +418,18 @@ export class KeylayoutToKmnConverter { return false } - - - //... helpers ............................................................................................. + // 34->"K_A" + public find_VK_X_in_ArrayOf_VK_US(vk_in: any, data: any): any { + for (let i = 0; i < data.ArrayOf_VK_US.length; i++) { + if (data.ArrayOf_VK_US[i][0] === vk_in) { + return data.ArrayOf_VK_US[i][1] + } + } + return + } + // TODO move outside of class? /** * @brief member function to return the unicode value of a character @@ -499,7 +530,62 @@ export class KeylayoutToKmnConverter { */ // TODO add all other keys // TODO replace with mapping from constants - public map_UkeleleKC_To_kmn_Key_Name_Array_Position(in_from_ukelele: Uint16Array, pos: any): any { + public map_UkeleleKC_To_kmn_Key_Name_Array_Position_n(pos: any): any { + // ukelele kc --> // kmn-Array kmn_Key_Name + // .keylayout-file // position in list + // code = .. // zerobased 0-... + //const pos = Number(poss) + + if (pos === 0) return 34 // a + if (pos === 11) return 35 // b + if (pos === 8) return 36 // c + if (pos === 2) return 37 // d + if (pos === 14) return 38 // e + if (pos === 3) return 39 // f + if (pos === 5) return 40 // g + if (pos === 4) return 41 // h + if (pos === 34) return 42 // i + if (pos === 38) return 43 // j + if (pos === 40) return 44 // k + if (pos === 37) return 45 // l + if (pos === 46) return 46 // m + if (pos === 45) return 47 // n + if (pos === 31) return 48 // o + if (pos === 35) return 49 // p + if (pos === 12) return 50 // q + if (pos === 15) return 51 // r + if (pos === 1) return 52 // s + if (pos === 17) return 53 // t + if (pos === 32) return 54 // u + if (pos === 9) return 55 // v + if (pos === 13) return 56 // w + if (pos === 7) return 57 // x + if (pos === 6) return 58 // y + if (pos === 16) return 59 // z + if (pos === 18) return 25 // 1 + if (pos === 19) return 26 // 2 + if (pos === 20) return 27 // 3 + if (pos === 21) return 28 // 4 + if (pos === 23) return 29 // 5 + if (pos === 22) return 30 // 6 + if (pos === 26) return 31 // 7 + if (pos === 28) return 32 // 8 + if (pos === 25) return 33 // 9 + if (pos === 29) return 34 // 0 + if (pos === 24) return 97 // ´ EQUAL + if (pos === 10) return 102 // ^ BKQUOTE + if (pos === 33) return 103 // [ LBKT + if (pos === 30) return 104 // ] RBKT + + + /*if (pos === 187) return 100 // ^ + if (pos === 192) return 95 // ´*/ + + + return + } + + /*public map_UkeleleKC_To_kmn_Key_Name_Array_Position(in_from_ukelele: Uint16Array, pos: any): any { // ukelele kc --> // kmn-Array kmn_Key_Name // .keylayout-file // position in list // code = .. // zerobased 0-... @@ -539,6 +625,307 @@ export class KeylayoutToKmnConverter { if (pos === 28) return 32 // 8 if (pos === 25) return 33 // 9 if (pos === 29) return 34 // 0 + + + if (pos === 24) return 97 // ´ EQUAL + if (pos === 10) return 102 // ^ BKQUOTE + + if (pos === 187) return 100 // ^ + + return - } + }*/ + + + /* public map_UkeleleKC_To_kmn_Key_VK_Name(pos: any): any { + // ukelele kc --> // kmn-Array kmn_Key_Name + // .keylayout-file // position in list + // code = .. // zerobased 0-... + //const pos = Number(poss) + + if (pos === 0) return "K_A" // a + if (pos === 2) return "K_D" // d + if (pos === 3) return "K_F" // f + if (pos === 1) return "K_S" // s + if (pos === 11) return "K_B" // b + if (pos === 8) return "K_C" // c + /* if (pos === 14) return 38 // e + if (pos === 5) return 40 // g + if (pos === 4) return 41 // h + if (pos === 34) return 42 // i + if (pos === 38) return 43 // j + if (pos === 40) return 44 // k + if (pos === 37) return 45 // l + if (pos === 46) return 46 // m + if (pos === 45) return 47 // n + if (pos === 31) return 48 // o + if (pos === 35) return 49 // p + if (pos === 12) return 50 // q + if (pos === 15) return 51 // r + if (pos === 17) return 53 // t + if (pos === 32) return 54 // u + if (pos === 9) return 55 // v + if (pos === 13) return 56 // w + if (pos === 7) return 57 // x + if (pos === 6) return 58 // y + if (pos === 16) return 59 // z + if (pos === 18) return 25 // 1 + if (pos === 19) return 26 // 2 + if (pos === 20) return 27 // 3 + if (pos === 21) return 28 // 4 + if (pos === 22) return 29 // 5 + if (pos === 23) return 30 // 6 + if (pos === 26) return 31 // 7 + if (pos === 28) return 32 // 8 + if (pos === 25) return 33 // 9 + if (pos === 29) return 34 // 0 + + + if (pos === 187) return 100 // ^ + if (pos === 192) return 95 // ´ + + + return + }*/ + + // 34->0 + /*public find_pos_ofVK_in_ArrayOf_VK_US(vk_in: any, data: any): any { + for (let i = 0; i < data.ArrayOf_VK_US.length; i++) { + if (data.ArrayOf_VK_US[i][0] === vk_in) { + return i + } + } + return + }*/ + + // 34->0 + /* public find_pos_ofkmn_in_ArrayOf_kmn(pos_kmn: any, data: any): any { + for (let i = 0; i < data.ArrayOf_Kmn.length; i++) { + if (data.ArrayOf_Kmn[i][1] === pos_kmn) { + return i + } + } + return + }*/ + + //'^' -> 10 + /*public find_dk_in_uku_action(dk_in: any, data: any): any { + const chr = new TextDecoder().decode(data.ArrayOf_Ukelele_output[0][10]) + console.log("dk_in", dk_in, "chr", chr) + for (let j = 0; j < 8; j++) { + // console.log(data.ArrayOf_Ukelele[0]) + } + return 777 + }*/ + + // dk->"dk K_EQUAL" + /* public find_VK_X_in_ArrayOf_dk(vk_in: any, data: any): any { + for (let i = 0; i < data.ArrayOf_dk.length; i++) { + if (data.ArrayOf_dk[i][0] === vk_in) { + return data.ArrayOf_dk[i][1] + } + } + return + }*/ + } + +export const USVirtualKeyCodes = { + K_BKSP: 8, + K_TAB: 9, + K_ENTER: 13, + K_SHIFT: 16, + K_CONTROL: 17, + K_ALT: 18, + K_PAUSE: 19, + K_CAPS: 20, + K_ESC: 27, + K_SPACE: 32, + K_PGUP: 33, + K_PGDN: 34, + K_END: 35, + K_HOME: 36, + K_LEFT: 37, + K_UP: 38, + K_RIGHT: 39, + K_DOWN: 40, + K_SEL: 41, + K_PRINT: 42, + K_EXEC: 43, + K_INS: 45, + K_DEL: 46, + K_HELP: 47, + K_0: 48, + K_1: 49, + K_2: 50, + K_3: 51, + K_4: 52, + K_5: 53, + K_6: 54, + K_7: 55, + K_8: 56, + K_9: 57, + K_A: 65, + K_B: 66, + K_C: 67, + K_D: 68, + K_E: 69, + K_F: 70, + K_G: 71, + K_H: 72, + K_I: 73, + K_J: 74, + K_K: 75, + K_L: 76, + K_M: 77, + K_N: 78, + K_O: 79, + K_P: 80, + K_Q: 81, + K_R: 82, + K_S: 83, + K_T: 84, + K_U: 85, + K_V: 86, + K_W: 87, + K_X: 88, + K_Y: 89, + K_Z: 90, + K_NP0: 96, + K_NP1: 97, + K_NP2: 98, + K_NP3: 99, + K_NP4: 100, + K_NP5: 101, + K_NP6: 102, + K_NP7: 103, + K_NP8: 104, + K_NP9: 105, + K_NPSTAR: 106, + K_NPPLUS: 107, + K_SEPARATOR: 108, + K_NPMINUS: 109, + K_NPDOT: 110, + K_NPSLASH: 111, + K_F1: 112, + K_F2: 113, + K_F3: 114, + K_F4: 115, + K_F5: 116, + K_F6: 117, + K_F7: 118, + K_F8: 119, + K_F9: 120, + K_F10: 121, + K_F11: 122, + K_F12: 123, + K_NUMLOCK: 144, + K_SCROLL: 145, + K_LSHIFT: 160, + K_RSHIFT: 161, + K_LCONTROL: 162, + K_RCONTROL: 163, + K_LALT: 164, + K_RALT: 165, + K_COLON: 186, + K_EQUAL: 187, + K_COMMA: 188, + K_HYPHEN: 189, + K_PERIOD: 190, + K_SLASH: 191, + K_BKQUOTE: 192, + K_LBRKT: 219, + /** + * == K_OEM_5, 0xDC + */ + K_BKSLASH: 220, + K_RBRKT: 221, + K_QUOTE: 222, + /** + * ISO B00, key to right of left shift, not on US keyboard, + * 0xE2, K_OEM_102 + */ + K_oE2: 226, + K_OE2: 226, + K_oC1: 193, // ISO B11, ABNT-2 key to left of right shift, not on US keyboard + K_OC1: 193, + 'K_?C1': 193, + 'k_?C1': 193, + K_oDF: 0xDF, + K_ODF: 0xDF, + K_LOPT: 50001, + K_ROPT: 50002, + K_NUMERALS: 50003, + K_SYMBOLS: 50004, + K_CURRENCIES: 50005, + K_UPPER: 50006, + K_LOWER: 50007, + K_ALPHA: 50008, + K_SHIFTED: 50009, + K_ALTGR: 50010, + K_TABBACK: 50011, + K_TABFWD: 50012 +}; + +const k = USVirtualKeyCodes; + +export const UkeleleScanToUSVirtualKeyCodes = { + 0x12: k.K_1, /* 18 */ + 0x13: k.K_2, /* 19 */ + 0x14: k.K_3, /* 20 */ + 0x15: k.K_4, /* 21 */ + 0x17: k.K_5, /* 23 */ + 0x16: k.K_6, /* 22 */ + 0x1A: k.K_7, /* 26 */ + 0x1C: k.K_8, /* 28 */ + 0x19: k.K_9, /* 25 */ + 0x1D: k.K_0, /* 29 */ + 0x18: k.K_HYPHEN, /* 24 */ + 0x0A: k.K_EQUAL, /* 187 */ //changed + + 0x0C: k.K_Q, /* 12 */ + 0x0D: k.K_W, /* 13 */ + 0x0E: k.K_E, /* 14 */ + 0x0F: k.K_R, /* 15 */ + 0x11: k.K_T, /* 17 */ + 0x10: k.K_Y, /* 16 */ + 0x20: k.K_U, /* 32 */ + 0x22: k.K_I, /* 34 */ + 0x1F: k.K_O, /* 31 */ + 0x23: k.K_P, /* 35 */ + 0x21: k.K_LBRKT, + 0x1E: k.K_RBRKT, + + 0x00: k.K_A, /* 0 */ + 0x01: k.K_S, /* 1 */ + 0x02: k.K_D, /* 2 */ + 0x03: k.K_F, /* 3 */ + 0x05: k.K_G, /* 5 */ + 0x04: k.K_H, /* 4 */ + 0x26: k.K_J, /* 38 */ + 0x28: k.K_K, /* 40 */ + 0x25: k.K_L, /* 37 */ + 0x29: k.K_COLON, + 0x27: k.K_QUOTE, + 0x2A: k.K_BKQUOTE, /* 192 */ // changed + + 0x32: k.K_BKSLASH, /* ???*/ + + 0x06: k.K_Z, + 0x07: k.K_X, + 0x08: k.K_C, + 0x09: k.K_V, + 0x0B: k.K_B, + 0x2D: k.K_N, + 0x2E: k.K_M, + 0x2B: k.K_COMMA, + 0x2F: k.K_PERIOD, + 0x2C: k.K_SLASH, + + 0x31: k.K_SPACE, + + 0x56: k.K_oE2, // 86 << Same as 0x7D; found on iso, abnt2 + 0x73: k.K_oC1, + 0x7D: k.K_oE2, // << Same as 0x56; found on jis + +}; From 2503d9c58aebada831ebff437d3c89a47c35786e Mon Sep 17 00:00:00 2001 From: Sabine Date: Sat, 23 Nov 2024 17:26:57 +0100 Subject: [PATCH 014/251] feat(developer): kmc-convert: data in object; read more data from .keylayout and more --- .../keylayout-to-kmn-converter.ts | 348 ++++++++++++++---- 1 file changed, 276 insertions(+), 72 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index eaa2367b8c0..66dc896898f 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -6,6 +6,39 @@ import { CompilerCallbacks, CompilerOptions } from "@keymanapp/developer-utils"; import { ConverterToKmnArtifacts } from "../converter-artifacts.js"; +// TODO keylayout->kmn + +// write read, convert, write +// tests for 3 functions read write convert +// add data to object +// action/output:use filter etc to shorten func +// deadkeyables:use filter etc to shorten func +// dk-> for all action:use filter etc to shorten func +// remove unneccessa´ry data from dataObject +// rename symbols +// remove part using kmn_key_Name1 +// remove unnecceaasry map_UkeleleKC_To_kmn_Key_Name_Array_Position_n etc +// loop throught ANSI, JIS- art moment only use [0] +// remove func at teh end +// import { makePathToFixture } from '../../test/helpers/index.js'; // _S2 my imports +// Mapping 0->30 or 0->K_A-> missing entries in mapping +// Replace any-types +// Several steps action-> action-> action->character ( not only action->character) +// Usable for all keylayout files +// Return conditions +// Use callbacks as for writeFileSync +// Tests throws +// Use filter functions +// Conditions NCAPS,OPT;... +// Which stores +// TODO move func outside of class +// Functions as object methods? +// objects contain only used stuff READ in: -- out: only read arrays / CONVERT in: only read arrays out: return only to write arrays +// Use catch blocks for file read +// use + + +// TODO waht about using actions twice in a row??? // _S2 imports Sabine import { XMLParser } from 'fast-xml-parser'; // for reading a file import { readFileSync } from 'fs'; @@ -16,6 +49,7 @@ export class KeylayoutToKmnConverter { static readonly OUTPUT_FILE_EXTENSION = '.kmn'; // TODO use callbacks + //constructor(/*private*/ _callbacks: CompilerCallbacks, /*private*/ _options: CompilerOptions) { constructor(/*private*/ _callbacks: CompilerCallbacks, /*private*/ _options: CompilerOptions) { // TODO: if these are needed, uncomment /*private*/ and remove _, and they will then // be available as class properties @@ -34,7 +68,7 @@ export class KeylayoutToKmnConverter { throw new Error('Invalid parameters'); } - console.log(' _S2 first READ file ........................................'); + console.log(' _S2 first READ file ........................................in:', inputFilename); const inArray: object = this.read(inputFilename) if (!inArray) { @@ -70,15 +104,14 @@ export class KeylayoutToKmnConverter { // _S2 TODO which stores? // _S2 use var a = document.getElementById("target"); */ - + console.log("inputFilename read", filename) const options = { ignoreAttributes: false, attributeNamePrefix: '@_', // to access the attribute }; - // TODO create path from "filename" - //const xmlFile = readFileSync(`${process.cwd()}/data/MySample.keylayout`, 'utf8'); - const xmlFile = readFileSync(`${process.cwd()}/data/My_dk_Keyboard.keylayout`, 'utf8'); + //const xmlFile = readFileSync(`${process.cwd()}/data/MySample.keylayout`, 'utf8') + const xmlFile = readFileSync((process.cwd() + "\\data" + filename.substring(filename.lastIndexOf("\\"))).replace(" ", ""), 'utf8'); const parser = new XMLParser(options); const jsonObj = parser.parse(xmlFile); // get plain Object @@ -90,9 +123,25 @@ export class KeylayoutToKmnConverter { const data_output_all_Layers: any[] = [] const keys_action_all_Layers: any[] = [] // array holding all values with ACTION attribute (needed for finding deadkeys) const deadkeyedChars_all_Layers: any[] = [] // array holding all DEADKEYS for each mod state â, ê, ,.... - //const data_all_Layers: any[] = [] // array holds ALL DATA: keys, output, action, dedkeys,... + const terminators_all_Layers: any[] = [] // array holding all DEADKEYS for each mod state â, ê, ,.... + + // ......................................................... + // LAYOUTS: get all groups like ANSI JIS + // ......................................................... + const duplicate_layouts_array: any[] = [] + + for (let i = 0; i < jsonObj.keyboard.layouts.layout.length; i++) { + duplicate_layouts_array[i] = jsonObj.keyboard.layouts.layout[i]['@_mapSet'] + } + // remove duplicates + const layouts_array: any[] = duplicate_layouts_array.filter(function (item, pos, self) { + return self.indexOf(item) == pos; + }) + + // ......................................................... + // KEYMAP: get all keys for attribute "output" and "action" - TODO can i use shorter function? + // ......................................................... - // get data separated into data for output/action // loop through all ss-combin for (let j = 0; j < nrOfStates; j++) { // get modifier list e.g. "anyshift caps? anyOption" @@ -103,7 +152,7 @@ export class KeylayoutToKmnConverter { const keys_action_One_Layer: Uint8Array[] = [] // ......................................................... - // get all keys for attribute "output" ( y,c,b,...) - TODO can i use shorter function? + // KEYMAP: get all keys for attribute "output" ( y,c,b,...) - TODO can i use shorter function? // ......................................................... for (let i = 0; i < jsonObj.keyboard.keyMapSet[0].keyMap[j].key.length; i++) { if (jsonObj.keyboard.keyMapSet[0].keyMap[j].key[i]['@_output'] !== "\0") { @@ -113,7 +162,7 @@ export class KeylayoutToKmnConverter { } // ......................................................... - // get all keys for attribute "action" ( ^,a,e,i,...) - TODO can i use shorter function? + // KEYMAP: get all keys for attribute "action" ( ^,a,e,i,...) - TODO can i use shorter function? // ......................................................... if (jsonObj.keyboard.keyMapSet[0].keyMap[j].key[i]['@_action'] !== "\0") { keys_action_One_Layer[i] = new TextEncoder().encode(jsonObj.keyboard.keyMapSet[0].keyMap[j].key[i]['@_action']); @@ -121,12 +170,12 @@ export class KeylayoutToKmnConverter { } // ......................................................... // create array of "action" and array of "output" - // data_all_Layers.push(keys_output_One_Layer) // save all @output data ( will be used for conversion, write...) + // data_all_Layers.push(keys_output_One_Layer) // save all @output data ( will be used for conversion, write...) data_output_all_Layers.push(keys_output_One_Layer) // save all @output data ( will be used for conversion, write...) keys_action_all_Layers.push(keys_action_One_Layer) // save all @action data ( will be used for deadkeys) } // ......................................................... - // create array of "deadkey" / "deadkey names" - TODO can i use shorter function? + // ACTION: create array of "deadkey" / "deadkey names" - TODO can i use shorter function? // ......................................................... const dk_pairs_all_Layers: string[][] = [] for (let jj = 0; jj < jsonObj.keyboard.actions.action.length; jj++) { @@ -140,14 +189,15 @@ export class KeylayoutToKmnConverter { } // ......................................................... - // create array of deadkey base ^ ´ ` // TODO needed to add and distribute? + // ACTION: create array of deadkey base ^ ´ ` // TODO needed to add and distribute? // ......................................................... const dk: string[] = []; for (let k = 0; k < dk_pairs_all_Layers.length; k++) { dk.push(dk_pairs_all_Layers[k][1]) } + // ......................................................... - // create array of "deadkeyables_all_Layers" - TODO can i use shorter function? + // ACTION: create array of "deadkeyables_all_Layers" - TODO can i use shorter function? // ......................................................... const deadkeyables_all_Layers: string[][] = [] for (let j = 0; j < jsonObj.keyboard.keyMapSet[0].keyMap.length; j++) { @@ -167,9 +217,16 @@ export class KeylayoutToKmnConverter { }); } } + // ......................................................... + // TERMINATOR: create array of "terminators" - TODO can i use shorter function? what element of terminators do i need + // ......................................................... + for (let i = 0; i < jsonObj.keyboard.terminators.when.length; i++) { + terminators_all_Layers[i] = jsonObj.keyboard.terminators.when[i] + } // ......................................................... // TODO can i use shorter function? -> yes use terminators + // loop through all dk, key-actions and find @_action // find this value in // in their 'when' find output for dk @@ -197,18 +254,22 @@ export class KeylayoutToKmnConverter { deadkeyedChars_all_Layers.push(deadkeys_One_dk) } + // TODO remove unneccassary elements const DataObject = { name: "Ukelele-kmn", + ArrayOf_Layouts: layouts_array, ArrayOf_Ukelele_output: data_output_all_Layers, ArrayOf_Ukelele_action: keys_action_all_Layers, - ArrayOf_Modifiers: modifier_array, + ArrayOf_Modifiers: modifier_array, ArrayOf_VK_US: "", + ArrayOf_SC_MacWin: "", ArrayOf_dk: dk_pairs_all_Layers, // add dk-mapping ( dk1 <-> '^' ) ArrayOf_Dk: dk, // add plain dk ( '^', '´','`') ArrayOf_deadkeyables: deadkeyables_all_Layers, // add char that can be modified with dk ( a,e,i,o,u) - ArrayOf_deadkeyedChar: deadkeyedChars_all_Layers // add modified keys ( â,ê,î,ô,û) + ArrayOf_deadkeyedChar: deadkeyedChars_all_Layers, // add modified keys ( â,ê,î,ô,û) + ArrayOf_Terminators: terminators_all_Layers // add terminators ( ^,´,`) }; - + console.log("DataObject", DataObject) // TODO review condition return DataObject return ((data_output_all_Layers.length === nrOfStates + 5) && data_output_all_Layers[0].length === nrOfKeys_inLayer) ? data_output_all_Layers : null; @@ -221,6 +282,7 @@ export class KeylayoutToKmnConverter { */ public convert(data_ukelele: any): any { + // TODO remove const kmn_Key_Name1 = [ 'K_BKSP', 'K_TAB', 'K_ENTER', 'K_SHIFT', 'K_CONTROL', 'K_ALT', 'K_PAUSE', 'K_CAPS', //7 'K_ESC', 'K_SPACE', 'K_PGUP', 'K_PGDN', 'K_END', 'K_HOME', 'K_LEFT', 'K_UP', 'K_RIGHT', //16 @@ -249,28 +311,38 @@ export class KeylayoutToKmnConverter { const data_VKUS: any[][] = []; const data_kmn: any[][] = []; + const data_mac_Win: any[][] = []; //const keys_singleLayer: Uint8Array[] = [] - + // use UkeleleKeyCodeToScanCodes !!! for (let i = 0; i < data_ukelele.ArrayOf_Ukelele_output[0].length; i++) { const data_VKUS_pos_pair: any[] = []; + const data_mac_US_pair: any[] = []; const data_kmn_pair: any[] = []; const keyName = kmn_Key_Name1[this.map_UkeleleKC_To_kmn_Key_Name_Array_Position_n(i)] data_kmn_pair.push(i) data_kmn_pair.push(this.map_UkeleleKC_To_kmn_Key_Name_Array_Position_n(i)) data_VKUS_pos_pair.push(this.map_UkeleleKC_To_kmn_Key_Name_Array_Position_n(i)) data_VKUS_pos_pair.push(keyName) + data_mac_US_pair.push(i) + // data_mac_US_pair.push(this.map_UkeleleKC_To_Win_KC(i)) + data_mac_US_pair.push(keyName) data_VKUS.push(data_VKUS_pos_pair) data_kmn.push(data_kmn_pair) + data_mac_Win.push(data_mac_US_pair) } data_ukelele.ArrayOf_VK_US = data_VKUS data_ukelele.ArrayOf_Kmn = data_kmn + data_ukelele.ArrayOf_SC_MacWin = data_mac_Win + console.log("data_ukelele.ArrayOf_VK_US", data_ukelele.ArrayOf_VK_US) + console.log("data_ukelele.ArrayOf_SC_MacWin", data_ukelele.ArrayOf_SC_MacWin) return data_ukelele } + /** * @brief member function to write data to file * @param kmn_array the array holding keyboard data @@ -321,22 +393,50 @@ export class KeylayoutToKmnConverter { data += "begin Unicode > use(main)\n\n" data += "group(main) using keys\n\n" - data += "Tipp: if K_? is replaced by undefined-> no enry in kmn_Key_Name=> add K_? there and it will be shown here" - data += "Tipp: keys that are marked with sction do not aoear in ukelele_Array_output->do not appear in kmn" - + data += "Tipp: if K_? is replaced by undefined-> no enry in kmn_Key_Name=> add K_? there and it will be shown here\n" + data += "Tipp: keys that are marked with sction do not aoear in ukelele_Array_output->do not appear in kmn\n" + data += "\n" // ************************************************************* // **** write rules ******************************************** // *************************************************************^ + + + + /* + const numbers: number[] = [11, 23, 45, 89, 7, 98]; + const filteredNumbers: number[] = numbers.filter((num) => num > 10); + console.log(filteredNumbers); + + const words: string[] = ["apple", "banana", "cherry", "date"]; + const filteredWords: string[] = words.filter((word) => word.length > 5); + console.log(filteredWords); + + // now with kmc-convert: + const varToFind= kmn_array.ArrayOf_VK_US[2][0] + const numbersMy: number[][] = kmn_array.ArrayOf_VK_US + const filteredNumbersMy = numbersMy.filter(innerArray => innerArray[0] === varToFind); + + console.log("ArrayOf_VK_US",kmn_array.ArrayOf_VK_US ); + console.log("kmn_array.ArrayOf_VK_US[x][0]",varToFind ); + console.log("filteredNumbersMy",filteredNumbersMy);*/ + /* +const vk_label_test = this.find_VK_X_in_ArrayOf_VK_US(kmn_array.ArrayOf_VK_US[0][0], kmn_array) +console.log("kmn_array",kmn_array.ArrayOf_VK_US, "(kmn_array.ArrayOf_VK_US[0][0]",kmn_array.ArrayOf_VK_US[0][0]) +const vl_label2= kmn_array.ArrayOf_VK_US[0].filter((num:number) => num ===kmn_array.ArrayOf_VK_US[0][0]) +console.log("§§§§§§§§§§§§§§§§§§§§§§§§", vk_label_test,"--", vl_label2, vl_label2===vk_label_test,kmn_array.ArrayOf_VK_US[vl_label2][1] )*/ + + + + // if caps is used in .keylayout-file we need to add NCAPS in kmn-file let isCAPSused = false - for (let i = 0; i < kmn_array.ArrayOf_Modifiers.length; i++) { - isCAPSused = false - if (String((kmn_array.ArrayOf_Modifiers[i])).indexOf("caps") !== -1) { - isCAPSused = true - } - } + const modi: string[] = kmn_array.ArrayOf_Modifiers; + const filteredModifiers: string[] = modi.filter((mod) => (String(mod) === ("caps"))) + if (filteredModifiers.indexOf("caps") >= 0) + isCAPSused = true + // TODO good explanation // find all modifiers used per modifier combination @@ -346,6 +446,8 @@ export class KeylayoutToKmnConverter { //for (let j = 0; j item[0] === kmn_array.ArrayOf_SC_MacWin[j][0]) - if (resulting_character !== '') { - if (i === 0) - data += '\n' - // TODO remove j - data += j + `+ [` + label_modifier + ' ' + vk_label + `] > \'` + resulting_character + '\'\n' - } + // TODO remove j + if (resulting_character !== '') + data += j + `+ [` + (label_modifier + ' ' + vk_label[0][1]).trim() + `] > \'` + resulting_character + '\'\n' } } @@ -384,11 +484,12 @@ export class KeylayoutToKmnConverter { if (resulting_character !== "") { //get the VK_ - label - const vk_label = this.find_VK_X_in_ArrayOf_VK_US(kmn_array.ArrayOf_VK_US[i][0], kmn_array) + const VK: number[][] = kmn_array.ArrayOf_SC_MacWin + const vk_label = VK.filter(item => item[0] === kmn_array.ArrayOf_SC_MacWin[i][0]) for (let k = 0; k < kmn_array.ArrayOf_dk.length; k++) { if ((resulting_character !== "") && (resulting_character === kmn_array.ArrayOf_dk[k][1])) { - data += '[' + label_modifier + vk_label + '] ' + "> dk(" + this.getHexFromChar(kmn_array.ArrayOf_dk[k][1]) + ") " + '\n' + data += '[' + (label_modifier + ' ' + vk_label[0][1]).trim() + '] ' + "> dk(" + this.getHexFromChar(kmn_array.ArrayOf_dk[k][1]) + ") " + '\n' } } } @@ -420,6 +521,7 @@ export class KeylayoutToKmnConverter { //... helpers ............................................................................................. + // 34->"K_A" public find_VK_X_in_ArrayOf_VK_US(vk_in: any, data: any): any { for (let i = 0; i < data.ArrayOf_VK_US.length; i++) { @@ -440,21 +542,6 @@ export class KeylayoutToKmnConverter { return '00' + character.charCodeAt(0).toString(16).slice(-4).toLowerCase() } - /** - * @brief member function to check if search_modifier is already available in modifier_array - * @param search_modifier the value that will be searched for in modifier_array - * @param modifier_array the array holding all modifiers used in kmc-convert - * @return true if search_modifier is found; false if not - */ - // TODO better function? - public isInArray(search_modifier: string, modifier_array: string[]): boolean { - for (let i = 0; i < modifier_array.length; i++) { - if (search_modifier === String(modifier_array[i])) - return true - } - return false - } - /** * @brief member function to create a string of modifiers in kmn-style from the modifierMap section of .keylayout-file * @param keylayout_modifier the modifier value used in the .keylayout-file @@ -488,17 +575,17 @@ export class KeylayoutToKmnConverter { else if (String(modifier_state[i]) === "anyControl?") add_modifier = "" // TODO naming RSHIFT, rshift, Rshift,...? - else if ((String(modifier_state[i]) === "shift?") && this.isInArray('rshift', modifier_state)) add_modifier = "RSHIFT " - else if ((String(modifier_state[i]) === "shift?") && this.isInArray('lshift', modifier_state)) add_modifier = "LSHIFT " - else if ((String(modifier_state[i]) === "shift?") && this.isInArray('rshift', modifier_state) && this.isInArray('lshift', modifier_state)) add_modifier = "SHIFT " + else if ((String(modifier_state[i]) === "shift?") && modifier_state.includes('rshift')) add_modifier = "RSHIFT " + else if ((String(modifier_state[i]) === "shift?") && modifier_state.includes('lshift')) add_modifier = "LSHIFT " + else if ((String(modifier_state[i]) === "shift?") && modifier_state.includes('rshift') && modifier_state.includes('lshift')) add_modifier = "SHIFT " - else if ((String(modifier_state[i]) === "option?") && this.isInArray('rOption', modifier_state)) add_modifier = "ROPT " - else if ((String(modifier_state[i]) === "option?") && this.isInArray('lOption', modifier_state)) add_modifier = "LOPT " - else if ((String(modifier_state[i]) === "option?") && this.isInArray('rOption', modifier_state) && this.isInArray('lOption', modifier_state)) add_modifier = "OPT " + else if ((String(modifier_state[i]) === "option?") && modifier_state.includes('rOption')) add_modifier = "ROPT " + else if ((String(modifier_state[i]) === "option?") && modifier_state.includes('lOption')) add_modifier = "LOPT " + else if ((String(modifier_state[i]) === "option?") && modifier_state.includes('rOption') && modifier_state.includes('lOption')) add_modifier = "OPT " - else if ((String(modifier_state[i]) === "ctrl?") && this.isInArray('rControl', modifier_state)) add_modifier = "RCTRL " - else if ((String(modifier_state[i]) === "ctrl?") && this.isInArray('lControl', modifier_state)) add_modifier = "LCTRL " - else if ((String(modifier_state[i]) === "ctrl?") && this.isInArray('rControl', modifier_state) && this.isInArray('lControl', modifier_state)) add_modifier = "CTRL " + else if ((String(modifier_state[i]) === "ctrl?") && modifier_state.includes('rControl')) add_modifier = "RCTRL " + else if ((String(modifier_state[i]) === "ctrl?") && modifier_state.includes('lControl')) add_modifier = "LCTRL " + else if ((String(modifier_state[i]) === "ctrl?") && modifier_state.includes('rControl') && modifier_state.includes('lControl')) add_modifier = "CTRL " // remove if modifier contains '?' except for 'caps?' e.g. 'shift?', 'ctrl?', ... // TODO is this correct: caps? => caps is not neccessary. If its not neccessary we need to write NCAPS. Correct? @@ -510,22 +597,18 @@ export class KeylayoutToKmnConverter { kmn_modifier += kmn_ncaps + add_modifier } - // replace duplicate entries with "" // TODO better function - const unique_Modifier: string[] = kmn_modifier.split(" ") - for (let i = 0; i < unique_Modifier.length; i++) { - const modi = unique_Modifier[i] - for (let j = i + 1; j < unique_Modifier.length; j++) { - const modi_next = unique_Modifier[j] - if (modi_next === modi) - unique_Modifier[j] = "" - } - } + // remove duplicate and empty entries + const duplicate_modifier_array: string[] = kmn_modifier.split(" ").filter(item => item) + const unique_Modifier: string[] = duplicate_modifier_array.filter(function (item, pos, self) { + return self.indexOf(item) == pos; + }) + return unique_Modifier.join(" ").replace(/\s+/g, " ").trim().toUpperCase() } - /** +/** * @brief member function to map Ukelele keycodes to a position of Key_Name_Arra - * @param in_from_ukelele Ukelele (=mac) keycodes + * @param pos Ukelele (=mac) keycodes * @return position of Key_Name_Array ( the array holding all keynames) */ // TODO add all other keys @@ -585,6 +668,66 @@ export class KeylayoutToKmnConverter { return } + /** + * @brief member function to map Ukelele keycodes to a Windows Keycodes + * @param pos Ukelele (=mac) keycodes + * @return keycode on Win Keyboard + */ + // TODO finish all entries + public map_UkeleleKC_To_Win_KC(pos: any): any { + // ukelele KC --> // kmn win KC + + if (pos === 0x06) return 0x2D /* z, /* */ + if (pos === 0x07) return 0x2E /* X, /* */ + if (pos === 0x08) return 0x2E /* C, /* */ + if (pos === 0x09) return 0x2F /* V, /* */ + if (pos === 0x0B) return 0x30 /* B, /* */ + if (pos === 0x2D) return 0x31 /* N, /* */ + if (pos === 0x2E) return 0x32 /* M, /* */ + + + if (pos === 0x00) return 0x1E /* A, /* */ + if (pos === 0x01) return 0x1F /* S, /* */ + if (pos === 0x02) return 0x20 /* D, /* */ + if (pos === 0x03) return 0x21 /* F, /* */ + if (pos === 0x05) return 0x22 /* G, /* */ + if (pos === 0x04) return 0x23 /* H, /* */ + if (pos === 0x26) return 0x24 /* J, /* */ + if (pos === 0x28) return 0x25 /* K, /* */ + if (pos === 0x25) return 0x26 /* L, /* */ + /* 0x29) return 0x /* COLON, + if (pos === 0x27) return 0x /* QUOTE, + if (pos === 0x2A) return 0x /* BKQUOTE, /* 192 */ // changed + /* + if (pos === 0x32) return 0x /* BKSLASH, /* ???*/ + if (pos === 0x0C) return 0x10 /* Q, /* 12 */ + if (pos === 0x0D) return 0x11 /* W, /* 13 */ + if (pos === 0x0E) return 0x12 /* E, /* 14 */ + if (pos === 0x0F) return 0x13 /* R, /* 15 */ + if (pos === 0x11) return 0x14 /* T, /* 17 */ + if (pos === 0x10) return 0x15 /* Y, /* 16 */ + if (pos === 0x20) return 0x16 /* U, /* 32 */ + if (pos === 0x22) return 0x17 /* I, /* 4 */ + if (pos === 0x1F) return 0x18 /* O, /* 31 */ + if (pos === 0x23) return 0x19 /* P, /* 35 */ + /* if (pos === 0x21) return k.K_LBRKT, + if (pos === 0x1E) return k.K_RBRKT,/* + + + if (pos === 0x2B) return 0x /* COMMA, + if (pos === 0x2F) return 0x /* PERIOD, + if (pos === 0x2C) return 0x /* SLASH, + + if (pos === 0x31) return 0x /* SPACE, + + if (pos === 0x56) return 0x /* oE2, // 86 << Same as 0x7D; found on iso, abnt2 + if (pos === 0x73) return 0x /* oC1, + if (pos === 0x7D) return 0x /* oE2, // << Same as 0x56; found on jis + */ + + } + + // _S2 can probably go /*public map_UkeleleKC_To_kmn_Key_Name_Array_Position(in_from_ukelele: Uint16Array, pos: any): any { // ukelele kc --> // kmn-Array kmn_Key_Name // .keylayout-file // position in list @@ -644,11 +787,12 @@ export class KeylayoutToKmnConverter { //const pos = Number(poss) if (pos === 0) return "K_A" // a + if (pos === 1) return "K_S" // s if (pos === 2) return "K_D" // d if (pos === 3) return "K_F" // f - if (pos === 1) return "K_S" // s if (pos === 11) return "K_B" // b if (pos === 8) return "K_C" // c + /* if (pos === 14) return 38 // e if (pos === 5) return 40 // g if (pos === 4) return 41 // h @@ -729,7 +873,21 @@ export class KeylayoutToKmnConverter { }*/ } +/* +function iscapsUsedInVal(num:any) { + if (String(num)===("caps")) + return true +else return false +}*/ +/*function iscapsUsedInVal_(accumulator:any, num:any) { + if (String(num)===("caps")) + return (accumulator && true) +else return (accumulator && false) +}*/ + + + // _S2 can probably go export const USVirtualKeyCodes = { K_BKSP: 8, K_TAB: 9, @@ -867,8 +1025,10 @@ export const USVirtualKeyCodes = { K_TABFWD: 50012 }; + // _S2 can probably go const k = USVirtualKeyCodes; + // _S2 can probably go export const UkeleleScanToUSVirtualKeyCodes = { 0x12: k.K_1, /* 18 */ 0x13: k.K_2, /* 19 */ @@ -929,3 +1089,47 @@ export const UkeleleScanToUSVirtualKeyCodes = { 0x7D: k.K_oE2, // << Same as 0x56; found on jis }; + +// _S2 can probably go +/* +export const UkeleleKeyCodeToScanCodes = { + + 0x00: 0x1E, /* A, /* 0 + 0x01: 0x1F, /* S, /* 1 + 0x02: 0x20 ,/* D, /* 2 + 0x03: 0x21 ,/* F, /* 3 + 0x05: 0x22 ,/* G, /* 5 + 0x04: 0x23 ,/* H, /* 4 + 0x26: 0x24 ,/* J, /* 38 + 0x28: 0x25 ,/* K, /* 40 + 0x25: 0x26 ,/* L, /* 37 + /* 0x29: 0x ,/* COLON, + 0x27: 0x ,/* QUOTE, + 0x2A: 0x ,/* BKQUOTE, /* 192 // changed +/* + 0x32: 0x ,/* BKSLASH, /* ??? + 0x0C: 0x10 ,/* Q, /* 12 + 0x0D: 0x11 ,/* W, /* 13 + 0x0E: 0x12 ,/* E, /* 14 + 0x0F: 0x13 ,/* R, /* 15 + 0x11: 0x14 ,/* T, /* 17 + 0x10: 0x15 ,/* Y, /* 16 + 0x20: 0x16 ,/* U, /* 32 + 0x22: 0x17 ,/* I, /* 4 + 0x1F: 0x18 ,/* O, /* 31 + 0x23: 0x19 ,/* P, /* 35 + 0x21: k.K_LBRKT, + 0x1E: k.K_RBRKT, + +/* + 0x2B: 0x ,/* COMMA, + 0x2F: 0x ,/* PERIOD, + 0x2C: 0x ,/* SLASH, + + 0x31: 0x ,/* SPACE, + + 0x56: 0x ,/* oE2, // 86 << Same as 0x7D; found on iso, abnt2 + 0x73: 0x ,/* oC1, + 0x7D: 0x ,/* oE2, // << Same as 0x56; found on jis + +};*/ From a0032e88a072ba6a07ee0e4ffadd511d9848e593 Mon Sep 17 00:00:00 2001 From: Sabine Date: Mon, 25 Nov 2024 09:43:08 +0100 Subject: [PATCH 015/251] feat(developer): kmc-convert: add LAYOUTS (ANSI JIS) and terminators --- .../keylayout-to-kmn-converter.ts | 76 ++++++++++--------- 1 file changed, 41 insertions(+), 35 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 66dc896898f..1d5e9595fb7 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -11,6 +11,7 @@ import { ConverterToKmnArtifacts } from "../converter-artifacts.js"; // write read, convert, write // tests for 3 functions read write convert // add data to object +// Use filter functions // action/output:use filter etc to shorten func // deadkeyables:use filter etc to shorten func // dk-> for all action:use filter etc to shorten func @@ -18,8 +19,8 @@ import { ConverterToKmnArtifacts } from "../converter-artifacts.js"; // rename symbols // remove part using kmn_key_Name1 // remove unnecceaasry map_UkeleleKC_To_kmn_Key_Name_Array_Position_n etc -// loop throught ANSI, JIS- art moment only use [0] -// remove func at teh end +// loop throught ANSI, JIS- art moment only use [keyMapSet_count] (keyMapSet_count=0) +// remove funcs at teh end // import { makePathToFixture } from '../../test/helpers/index.js'; // _S2 my imports // Mapping 0->30 or 0->K_A-> missing entries in mapping // Replace any-types @@ -28,13 +29,13 @@ import { ConverterToKmnArtifacts } from "../converter-artifacts.js"; // Return conditions // Use callbacks as for writeFileSync // Tests throws -// Use filter functions // Conditions NCAPS,OPT;... // Which stores // TODO move func outside of class // Functions as object methods? // objects contain only used stuff READ in: -- out: only read arrays / CONVERT in: only read arrays out: return only to write arrays // Use catch blocks for file read + // use @@ -43,6 +44,8 @@ import { ConverterToKmnArtifacts } from "../converter-artifacts.js"; import { XMLParser } from 'fast-xml-parser'; // for reading a file import { readFileSync } from 'fs'; import { writeFileSync } from "fs"; // for writing a file +import * as fs from 'fs'; // what is this/do I need it? - either import all or seperately like above + export class KeylayoutToKmnConverter { static readonly INPUT_FILE_EXTENSION = '.keylayout'; @@ -50,7 +53,7 @@ export class KeylayoutToKmnConverter { // TODO use callbacks //constructor(/*private*/ _callbacks: CompilerCallbacks, /*private*/ _options: CompilerOptions) { - constructor(/*private*/ _callbacks: CompilerCallbacks, /*private*/ _options: CompilerOptions) { + constructor(private callbacks: CompilerCallbacks, /*private*/ _options: CompilerOptions) { // TODO: if these are needed, uncomment /*private*/ and remove _, and they will then // be available as class properties } @@ -102,7 +105,6 @@ export class KeylayoutToKmnConverter { /* // _S2 answer : + [K_A] > 'a' is OK / TODO which format to use in output ? + [K_A] > 'a' (character code) or + [K_A] > U+0061 (virt Keycode) // _S2 TODO which stores? - // _S2 use var a = document.getElementById("target"); */ console.log("inputFilename read", filename) const options = { @@ -112,23 +114,32 @@ export class KeylayoutToKmnConverter { //const xmlFile = readFileSync(`${process.cwd()}/data/MySample.keylayout`, 'utf8') const xmlFile = readFileSync((process.cwd() + "\\data" + filename.substring(filename.lastIndexOf("\\"))).replace(" ", ""), 'utf8'); + + // we don`t need file-read with uint8array return + const fullPath = (process.cwd() + "\\data" + filename.substring(filename.lastIndexOf("\\"))).replace(" ", "") + const xmlFile1 = this.callbacks.loadFile(fullPath) + console.log("xmlFile1",xmlFile1) + //console.log("xmlFile",xmlFile) + const parser = new XMLParser(options); const jsonObj = parser.parse(xmlFile); // get plain Object - const nrOfStates = jsonObj.keyboard.keyMapSet[0].keyMap.length - const nrOfKeys_inLayer = jsonObj.keyboard.keyMapSet[0].keyMap[0].key.length // will they all have the same length later ? + const keyMapSet_count =0 + const nrOfStates = jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap.length + const nrOfKeys_inLayer = jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap[0].key.length // will they all have the same length later ? + // ToDo naming // TODO array-> object + const duplicate_layouts_array: any[] = [] const modifier_array: any[] = [] // array holding all MODIFIER strings e.g. "anyShift caps anyOption" -why not put modifiers into Uint8Array along with values of keys of layer const data_output_all_Layers: any[] = [] const keys_action_all_Layers: any[] = [] // array holding all values with ACTION attribute (needed for finding deadkeys) - const deadkeyedChars_all_Layers: any[] = [] // array holding all DEADKEYS for each mod state â, ê, ,.... - const terminators_all_Layers: any[] = [] // array holding all DEADKEYS for each mod state â, ê, ,.... + const deadkeyedChars_all_Layers: any[] = [] // array holding all DEADKEYS for each mod state â, ê, ,.... + const terminators_all_Layers: any[] = [] // array holding all DEADKEYS for each mod state â, ê, ,.... // ......................................................... // LAYOUTS: get all groups like ANSI JIS // ......................................................... - const duplicate_layouts_array: any[] = [] for (let i = 0; i < jsonObj.keyboard.layouts.layout.length; i++) { duplicate_layouts_array[i] = jsonObj.keyboard.layouts.layout[i]['@_mapSet'] @@ -154,18 +165,18 @@ export class KeylayoutToKmnConverter { // ......................................................... // KEYMAP: get all keys for attribute "output" ( y,c,b,...) - TODO can i use shorter function? // ......................................................... - for (let i = 0; i < jsonObj.keyboard.keyMapSet[0].keyMap[j].key.length; i++) { - if (jsonObj.keyboard.keyMapSet[0].keyMap[j].key[i]['@_output'] !== "\0") { + for (let i = 0; i < jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap[j].key.length; i++) { + if (jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap[j].key[i]['@_output'] !== "\0") { // textencoder converts string -> bytes ( 'A' -> [ 65 ], '☺' -> [ 226, 152, 186 ]) // textencoder is of Uint8Array(1) for A and Uint8Array(3) for ☺ - keys_output_One_Layer[i] = new TextEncoder().encode(jsonObj.keyboard.keyMapSet[0].keyMap[j].key[i]['@_output']); + keys_output_One_Layer[i] = new TextEncoder().encode(jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap[j].key[i]['@_output']); } // ......................................................... // KEYMAP: get all keys for attribute "action" ( ^,a,e,i,...) - TODO can i use shorter function? // ......................................................... - if (jsonObj.keyboard.keyMapSet[0].keyMap[j].key[i]['@_action'] !== "\0") { - keys_action_One_Layer[i] = new TextEncoder().encode(jsonObj.keyboard.keyMapSet[0].keyMap[j].key[i]['@_action']); + if (jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap[j].key[i]['@_action'] !== "\0") { + keys_action_One_Layer[i] = new TextEncoder().encode(jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap[j].key[i]['@_action']); } } // ......................................................... @@ -200,9 +211,9 @@ export class KeylayoutToKmnConverter { // ACTION: create array of "deadkeyables_all_Layers" - TODO can i use shorter function? // ......................................................... const deadkeyables_all_Layers: string[][] = [] - for (let j = 0; j < jsonObj.keyboard.keyMapSet[0].keyMap.length; j++) { + for (let j = 0; j < jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap.length; j++) { const deadkeyables_one: string[] = [] - for (let i = 0; i < jsonObj.keyboard.keyMapSet[0].keyMap[0].key.length; i++) { + for (let i = 0; i < jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap[0].key.length; i++) { const resulting_character = new TextDecoder().decode(keys_action_all_Layers[j][i]) if (resulting_character !== "") deadkeyables_one.push(resulting_character) @@ -261,7 +272,7 @@ export class KeylayoutToKmnConverter { ArrayOf_Ukelele_output: data_output_all_Layers, ArrayOf_Ukelele_action: keys_action_all_Layers, ArrayOf_Modifiers: modifier_array, - ArrayOf_VK_US: "", + //ArrayOf_VK_US: "", ArrayOf_SC_MacWin: "", ArrayOf_dk: dk_pairs_all_Layers, // add dk-mapping ( dk1 <-> '^' ) ArrayOf_Dk: dk, // add plain dk ( '^', '´','`') @@ -309,34 +320,27 @@ export class KeylayoutToKmnConverter { 'K_PERIOD', 'K_SLASH', 'K_BKQUOTE', 'K_LBRKT', 'K_RBRKT', //104 ] - const data_VKUS: any[][] = []; - const data_kmn: any[][] = []; const data_mac_Win: any[][] = []; - //const keys_singleLayer: Uint8Array[] = [] // use UkeleleKeyCodeToScanCodes !!! for (let i = 0; i < data_ukelele.ArrayOf_Ukelele_output[0].length; i++) { - const data_VKUS_pos_pair: any[] = []; const data_mac_US_pair: any[] = []; - const data_kmn_pair: any[] = []; const keyName = kmn_Key_Name1[this.map_UkeleleKC_To_kmn_Key_Name_Array_Position_n(i)] - data_kmn_pair.push(i) - data_kmn_pair.push(this.map_UkeleleKC_To_kmn_Key_Name_Array_Position_n(i)) - data_VKUS_pos_pair.push(this.map_UkeleleKC_To_kmn_Key_Name_Array_Position_n(i)) - data_VKUS_pos_pair.push(keyName) + /*const secondName= UkeleleScanToUSVirtualKeyCodes(i) +const kS = Constants.CLDRScanToUSVirtualKeyCodes + +Constants.UkeleleScanToUSVirtualKeyCodes + console.log("secondName",secondName)*/ data_mac_US_pair.push(i) - // data_mac_US_pair.push(this.map_UkeleleKC_To_Win_KC(i)) data_mac_US_pair.push(keyName) - data_VKUS.push(data_VKUS_pos_pair) - data_kmn.push(data_kmn_pair) + + // data_mac_US_pair.push(this.map_UkeleleKC_To_Win_KC(i)) data_mac_Win.push(data_mac_US_pair) } - data_ukelele.ArrayOf_VK_US = data_VKUS - data_ukelele.ArrayOf_Kmn = data_kmn + //data_ukelele.ArrayOf_Kmn = data_kmn data_ukelele.ArrayOf_SC_MacWin = data_mac_Win - console.log("data_ukelele.ArrayOf_VK_US", data_ukelele.ArrayOf_VK_US) console.log("data_ukelele.ArrayOf_SC_MacWin", data_ukelele.ArrayOf_SC_MacWin) return data_ukelele @@ -511,6 +515,8 @@ console.log("§§§§§§§§§§§§§§§§§§§§§§§§", vk_label_test,"- // Todo use writefile from elsewhere writeFileSync("data/MyResult.kmn", data, { flag: "w" }) + fs.writeFileSync("data/MyResult_fs.kmn", data, { flag: "w" }) + //this.callbacks.fs.writeFileSync("data/MyResult_callb_fs.kmn", data) // not usable here since it takes UInt8array data // ToDo conditions? if (data.length > 0) @@ -523,14 +529,14 @@ console.log("§§§§§§§§§§§§§§§§§§§§§§§§", vk_label_test,"- // 34->"K_A" - public find_VK_X_in_ArrayOf_VK_US(vk_in: any, data: any): any { + /*public find_VK_X_in_ArrayOf_VK_US(vk_in: any, data: any): any { for (let i = 0; i < data.ArrayOf_VK_US.length; i++) { if (data.ArrayOf_VK_US[i][0] === vk_in) { return data.ArrayOf_VK_US[i][1] } } return - } + }*/ // TODO move outside of class? /** From c761490bf2912e41c39803e25b518afccf62faa3 Mon Sep 17 00:00:00 2001 From: Sabine Date: Tue, 26 Nov 2024 03:59:35 +0100 Subject: [PATCH 016/251] feat(developer): kmc-convert: use direct mapping Ukelele->VK --- .../keylayout-to-kmn-converter.ts | 256 ++++++++++++++---- 1 file changed, 203 insertions(+), 53 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 1d5e9595fb7..59d36eb0343 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -7,7 +7,8 @@ import { CompilerCallbacks, CompilerOptions } from "@keymanapp/developer-utils"; import { ConverterToKmnArtifacts } from "../converter-artifacts.js"; // TODO keylayout->kmn - +//modifiers: The identifier of the element to use for this range of hardware keyboard types. +//defaultIndex: The table number to use for modifier key combinations which are not explicitly specified by any element within the . // write read, convert, write // tests for 3 functions read write convert // add data to object @@ -52,8 +53,8 @@ export class KeylayoutToKmnConverter { static readonly OUTPUT_FILE_EXTENSION = '.kmn'; // TODO use callbacks - //constructor(/*private*/ _callbacks: CompilerCallbacks, /*private*/ _options: CompilerOptions) { - constructor(private callbacks: CompilerCallbacks, /*private*/ _options: CompilerOptions) { + constructor(/*private*/ _callbacks: CompilerCallbacks, /*private*/ _options: CompilerOptions) { + // constructor(private callbacks: CompilerCallbacks, /*private*/ _options: CompilerOptions) { // TODO: if these are needed, uncomment /*private*/ and remove _, and they will then // be available as class properties } @@ -116,9 +117,9 @@ export class KeylayoutToKmnConverter { const xmlFile = readFileSync((process.cwd() + "\\data" + filename.substring(filename.lastIndexOf("\\"))).replace(" ", ""), 'utf8'); // we don`t need file-read with uint8array return - const fullPath = (process.cwd() + "\\data" + filename.substring(filename.lastIndexOf("\\"))).replace(" ", "") + /*const fullPath = (process.cwd() + "\\data" + filename.substring(filename.lastIndexOf("\\"))).replace(" ", "") const xmlFile1 = this.callbacks.loadFile(fullPath) - console.log("xmlFile1",xmlFile1) + console.log("xmlFile1",xmlFile1)*/ //console.log("xmlFile",xmlFile) const parser = new XMLParser(options); @@ -274,13 +275,14 @@ export class KeylayoutToKmnConverter { ArrayOf_Modifiers: modifier_array, //ArrayOf_VK_US: "", ArrayOf_SC_MacWin: "", + ArrayOf_VK_DirectFromUku: "", ArrayOf_dk: dk_pairs_all_Layers, // add dk-mapping ( dk1 <-> '^' ) ArrayOf_Dk: dk, // add plain dk ( '^', '´','`') ArrayOf_deadkeyables: deadkeyables_all_Layers, // add char that can be modified with dk ( a,e,i,o,u) ArrayOf_deadkeyedChar: deadkeyedChars_all_Layers, // add modified keys ( â,ê,î,ô,û) ArrayOf_Terminators: terminators_all_Layers // add terminators ( ^,´,`) }; - console.log("DataObject", DataObject) + //console.log("DataObject", DataObject) // TODO review condition return DataObject return ((data_output_all_Layers.length === nrOfStates + 5) && data_output_all_Layers[0].length === nrOfKeys_inLayer) ? data_output_all_Layers : null; @@ -294,7 +296,7 @@ export class KeylayoutToKmnConverter { public convert(data_ukelele: any): any { // TODO remove - const kmn_Key_Name1 = [ + /* const kmn_Key_Name1 = [ 'K_BKSP', 'K_TAB', 'K_ENTER', 'K_SHIFT', 'K_CONTROL', 'K_ALT', 'K_PAUSE', 'K_CAPS', //7 'K_ESC', 'K_SPACE', 'K_PGUP', 'K_PGDN', 'K_END', 'K_HOME', 'K_LEFT', 'K_UP', 'K_RIGHT', //16 'K_DOWN', 'K_SEL', 'K_PRINT', 'K_EXEC', 'K_INS', 'K_DEL', 'K_HELP', //23 @@ -317,31 +319,64 @@ export class KeylayoutToKmnConverter { 'K_LALT', 'K_RALT', //95 'K_COLON', 'K_EQUAL', 'K_COMMA', 'K_HYPHEN', //99 - 'K_PERIOD', 'K_SLASH', 'K_BKQUOTE', 'K_LBRKT', 'K_RBRKT', //104 - ] + 'K_PERIOD', 'K_SLASH', 'K_BKQUOTE', 'K_LBRKT', 'K_RBRKT', K_QUOTE //105 + ]*/ + + const data_VKUS: any[][] = []; + const data_kmn: any[][] = []; + + /*const data_kmn_pair: any[] = []; + const data_VKUS_pos_pair: any[] = [];*/ + + /* const data_VK_US_K_pair: any[] = []; + const data_VK_US_K_: any[][] = [];*/ const data_mac_Win: any[][] = []; + const data_vk_directfromUku: any[][] = []; + // use UkeleleKeyCodeToScanCodes !!! for (let i = 0; i < data_ukelele.ArrayOf_Ukelele_output[0].length; i++) { - const data_mac_US_pair: any[] = []; - const keyName = kmn_Key_Name1[this.map_UkeleleKC_To_kmn_Key_Name_Array_Position_n(i)] - /*const secondName= UkeleleScanToUSVirtualKeyCodes(i) -const kS = Constants.CLDRScanToUSVirtualKeyCodes -Constants.UkeleleScanToUSVirtualKeyCodes - console.log("secondName",secondName)*/ - data_mac_US_pair.push(i) - data_mac_US_pair.push(keyName) + const data_mac_US_pair: any[] = []; + const data_vk_directfromUku_pair: any[] = []; + const Name_Array_Pos = this.map_UkeleleKC_To_kmn_Key_Name_Array_Position_n(i) + const keyName1 = this.map_UkeleleKC_To_kmn_Key_Name_Array_Position_new(Name_Array_Pos) + const nr_Win = this.map_UkeleleKC_To_Win_KC(i) + const keyName2 = this.map_UkeleleKC_To_kmn_Key_Name_Array_Position_new_2(nr_Win) + // const keyName = this.map_UkeleleKC_To_kmn_Key_Name_Array_Position_new(nr_Win) + // console.log("i",i,"nr_Win",nr_Win,"keyName",keyName) // data_mac_US_pair.push(this.map_UkeleleKC_To_Win_KC(i)) + + console.log("i",i, " -- nr_Win",nr_Win, " -- keyName","-",keyName1, Name_Array_Pos, "!!!",i, keyName2 ) + data_mac_US_pair.push(nr_Win) + data_mac_US_pair.push(keyName1) // this gives the part: K_A data_mac_Win.push(data_mac_US_pair) + + + const vk_from_Ukelele = this.map_UkeleleKC_To_VK(i) + data_vk_directfromUku_pair.push(i) + data_vk_directfromUku_pair.push(vk_from_Ukelele) + data_vk_directfromUku.push(data_vk_directfromUku_pair) + + + // write 0 - K_A + /* data_VK_US_K_pair.push(i) + data_VK_US_K_pair.push(keyName) + data_VK_US_K_.push(data_VK_US_K_pair) + //console.log("data_VK_US_K_pair",data_VK_US_K_pair)*/ } - //data_ukelele.ArrayOf_Kmn = data_kmn + console.log("data_vk_directfromUku",data_vk_directfromUku) + // console.log(".....data_mac_Win",data_mac_Win) + data_ukelele.ArrayOf_VK_US = data_VKUS + data_ukelele.ArrayOf_Kmn = data_kmn data_ukelele.ArrayOf_SC_MacWin = data_mac_Win - console.log("data_ukelele.ArrayOf_SC_MacWin", data_ukelele.ArrayOf_SC_MacWin) + data_ukelele.ArrayOf_VK_DirectFromUku = data_vk_directfromUku + + // console.log("data_ukelele.ArrayOf_SC_MacWin", data_ukelele.ArrayOf_SC_MacWin) return data_ukelele } @@ -380,6 +415,8 @@ Constants.UkeleleScanToUSVirtualKeyCodes 'K_PERIOD', 'K_SLASH', 'K_BKQUOTE', 'K_LBRKT', //101 ]*/ + console.log("ArrayOf_VK_DirectFromUku",kmn_array.ArrayOf_VK_DirectFromUku ) + // ************************************************************* // **** write stores ******************************************* // ************************************************************* @@ -441,11 +478,10 @@ console.log("§§§§§§§§§§§§§§§§§§§§§§§§", vk_label_test,"- if (filteredModifiers.indexOf("caps") >= 0) isCAPSused = true - // TODO good explanation // find all modifiers used per modifier combination // find resulting character from - + // todo magic 50 // loop through keys //for (let j = 0; j item[0] === kmn_array.ArrayOf_SC_MacWin[j][0]) + // const VK: number[][] = kmn_array.ArrayOf_SC_MacWin + // const vk_label = VK.filter(item => item[0] === kmn_array.ArrayOf_SC_MacWin[j][0]) + const VK: number[][] = kmn_array.ArrayOf_VK_DirectFromUku + const vk_label = VK.filter(item => item[0] === kmn_array.ArrayOf_VK_DirectFromUku[j][0]) // TODO remove j if (resulting_character !== '') @@ -660,18 +700,37 @@ console.log("§§§§§§§§§§§§§§§§§§§§§§§§", vk_label_test,"- if (pos === 26) return 31 // 7 if (pos === 28) return 32 // 8 if (pos === 25) return 33 // 9 - if (pos === 29) return 34 // 0 + if (pos === 29) return 24 // 0 if (pos === 24) return 97 // ´ EQUAL if (pos === 10) return 102 // ^ BKQUOTE if (pos === 33) return 103 // [ LBKT - if (pos === 30) return 104 // ] RBKT + if (pos === 50) return 104 // \ BKSLASH + if (pos === 30) return 105 // ] RBKT + if (pos === 44) return 101 // / SLASH + if (pos === 43) return 98 // , COMMA + if (pos === 27) return 99 // ß HYPHEN + if (pos === 36) return 2 // , SPACE K_ENTER + if (pos === 39) return 106 // , QUOTE + if (pos === 41) return 96 // : COLON + if (pos === 47) return 100 // : PERIOD /*if (pos === 187) return 100 // ^ if (pos === 192) return 95 // ´*/ - return + return 999 + } + public map_UkeleleKC_To_kmn_Key_Name_Array_Position_new(pos: any): any { + const firstKey = Object.keys(k)[pos] + //console.log("pos",pos, firstKey) + return firstKey + } + + public map_UkeleleKC_To_kmn_Key_Name_Array_Position_new_2(pos: any): any { + const firstKey = Object.keys(kk)[pos] + console.log("pos",pos, firstKey) + return firstKey } /** @@ -683,39 +742,71 @@ console.log("§§§§§§§§§§§§§§§§§§§§§§§§", vk_label_test,"- public map_UkeleleKC_To_Win_KC(pos: any): any { // ukelele KC --> // kmn win KC - if (pos === 0x06) return 0x2D /* z, /* */ - if (pos === 0x07) return 0x2E /* X, /* */ - if (pos === 0x08) return 0x2E /* C, /* */ - if (pos === 0x09) return 0x2F /* V, /* */ - if (pos === 0x0B) return 0x30 /* B, /* */ - if (pos === 0x2D) return 0x31 /* N, /* */ - if (pos === 0x2E) return 0x32 /* M, /* */ - - - if (pos === 0x00) return 0x1E /* A, /* */ - if (pos === 0x01) return 0x1F /* S, /* */ - if (pos === 0x02) return 0x20 /* D, /* */ - if (pos === 0x03) return 0x21 /* F, /* */ - if (pos === 0x05) return 0x22 /* G, /* */ - if (pos === 0x04) return 0x23 /* H, /* */ + if (pos === 0x0A) return 0x29 /* ^, /*--*/ + if (pos === 0x12) return 0x02 /* 1, /*--*/ + if (pos === 0x13) return 0x03 /* 2, /*--*/ + if (pos === 0x14) return 0x04 /* 3, /*--*/ + if (pos === 0x15) return 0x05 /* 4, /*--*/ + if (pos === 0x17) return 0x06 /* 5, /*--*/ + if (pos === 0x16) return 0x07 /* 6, /*--*/ + if (pos === 0x1A) return 0x08 /* 7, /* */ + if (pos === 0x1C) return 0x09 /* 8, /* 28 */ + if (pos === 0x19) return 0x0A /* 9, /* 25 */ + if (pos === 0x1D) return 11 /* 0, /* 29*/ + if (pos === 0x1B) return 12 /* ß, /*27 HYPHEN */ + if (pos === 0x18) return 0x0D /* ´, / *EQUAL */ + + if (pos === 0x0C) return 0x10 /* Q, /* 12 */ + if (pos === 0x0D) return 0x11 /* W, /* 13 */ + if (pos === 0x0E) return 0x12 /* E, /* 14 */ + if (pos === 0x0F) return 0x13 /* R, /* 15 */ + if (pos === 0x11) return 0x14 /* T, /* 17 */ + if (pos === 0x10) return 0x15 /* Y, /* 16 */ + if (pos === 0x20) return 0x16 /* U, /* 32 */ + if (pos === 0x22) return 0x17 /* I, /* 4 */ + if (pos === 0x1F) return 0x18 /* O, /* 31 */ + if (pos === 0x23) return 0x19 /* P, /* 35 */ + if (pos === 0x21) return 0x1A /* Ü, /* LBRKT */ + if (pos === 0x1E) return 0x1B /* +, /* RBRKT */ + if (pos === 0x32) return 0x2B /* +, /* BKSLASH */ + + if (pos === 0x00) return 0x1E /* A, /*--*/ + if (pos === 0x01) return 0x1F /* S, /*--*/ + if (pos === 0x02) return 0x20 /* D, /*--*/ + if (pos === 0x03) return 0x21 /* F, /*--*/ + if (pos === 0x05) return 0x22 /* G, /*--*/ + if (pos === 0x04) return 0x23 /* H, /*--*/ if (pos === 0x26) return 0x24 /* J, /* */ if (pos === 0x28) return 0x25 /* K, /* */ if (pos === 0x25) return 0x26 /* L, /* */ + if (pos === 0x29) return 0x27 /* Ö, /* COLON */ + if (pos === 0x27) return 40 /* Ä, /* QUOTE */ + + if (pos === 0x23) return 0x19 /* Ü, /* OE2 */ + if (pos === 0x06) return 0x2C /* Z, /*--*/ + if (pos === 0x07) return 0x2D /* X, /*--*/ + if (pos === 0x08) return 0x2E /* C, /*--*/ + if (pos === 0x09) return 0x2F /* V, /*--*/ + if (pos === 0x0B) return 0x30 /* B, /*--*/ + if (pos === 0x2D) return 0x31 /* N, /*--*/ + if (pos === 0x2E) return 0x32 /* M, /*--*/ + if (pos === 36) return 28 /* ENTER,*/ + + if (pos === 47) return 52 /* ,*/ + if (pos === 35) return 25 /* +, /* PERIOD */ + if (pos === 43) return 51 /* Ü, /* COMMA */ + if (pos === 44) return 53 /* Ü, /* SLASH */ + if (pos === 49) return 57 /* SPACE,*/ + + // if (pos === 0x23) return 0x19 /* +, /* KC01 */ + + /* 0x29) return 0x /* COLON, if (pos === 0x27) return 0x /* QUOTE, if (pos === 0x2A) return 0x /* BKQUOTE, /* 192 */ // changed /* if (pos === 0x32) return 0x /* BKSLASH, /* ???*/ - if (pos === 0x0C) return 0x10 /* Q, /* 12 */ - if (pos === 0x0D) return 0x11 /* W, /* 13 */ - if (pos === 0x0E) return 0x12 /* E, /* 14 */ - if (pos === 0x0F) return 0x13 /* R, /* 15 */ - if (pos === 0x11) return 0x14 /* T, /* 17 */ - if (pos === 0x10) return 0x15 /* Y, /* 16 */ - if (pos === 0x20) return 0x16 /* U, /* 32 */ - if (pos === 0x22) return 0x17 /* I, /* 4 */ - if (pos === 0x1F) return 0x18 /* O, /* 31 */ - if (pos === 0x23) return 0x19 /* P, /* 35 */ + /* if (pos === 0x21) return k.K_LBRKT, if (pos === 0x1E) return k.K_RBRKT,/* @@ -724,7 +815,6 @@ console.log("§§§§§§§§§§§§§§§§§§§§§§§§", vk_label_test,"- if (pos === 0x2F) return 0x /* PERIOD, if (pos === 0x2C) return 0x /* SLASH, - if (pos === 0x31) return 0x /* SPACE, if (pos === 0x56) return 0x /* oE2, // 86 << Same as 0x7D; found on iso, abnt2 if (pos === 0x73) return 0x /* oC1, @@ -732,6 +822,65 @@ console.log("§§§§§§§§§§§§§§§§§§§§§§§§", vk_label_test,"- */ } + // TODO finish all entries + public map_UkeleleKC_To_VK(pos: any): any { + // ukelele KC --> // VK_US + + if (pos === 0x0A) return "K_BKQUOTE" /* ^, /*--*/ + if (pos === 0x12) return "K_1" /* 1, /*--*/ + if (pos === 0x13) return "K_2" /* 2, /*--*/ + if (pos === 0x14) return "K_3" /* 3, /*--*/ + if (pos === 0x15) return "K_4" /* 4, /*--*/ + if (pos === 0x17) return "K_5" /* 5, /*--*/ + if (pos === 0x16) return "K_6" /* 6, /*--*/ + if (pos === 0x1A) return "K_7" /* 7, " /* */ + if (pos === 0x1C) return "K_8" /* 8, " /* 28 */ + if (pos === 0x19) return "K_9" /* 9, " /* 25 */ + if (pos === 0x1D) return "K_0" /* 0, " /* 29*/ + if (pos === 0x1B) return "K_HYPHEN" /* ß, /*27 HYPHEN */ + if (pos === 0x18) return "K_EQUAL" /* ´, / *EQUAL */ + + if (pos === 0x0C) return "K_Q" /* Q, " /* 12 */ + if (pos === 0x0D) return "K_W" /* W, " /* 13 */ + if (pos === 0x0E) return "K_E" /* E, " /* 14 */ + if (pos === 0x0F) return "K_R" /* R, " /* 15 */ + if (pos === 0x11) return "K_T" /* T, " /* 17 */ + if (pos === 0x10) return "K_Y" /* Y, " /* 16 */ + if (pos === 0x20) return "K_U" /* U, " /* 32 */ + if (pos === 0x22) return "K_I" /* I, " /* 4 */ + if (pos === 0x1F) return "K_O" /* O, " /* 31 */ + if (pos === 0x23) return "K_P" /* P, " /* 35 */ + if (pos === 0x21) return "K_LBRKT" /* Ü, " /* LBRKT */ + if (pos === 0x1E) return "K_RBRKT" /* +, " /* RBRKT */ + if (pos === 0x32) return "K_BKSLASH" /* +, " /* BKSLASH */ + + if (pos === 0x00) return "K_A" /* A, /*--*/ + if (pos === 0x01) return "K_S" /* S, /*--*/ + if (pos === 0x02) return "K_D" /* D, /*--*/ + if (pos === 0x03) return "K_F" /* F, /*--*/ + if (pos === 0x05) return "K_G" /* G, /*--*/ + if (pos === 0x04) return "K_H" /* H, /*--*/ + if (pos === 0x26) return "K_J" /* J, " /* */ + if (pos === 0x28) return "K_K" /* K, " /* */ + if (pos === 0x25) return "K_L" /* L, " /* */ + if (pos === 0x29) return "K_COLON" /* Ö, " /* COLON */ + if (pos === 0x27) return "K_QUOTE" /* Ä, " /* QUOTE */ + + if (pos === 0x23) return "K_oE2" /* |, " /* OE2 */ + if (pos === 0x06) return "K_Z" /* Z, /*--*/ + if (pos === 0x07) return "K_X" /* X, /*--*/ + if (pos === 0x08) return "K_C" /* C, /*--*/ + if (pos === 0x09) return "K_V" /* V, /*--*/ + if (pos === 0x0B) return "K_B" /* B, /*--*/ + if (pos === 0x2D) return "K_N" /* N, /*--*/ + if (pos === 0x2E) return "K_M" /* M, /*--*/ + if (pos === 43) return "K_COMMA" /* Ü, " /* COMMA */ + if (pos === 47) return "K_PERIOD" /* ,*/ + if (pos === 44) return "K_SLASH" /* Ü, " /* SLASH */ + + if (pos === 36) return "K_ENTER" /* ENTER,*/ + if (pos === 49) return "K_SPACE" /* SPACE,*/ + } // _S2 can probably go /*public map_UkeleleKC_To_kmn_Key_Name_Array_Position(in_from_ukelele: Uint16Array, pos: any): any { @@ -1096,6 +1245,7 @@ export const UkeleleScanToUSVirtualKeyCodes = { }; +const kk = UkeleleScanToUSVirtualKeyCodes; // _S2 can probably go /* export const UkeleleKeyCodeToScanCodes = { From 95c683a3015f18a0ece929be16823b97c0c1d2cc Mon Sep 17 00:00:00 2001 From: Sabine Date: Tue, 26 Nov 2024 05:01:03 +0100 Subject: [PATCH 017/251] feat(developer): kmc-convert: remove unneccessary code --- .../keylayout-to-kmn-converter.ts | 906 ++---------------- 1 file changed, 92 insertions(+), 814 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 59d36eb0343..729ac8b2fe8 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -36,11 +36,10 @@ import { ConverterToKmnArtifacts } from "../converter-artifacts.js"; // Functions as object methods? // objects contain only used stuff READ in: -- out: only read arrays / CONVERT in: only read arrays out: return only to write arrays // Use catch blocks for file read - -// use - - // TODO waht about using actions twice in a row??? +// read: _S2 answer : + [K_A] > 'a' is OK / TODO which format to use in output ? + [K_A] > 'a' (character code) or + [K_A] > U+0061 (virt Keycode) +// read // _S2 TODO which stores? + // _S2 imports Sabine import { XMLParser } from 'fast-xml-parser'; // for reading a file import { readFileSync } from 'fs'; @@ -54,7 +53,7 @@ export class KeylayoutToKmnConverter { // TODO use callbacks constructor(/*private*/ _callbacks: CompilerCallbacks, /*private*/ _options: CompilerOptions) { - // constructor(private callbacks: CompilerCallbacks, /*private*/ _options: CompilerOptions) { + // constructor(private callbacks: CompilerCallbacks, /*private*/ _options: CompilerOptions) { // TODO: if these are needed, uncomment /*private*/ and remove _, and they will then // be available as class properties } @@ -63,7 +62,6 @@ export class KeylayoutToKmnConverter { * @brief member function to run read/convert/write * @param inputFilename the ukelele .keylayout-file to be converted * @param outputFilename the resulting keyman .kmn-file - * @param binaryData ... _S2 * @return */ async run(inputFilename: string, outputFilename: string): Promise { @@ -103,10 +101,7 @@ export class KeylayoutToKmnConverter { * @return in case of success Uint8Array keys_all_Layers; else null */ public read(filename: string): object { - /* - // _S2 answer : + [K_A] > 'a' is OK / TODO which format to use in output ? + [K_A] > 'a' (character code) or + [K_A] > U+0061 (virt Keycode) - // _S2 TODO which stores? - */ + console.log("inputFilename read", filename) const options = { ignoreAttributes: false, @@ -125,15 +120,15 @@ export class KeylayoutToKmnConverter { const parser = new XMLParser(options); const jsonObj = parser.parse(xmlFile); // get plain Object - const keyMapSet_count =0 + const keyMapSet_count = 0 const nrOfStates = jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap.length const nrOfKeys_inLayer = jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap[0].key.length // will they all have the same length later ? // ToDo naming // TODO array-> object - const duplicate_layouts_array: any[] = [] - const modifier_array: any[] = [] // array holding all MODIFIER strings e.g. "anyShift caps anyOption" -why not put modifiers into Uint8Array along with values of keys of layer - const data_output_all_Layers: any[] = [] + const duplicate_layouts_array: any[] = [] // array holding the layouts e.g. ANSI or JIS + const modifierMap_array: any[] = [] // array holding all MODIFIER strings e.g. "anyShift caps anyOption" -why not put modifiers into Uint8Array along with values of keys of layer + const keys_output_all_Layers: any[] = [] const keys_action_all_Layers: any[] = [] // array holding all values with ACTION attribute (needed for finding deadkeys) const deadkeyedChars_all_Layers: any[] = [] // array holding all DEADKEYS for each mod state â, ê, ,.... const terminators_all_Layers: any[] = [] // array holding all DEADKEYS for each mod state â, ê, ,.... @@ -157,7 +152,7 @@ export class KeylayoutToKmnConverter { // loop through all ss-combin for (let j = 0; j < nrOfStates; j++) { // get modifier list e.g. "anyshift caps? anyOption" - modifier_array[j] = jsonObj.keyboard.modifierMap.keyMapSelect[j].modifier['@_keys'] + modifierMap_array[j] = jsonObj.keyboard.modifierMap.keyMapSelect[j].modifier['@_keys'] // create a new array of keys_in_Layer (type Uint8tarray) const keys_output_One_Layer: Uint8Array[] = [] @@ -182,9 +177,8 @@ export class KeylayoutToKmnConverter { } // ......................................................... // create array of "action" and array of "output" - // data_all_Layers.push(keys_output_One_Layer) // save all @output data ( will be used for conversion, write...) - data_output_all_Layers.push(keys_output_One_Layer) // save all @output data ( will be used for conversion, write...) - keys_action_all_Layers.push(keys_action_One_Layer) // save all @action data ( will be used for deadkeys) + keys_output_all_Layers.push(keys_output_One_Layer) // save all @output data ( will be used for conversion, write...) + keys_action_all_Layers.push(keys_action_One_Layer) // save all @action data ( will be used for deadkeys) } // ......................................................... // ACTION: create array of "deadkey" / "deadkey names" - TODO can i use shorter function? @@ -237,7 +231,7 @@ export class KeylayoutToKmnConverter { } // ......................................................... - // TODO can i use shorter function? -> yes use terminators + // TODO can i use shorter function? -> yes use terminators, filter, map or reduce // loop through all dk, key-actions and find @_action // find this value in @@ -270,22 +264,20 @@ export class KeylayoutToKmnConverter { const DataObject = { name: "Ukelele-kmn", ArrayOf_Layouts: layouts_array, - ArrayOf_Ukelele_output: data_output_all_Layers, + ArrayOf_Ukelele_output: keys_output_all_Layers, ArrayOf_Ukelele_action: keys_action_all_Layers, - ArrayOf_Modifiers: modifier_array, - //ArrayOf_VK_US: "", - ArrayOf_SC_MacWin: "", - ArrayOf_VK_DirectFromUku: "", - ArrayOf_dk: dk_pairs_all_Layers, // add dk-mapping ( dk1 <-> '^' ) - ArrayOf_Dk: dk, // add plain dk ( '^', '´','`') - ArrayOf_deadkeyables: deadkeyables_all_Layers, // add char that can be modified with dk ( a,e,i,o,u) - ArrayOf_deadkeyedChar: deadkeyedChars_all_Layers, // add modified keys ( â,ê,î,ô,û) - ArrayOf_Terminators: terminators_all_Layers // add terminators ( ^,´,`) + ArrayOf_Modifiers: modifierMap_array, + ArrayOf_VK_from_keylayout: "", + ArrayOf_dk: dk_pairs_all_Layers, // add dk-mapping ( dk1 <-> '^' ) + ArrayOf_Dk: dk, // add plain dk ( '^', '´','`') + ArrayOf_deadkeyables: deadkeyables_all_Layers, // add char that can be modified with dk ( a,e,i,o,u) + ArrayOf_deadkeyedChar: deadkeyedChars_all_Layers, // add modified keys ( â,ê,î,ô,û) + ArrayOf_Terminators: terminators_all_Layers // add terminators ( ^,´,`) }; - //console.log("DataObject", DataObject) + // TODO review condition return DataObject - return ((data_output_all_Layers.length === nrOfStates + 5) && data_output_all_Layers[0].length === nrOfKeys_inLayer) ? data_output_all_Layers : null; + return ((keys_output_all_Layers.length === nrOfStates + 5) && keys_output_all_Layers[0].length === nrOfKeys_inLayer) ? keys_output_all_Layers : null; } /** @@ -294,89 +286,16 @@ export class KeylayoutToKmnConverter { * @return outArray Uint8Array keys_all_Layers, the converted data for kmn-files if all layers have been converted; else null */ public convert(data_ukelele: any): any { + const data_VK_from_keylayout: any[][] = []; - // TODO remove - /* const kmn_Key_Name1 = [ - 'K_BKSP', 'K_TAB', 'K_ENTER', 'K_SHIFT', 'K_CONTROL', 'K_ALT', 'K_PAUSE', 'K_CAPS', //7 - 'K_ESC', 'K_SPACE', 'K_PGUP', 'K_PGDN', 'K_END', 'K_HOME', 'K_LEFT', 'K_UP', 'K_RIGHT', //16 - 'K_DOWN', 'K_SEL', 'K_PRINT', 'K_EXEC', 'K_INS', 'K_DEL', 'K_HELP', //23 - - 'K_0', 'K_1', 'K_2', 'K_3', 'K_4', 'K_5', 'K_6', 'K_7', 'K_8', 'K_9', //33 - - 'K_A', 'K_B', 'K_C', 'K_D', 'K_E', 'K_F', 'K_G', 'K_H', 'K_I', 'K_J', 'K_K', 'K_L', 'K_M', //46 - 'K_N', 'K_O', 'K_P', 'K_Q', 'K_R', 'K_S', 'K_T', 'K_U', 'K_V', 'K_W', 'K_X', 'K_Y', 'K_Z', //59 - - 'K_NP0', 'K_NP1', 'K_NP2', 'K_NP3', 'K_NP4', - 'K_NP5', 'K_NP6', 'K_NP7', 'K_NP8', 'K_NP9', //69 - - 'K_NPSTAR', 'K_NPPLUS', 'K_SEPARATOR', 'K_NPMINUS', 'K_NPDOT', 'K_NPSLASH', //75 - - 'K_F1', 'K_F2', 'K_F3', 'K_F4', 'K_F5', 'K_F6', - 'K_F7', 'K_F8', 'K_F9', 'K_F10', 'K_F11', 'K_F12', // 87 - - 'K_NUMLOCK', 'K_SCROLL', 'K_LSHIFT', - 'K_RSHIFT', 'K_LCONTROL', 'K_RCONTROL', - 'K_LALT', 'K_RALT', //95 - - 'K_COLON', 'K_EQUAL', 'K_COMMA', 'K_HYPHEN', //99 - 'K_PERIOD', 'K_SLASH', 'K_BKQUOTE', 'K_LBRKT', 'K_RBRKT', K_QUOTE //105 - ]*/ - - const data_VKUS: any[][] = []; - const data_kmn: any[][] = []; - - /*const data_kmn_pair: any[] = []; - const data_VKUS_pos_pair: any[] = [];*/ - - /* const data_VK_US_K_pair: any[] = []; - const data_VK_US_K_: any[][] = [];*/ - - const data_mac_Win: any[][] = []; - const data_vk_directfromUku: any[][] = []; - - - // use UkeleleKeyCodeToScanCodes !!! for (let i = 0; i < data_ukelele.ArrayOf_Ukelele_output[0].length; i++) { - - const data_mac_US_pair: any[] = []; - const data_vk_directfromUku_pair: any[] = []; - - const Name_Array_Pos = this.map_UkeleleKC_To_kmn_Key_Name_Array_Position_n(i) - const keyName1 = this.map_UkeleleKC_To_kmn_Key_Name_Array_Position_new(Name_Array_Pos) - - const nr_Win = this.map_UkeleleKC_To_Win_KC(i) - const keyName2 = this.map_UkeleleKC_To_kmn_Key_Name_Array_Position_new_2(nr_Win) - // const keyName = this.map_UkeleleKC_To_kmn_Key_Name_Array_Position_new(nr_Win) - // console.log("i",i,"nr_Win",nr_Win,"keyName",keyName) - // data_mac_US_pair.push(this.map_UkeleleKC_To_Win_KC(i)) - - console.log("i",i, " -- nr_Win",nr_Win, " -- keyName","-",keyName1, Name_Array_Pos, "!!!",i, keyName2 ) - data_mac_US_pair.push(nr_Win) - data_mac_US_pair.push(keyName1) // this gives the part: K_A - data_mac_Win.push(data_mac_US_pair) - - + const data_VK_from_keylayout_pair: any[] = []; const vk_from_Ukelele = this.map_UkeleleKC_To_VK(i) - data_vk_directfromUku_pair.push(i) - data_vk_directfromUku_pair.push(vk_from_Ukelele) - data_vk_directfromUku.push(data_vk_directfromUku_pair) - - - // write 0 - K_A - /* data_VK_US_K_pair.push(i) - data_VK_US_K_pair.push(keyName) - data_VK_US_K_.push(data_VK_US_K_pair) - //console.log("data_VK_US_K_pair",data_VK_US_K_pair)*/ + data_VK_from_keylayout_pair.push(i) + data_VK_from_keylayout_pair.push(vk_from_Ukelele) + data_VK_from_keylayout.push(data_VK_from_keylayout_pair) } - - console.log("data_vk_directfromUku",data_vk_directfromUku) - // console.log(".....data_mac_Win",data_mac_Win) - data_ukelele.ArrayOf_VK_US = data_VKUS - data_ukelele.ArrayOf_Kmn = data_kmn - data_ukelele.ArrayOf_SC_MacWin = data_mac_Win - data_ukelele.ArrayOf_VK_DirectFromUku = data_vk_directfromUku - - // console.log("data_ukelele.ArrayOf_SC_MacWin", data_ukelele.ArrayOf_SC_MacWin) + data_ukelele.ArrayOf_VK_from_keylayout = data_VK_from_keylayout return data_ukelele } @@ -389,33 +308,6 @@ export class KeylayoutToKmnConverter { */ //TODO need to use export const USVirtualKeyCodes here public write(kmn_array: any): boolean { - /*const kmn_Key_Name = [ - 'K_BKSP', 'K_TAB', 'K_ENTER', 'K_SHIFT', 'K_CONTROL', 'K_ALT', 'K_PAUSE', 'K_CAPS', //7 - 'K_ESC', 'K_SPACE', 'K_PGUP', 'K_PGDN', 'K_END', 'K_HOME', 'K_LEFT', 'K_UP', 'K_RIGHT', //16 - 'K_DOWN', 'K_SEL', 'K_PRINT', 'K_EXEC', 'K_INS', 'K_DEL', 'K_HELP', //23 - - 'K_0', 'K_1', 'K_2', 'K_3', 'K_4', 'K_5', 'K_6', 'K_7', 'K_8', 'K_9', //33 - - 'K_A', 'K_B', 'K_C', 'K_D', 'K_E', 'K_F', 'K_G', 'K_H', 'K_I', 'K_J', 'K_K', 'K_L', 'K_M', //46 - 'K_N', 'K_O', 'K_P', 'K_Q', 'K_R', 'K_S', 'K_T', 'K_U', 'K_V', 'K_W', 'K_X', 'K_Y', 'K_Z', //59 - - 'K_NP0', 'K_NP1', 'K_NP2', 'K_NP3', 'K_NP4', - 'K_NP5', 'K_NP6', 'K_NP7', 'K_NP8', 'K_NP9', - - 'K_NPSTAR', 'K_NPPLUS', 'K_SEPARATOR', 'K_NPMINUS', 'K_NPDOT', 'K_NPSLASH', //75 - - 'K_F1', 'K_F2', 'K_F3', 'K_F4', 'K_F5', 'K_F6', - 'K_F7', 'K_F8', 'K_F9', 'K_F10', 'K_F11', 'K_F12', // 85 - - 'K_NUMLOCK', 'K_SCROLL', 'K_LSHIFT', - 'K_RSHIFT', 'K_LCONTROL', 'K_RCONTROL', - 'K_LALT', 'K_RALT', //93 - - 'K_COLON', 'K_EQUAL', 'K_COMMA', 'K_HYPHEN', //97 - 'K_PERIOD', 'K_SLASH', 'K_BKQUOTE', 'K_LBRKT', //101 - ]*/ - - console.log("ArrayOf_VK_DirectFromUku",kmn_array.ArrayOf_VK_DirectFromUku ) // ************************************************************* // **** write stores ******************************************* @@ -442,37 +334,9 @@ export class KeylayoutToKmnConverter { // **** write rules ******************************************** // *************************************************************^ - - - - /* - const numbers: number[] = [11, 23, 45, 89, 7, 98]; - const filteredNumbers: number[] = numbers.filter((num) => num > 10); - console.log(filteredNumbers); - - const words: string[] = ["apple", "banana", "cherry", "date"]; - const filteredWords: string[] = words.filter((word) => word.length > 5); - console.log(filteredWords); - - // now with kmc-convert: - const varToFind= kmn_array.ArrayOf_VK_US[2][0] - const numbersMy: number[][] = kmn_array.ArrayOf_VK_US - const filteredNumbersMy = numbersMy.filter(innerArray => innerArray[0] === varToFind); - - console.log("ArrayOf_VK_US",kmn_array.ArrayOf_VK_US ); - console.log("kmn_array.ArrayOf_VK_US[x][0]",varToFind ); - console.log("filteredNumbersMy",filteredNumbersMy);*/ - /* -const vk_label_test = this.find_VK_X_in_ArrayOf_VK_US(kmn_array.ArrayOf_VK_US[0][0], kmn_array) -console.log("kmn_array",kmn_array.ArrayOf_VK_US, "(kmn_array.ArrayOf_VK_US[0][0]",kmn_array.ArrayOf_VK_US[0][0]) -const vl_label2= kmn_array.ArrayOf_VK_US[0].filter((num:number) => num ===kmn_array.ArrayOf_VK_US[0][0]) -console.log("§§§§§§§§§§§§§§§§§§§§§§§§", vk_label_test,"--", vl_label2, vl_label2===vk_label_test,kmn_array.ArrayOf_VK_US[vl_label2][1] )*/ - - - - // if caps is used in .keylayout-file we need to add NCAPS in kmn-file let isCAPSused = false + const used_Keys_count = 50 // do we need more than 50 keys?? const modi: string[] = kmn_array.ArrayOf_Modifiers; const filteredModifiers: string[] = modi.filter((mod) => (String(mod) === ("caps"))) if (filteredModifiers.indexOf("caps") >= 0) @@ -481,28 +345,23 @@ console.log("§§§§§§§§§§§§§§§§§§§§§§§§", vk_label_test,"- // TODO good explanation // find all modifiers used per modifier combination // find resulting character from - // todo magic 50 + // loop through keys //for (let j = 0; j item[0] === kmn_array.ArrayOf_SC_MacWin[j][0]) - const VK: number[][] = kmn_array.ArrayOf_VK_DirectFromUku - const vk_label = VK.filter(item => item[0] === kmn_array.ArrayOf_VK_DirectFromUku[j][0]) + const VK: number[][] = kmn_array.ArrayOf_VK_from_keylayout + const vk_label = VK.filter(item => item[0] === kmn_array.ArrayOf_VK_from_keylayout[j][0]) // TODO remove j if (resulting_character !== '') @@ -527,9 +386,8 @@ console.log("§§§§§§§§§§§§§§§§§§§§§§§§", vk_label_test,"- const resulting_character = new TextDecoder().decode(kmn_array.ArrayOf_Ukelele_action[j][i]) if (resulting_character !== "") { - //get the VK_ - label - const VK: number[][] = kmn_array.ArrayOf_SC_MacWin - const vk_label = VK.filter(item => item[0] === kmn_array.ArrayOf_SC_MacWin[i][0]) + const VK: number[][] = kmn_array.ArrayOf_VK_from_keylayout + const vk_label = VK.filter(item => item[0] === kmn_array.ArrayOf_VK_from_keylayout[i][0]) for (let k = 0; k < kmn_array.ArrayOf_dk.length; k++) { if ((resulting_character !== "") && (resulting_character === kmn_array.ArrayOf_dk[k][1])) { @@ -567,17 +425,6 @@ console.log("§§§§§§§§§§§§§§§§§§§§§§§§", vk_label_test,"- //... helpers ............................................................................................. - - // 34->"K_A" - /*public find_VK_X_in_ArrayOf_VK_US(vk_in: any, data: any): any { - for (let i = 0; i < data.ArrayOf_VK_US.length; i++) { - if (data.ArrayOf_VK_US[i][0] === vk_in) { - return data.ArrayOf_VK_US[i][1] - } - } - return - }*/ - // TODO move outside of class? /** * @brief member function to return the unicode value of a character @@ -652,640 +499,71 @@ console.log("§§§§§§§§§§§§§§§§§§§§§§§§", vk_label_test,"- return unique_Modifier.join(" ").replace(/\s+/g, " ").trim().toUpperCase() } -/** - * @brief member function to map Ukelele keycodes to a position of Key_Name_Arra - * @param pos Ukelele (=mac) keycodes - * @return position of Key_Name_Array ( the array holding all keynames) - */ - // TODO add all other keys - // TODO replace with mapping from constants - public map_UkeleleKC_To_kmn_Key_Name_Array_Position_n(pos: any): any { - // ukelele kc --> // kmn-Array kmn_Key_Name - // .keylayout-file // position in list - // code = .. // zerobased 0-... - //const pos = Number(poss) - - if (pos === 0) return 34 // a - if (pos === 11) return 35 // b - if (pos === 8) return 36 // c - if (pos === 2) return 37 // d - if (pos === 14) return 38 // e - if (pos === 3) return 39 // f - if (pos === 5) return 40 // g - if (pos === 4) return 41 // h - if (pos === 34) return 42 // i - if (pos === 38) return 43 // j - if (pos === 40) return 44 // k - if (pos === 37) return 45 // l - if (pos === 46) return 46 // m - if (pos === 45) return 47 // n - if (pos === 31) return 48 // o - if (pos === 35) return 49 // p - if (pos === 12) return 50 // q - if (pos === 15) return 51 // r - if (pos === 1) return 52 // s - if (pos === 17) return 53 // t - if (pos === 32) return 54 // u - if (pos === 9) return 55 // v - if (pos === 13) return 56 // w - if (pos === 7) return 57 // x - if (pos === 6) return 58 // y - if (pos === 16) return 59 // z - if (pos === 18) return 25 // 1 - if (pos === 19) return 26 // 2 - if (pos === 20) return 27 // 3 - if (pos === 21) return 28 // 4 - if (pos === 23) return 29 // 5 - if (pos === 22) return 30 // 6 - if (pos === 26) return 31 // 7 - if (pos === 28) return 32 // 8 - if (pos === 25) return 33 // 9 - if (pos === 29) return 24 // 0 - if (pos === 24) return 97 // ´ EQUAL - if (pos === 10) return 102 // ^ BKQUOTE - if (pos === 33) return 103 // [ LBKT - if (pos === 50) return 104 // \ BKSLASH - if (pos === 30) return 105 // ] RBKT - if (pos === 44) return 101 // / SLASH - if (pos === 43) return 98 // , COMMA - if (pos === 27) return 99 // ß HYPHEN - if (pos === 36) return 2 // , SPACE K_ENTER - if (pos === 39) return 106 // , QUOTE - if (pos === 41) return 96 // : COLON - if (pos === 47) return 100 // : PERIOD - - - /*if (pos === 187) return 100 // ^ - if (pos === 192) return 95 // ´*/ - - - return 999 - } - public map_UkeleleKC_To_kmn_Key_Name_Array_Position_new(pos: any): any { - const firstKey = Object.keys(k)[pos] - //console.log("pos",pos, firstKey) - return firstKey - } - - public map_UkeleleKC_To_kmn_Key_Name_Array_Position_new_2(pos: any): any { - const firstKey = Object.keys(kk)[pos] - console.log("pos",pos, firstKey) - return firstKey - } /** * @brief member function to map Ukelele keycodes to a Windows Keycodes * @param pos Ukelele (=mac) keycodes * @return keycode on Win Keyboard */ - // TODO finish all entries - public map_UkeleleKC_To_Win_KC(pos: any): any { - // ukelele KC --> // kmn win KC - - if (pos === 0x0A) return 0x29 /* ^, /*--*/ - if (pos === 0x12) return 0x02 /* 1, /*--*/ - if (pos === 0x13) return 0x03 /* 2, /*--*/ - if (pos === 0x14) return 0x04 /* 3, /*--*/ - if (pos === 0x15) return 0x05 /* 4, /*--*/ - if (pos === 0x17) return 0x06 /* 5, /*--*/ - if (pos === 0x16) return 0x07 /* 6, /*--*/ - if (pos === 0x1A) return 0x08 /* 7, /* */ - if (pos === 0x1C) return 0x09 /* 8, /* 28 */ - if (pos === 0x19) return 0x0A /* 9, /* 25 */ - if (pos === 0x1D) return 11 /* 0, /* 29*/ - if (pos === 0x1B) return 12 /* ß, /*27 HYPHEN */ - if (pos === 0x18) return 0x0D /* ´, / *EQUAL */ - - if (pos === 0x0C) return 0x10 /* Q, /* 12 */ - if (pos === 0x0D) return 0x11 /* W, /* 13 */ - if (pos === 0x0E) return 0x12 /* E, /* 14 */ - if (pos === 0x0F) return 0x13 /* R, /* 15 */ - if (pos === 0x11) return 0x14 /* T, /* 17 */ - if (pos === 0x10) return 0x15 /* Y, /* 16 */ - if (pos === 0x20) return 0x16 /* U, /* 32 */ - if (pos === 0x22) return 0x17 /* I, /* 4 */ - if (pos === 0x1F) return 0x18 /* O, /* 31 */ - if (pos === 0x23) return 0x19 /* P, /* 35 */ - if (pos === 0x21) return 0x1A /* Ü, /* LBRKT */ - if (pos === 0x1E) return 0x1B /* +, /* RBRKT */ - if (pos === 0x32) return 0x2B /* +, /* BKSLASH */ - - if (pos === 0x00) return 0x1E /* A, /*--*/ - if (pos === 0x01) return 0x1F /* S, /*--*/ - if (pos === 0x02) return 0x20 /* D, /*--*/ - if (pos === 0x03) return 0x21 /* F, /*--*/ - if (pos === 0x05) return 0x22 /* G, /*--*/ - if (pos === 0x04) return 0x23 /* H, /*--*/ - if (pos === 0x26) return 0x24 /* J, /* */ - if (pos === 0x28) return 0x25 /* K, /* */ - if (pos === 0x25) return 0x26 /* L, /* */ - if (pos === 0x29) return 0x27 /* Ö, /* COLON */ - if (pos === 0x27) return 40 /* Ä, /* QUOTE */ - - if (pos === 0x23) return 0x19 /* Ü, /* OE2 */ - if (pos === 0x06) return 0x2C /* Z, /*--*/ - if (pos === 0x07) return 0x2D /* X, /*--*/ - if (pos === 0x08) return 0x2E /* C, /*--*/ - if (pos === 0x09) return 0x2F /* V, /*--*/ - if (pos === 0x0B) return 0x30 /* B, /*--*/ - if (pos === 0x2D) return 0x31 /* N, /*--*/ - if (pos === 0x2E) return 0x32 /* M, /*--*/ - if (pos === 36) return 28 /* ENTER,*/ - - if (pos === 47) return 52 /* ,*/ - if (pos === 35) return 25 /* +, /* PERIOD */ - if (pos === 43) return 51 /* Ü, /* COMMA */ - if (pos === 44) return 53 /* Ü, /* SLASH */ - if (pos === 49) return 57 /* SPACE,*/ - - // if (pos === 0x23) return 0x19 /* +, /* KC01 */ - - - /* 0x29) return 0x /* COLON, - if (pos === 0x27) return 0x /* QUOTE, - if (pos === 0x2A) return 0x /* BKQUOTE, /* 192 */ // changed - /* - if (pos === 0x32) return 0x /* BKSLASH, /* ???*/ - - /* if (pos === 0x21) return k.K_LBRKT, - if (pos === 0x1E) return k.K_RBRKT,/* - - - if (pos === 0x2B) return 0x /* COMMA, - if (pos === 0x2F) return 0x /* PERIOD, - if (pos === 0x2C) return 0x /* SLASH, - - - if (pos === 0x56) return 0x /* oE2, // 86 << Same as 0x7D; found on iso, abnt2 - if (pos === 0x73) return 0x /* oC1, - if (pos === 0x7D) return 0x /* oE2, // << Same as 0x56; found on jis - */ - - } // TODO finish all entries public map_UkeleleKC_To_VK(pos: any): any { // ukelele KC --> // VK_US - if (pos === 0x0A) return "K_BKQUOTE" /* ^, /*--*/ - if (pos === 0x12) return "K_1" /* 1, /*--*/ - if (pos === 0x13) return "K_2" /* 2, /*--*/ - if (pos === 0x14) return "K_3" /* 3, /*--*/ - if (pos === 0x15) return "K_4" /* 4, /*--*/ - if (pos === 0x17) return "K_5" /* 5, /*--*/ - if (pos === 0x16) return "K_6" /* 6, /*--*/ - if (pos === 0x1A) return "K_7" /* 7, " /* */ - if (pos === 0x1C) return "K_8" /* 8, " /* 28 */ - if (pos === 0x19) return "K_9" /* 9, " /* 25 */ - if (pos === 0x1D) return "K_0" /* 0, " /* 29*/ - if (pos === 0x1B) return "K_HYPHEN" /* ß, /*27 HYPHEN */ - if (pos === 0x18) return "K_EQUAL" /* ´, / *EQUAL */ - - if (pos === 0x0C) return "K_Q" /* Q, " /* 12 */ - if (pos === 0x0D) return "K_W" /* W, " /* 13 */ - if (pos === 0x0E) return "K_E" /* E, " /* 14 */ - if (pos === 0x0F) return "K_R" /* R, " /* 15 */ - if (pos === 0x11) return "K_T" /* T, " /* 17 */ - if (pos === 0x10) return "K_Y" /* Y, " /* 16 */ - if (pos === 0x20) return "K_U" /* U, " /* 32 */ - if (pos === 0x22) return "K_I" /* I, " /* 4 */ - if (pos === 0x1F) return "K_O" /* O, " /* 31 */ - if (pos === 0x23) return "K_P" /* P, " /* 35 */ - if (pos === 0x21) return "K_LBRKT" /* Ü, " /* LBRKT */ - if (pos === 0x1E) return "K_RBRKT" /* +, " /* RBRKT */ - if (pos === 0x32) return "K_BKSLASH" /* +, " /* BKSLASH */ - - if (pos === 0x00) return "K_A" /* A, /*--*/ - if (pos === 0x01) return "K_S" /* S, /*--*/ - if (pos === 0x02) return "K_D" /* D, /*--*/ - if (pos === 0x03) return "K_F" /* F, /*--*/ - if (pos === 0x05) return "K_G" /* G, /*--*/ - if (pos === 0x04) return "K_H" /* H, /*--*/ - if (pos === 0x26) return "K_J" /* J, " /* */ - if (pos === 0x28) return "K_K" /* K, " /* */ - if (pos === 0x25) return "K_L" /* L, " /* */ - if (pos === 0x29) return "K_COLON" /* Ö, " /* COLON */ - if (pos === 0x27) return "K_QUOTE" /* Ä, " /* QUOTE */ - - if (pos === 0x23) return "K_oE2" /* |, " /* OE2 */ - if (pos === 0x06) return "K_Z" /* Z, /*--*/ - if (pos === 0x07) return "K_X" /* X, /*--*/ - if (pos === 0x08) return "K_C" /* C, /*--*/ - if (pos === 0x09) return "K_V" /* V, /*--*/ - if (pos === 0x0B) return "K_B" /* B, /*--*/ - if (pos === 0x2D) return "K_N" /* N, /*--*/ - if (pos === 0x2E) return "K_M" /* M, /*--*/ - if (pos === 43) return "K_COMMA" /* Ü, " /* COMMA */ - if (pos === 47) return "K_PERIOD" /* ,*/ - if (pos === 44) return "K_SLASH" /* Ü, " /* SLASH */ - - if (pos === 36) return "K_ENTER" /* ENTER,*/ - if (pos === 49) return "K_SPACE" /* SPACE,*/ + if (pos === 0x0A) return "K_BKQUOTE" /* ^ */ + if (pos === 0x12) return "K_1" /* 1 */ + if (pos === 0x13) return "K_2" /* 2 */ + if (pos === 0x14) return "K_3" /* 3 */ + if (pos === 0x15) return "K_4" /* 4 */ + if (pos === 0x17) return "K_5" /* 5 */ + if (pos === 0x16) return "K_6" /* 6 */ + if (pos === 0x1A) return "K_7" /* 7 */ + if (pos === 0x1C) return "K_8" /* 8 */ + if (pos === 0x19) return "K_9" /* 9 */ + if (pos === 0x1D) return "K_0" /* 0 */ + if (pos === 0x1B) return "K_HYPHEN" /* ß */ + if (pos === 0x18) return "K_EQUAL" /* ´ */ + + if (pos === 0x0C) return "K_Q" /* Q */ + if (pos === 0x0D) return "K_W" /* W */ + if (pos === 0x0E) return "K_E" /* E */ + if (pos === 0x0F) return "K_R" /* R */ + if (pos === 0x11) return "K_T" /* T */ + if (pos === 0x10) return "K_Y" /* Y */ + if (pos === 0x20) return "K_U" /* U */ + if (pos === 0x22) return "K_I" /* I */ + if (pos === 0x1F) return "K_O" /* O */ + if (pos === 0x23) return "K_P" /* P */ + if (pos === 0x21) return "K_LBRKT" /* [ */ + if (pos === 0x1E) return "K_RBRKT" /* ] */ + if (pos === 0x32) return "K_BKSLASH" /* \ */ + + if (pos === 0x00) return "K_A" /* A */ + if (pos === 0x01) return "K_S" /* S */ + if (pos === 0x02) return "K_D" /* D */ + if (pos === 0x03) return "K_F" /* F */ + if (pos === 0x05) return "K_G" /* G */ + if (pos === 0x04) return "K_H" /* H */ + if (pos === 0x26) return "K_J" /* J */ + if (pos === 0x28) return "K_K" /* K */ + if (pos === 0x25) return "K_L" /* L */ + if (pos === 0x29) return "K_COLON" /* : */ + if (pos === 0x27) return "K_QUOTE" /* " */ + + if (pos === 0x23) return "K_oE2" /* | */ + if (pos === 0x06) return "K_Z" /* Z */ + if (pos === 0x07) return "K_X" /* X */ + if (pos === 0x08) return "K_C" /* C */ + if (pos === 0x09) return "K_V" /* V */ + if (pos === 0x0B) return "K_B" /* B */ + if (pos === 0x2D) return "K_N" /* N */ + if (pos === 0x2E) return "K_M" /* M */ + if (pos === 43) return "K_COMMA" /* , */ + if (pos === 47) return "K_PERIOD" /* . */ + if (pos === 44) return "K_SLASH" /* / */ + + if (pos === 36) return "K_ENTER" + if (pos === 49) return "K_SPACE" } - - // _S2 can probably go - /*public map_UkeleleKC_To_kmn_Key_Name_Array_Position(in_from_ukelele: Uint16Array, pos: any): any { - // ukelele kc --> // kmn-Array kmn_Key_Name - // .keylayout-file // position in list - // code = .. // zerobased 0-... - if (pos === 0) return 34 // a - if (pos === 11) return 35 // b - if (pos === 8) return 36 // c - if (pos === 2) return 37 // d - if (pos === 14) return 38 // e - if (pos === 3) return 39 // f - if (pos === 5) return 40 // g - if (pos === 4) return 41 // h - if (pos === 34) return 42 // i - if (pos === 38) return 43 // j - if (pos === 40) return 44 // k - if (pos === 37) return 45 // l - if (pos === 46) return 46 // m - if (pos === 45) return 47 // n - if (pos === 31) return 48 // o - if (pos === 35) return 49 // p - if (pos === 12) return 50 // q - if (pos === 15) return 51 // r - if (pos === 1) return 52 // s - if (pos === 17) return 53 // t - if (pos === 32) return 54 // u - if (pos === 9) return 55 // v - if (pos === 13) return 56 // w - if (pos === 7) return 57 // x - if (pos === 6) return 58 // y - if (pos === 16) return 59 // z - if (pos === 18) return 25 // 1 - if (pos === 19) return 26 // 2 - if (pos === 20) return 27 // 3 - if (pos === 21) return 28 // 4 - if (pos === 22) return 29 // 5 - if (pos === 23) return 30 // 6 - if (pos === 26) return 31 // 7 - if (pos === 28) return 32 // 8 - if (pos === 25) return 33 // 9 - if (pos === 29) return 34 // 0 - - - if (pos === 24) return 97 // ´ EQUAL - if (pos === 10) return 102 // ^ BKQUOTE - - if (pos === 187) return 100 // ^ - - - return - }*/ - - - /* public map_UkeleleKC_To_kmn_Key_VK_Name(pos: any): any { - // ukelele kc --> // kmn-Array kmn_Key_Name - // .keylayout-file // position in list - // code = .. // zerobased 0-... - //const pos = Number(poss) - - if (pos === 0) return "K_A" // a - if (pos === 1) return "K_S" // s - if (pos === 2) return "K_D" // d - if (pos === 3) return "K_F" // f - if (pos === 11) return "K_B" // b - if (pos === 8) return "K_C" // c - - /* if (pos === 14) return 38 // e - if (pos === 5) return 40 // g - if (pos === 4) return 41 // h - if (pos === 34) return 42 // i - if (pos === 38) return 43 // j - if (pos === 40) return 44 // k - if (pos === 37) return 45 // l - if (pos === 46) return 46 // m - if (pos === 45) return 47 // n - if (pos === 31) return 48 // o - if (pos === 35) return 49 // p - if (pos === 12) return 50 // q - if (pos === 15) return 51 // r - if (pos === 17) return 53 // t - if (pos === 32) return 54 // u - if (pos === 9) return 55 // v - if (pos === 13) return 56 // w - if (pos === 7) return 57 // x - if (pos === 6) return 58 // y - if (pos === 16) return 59 // z - if (pos === 18) return 25 // 1 - if (pos === 19) return 26 // 2 - if (pos === 20) return 27 // 3 - if (pos === 21) return 28 // 4 - if (pos === 22) return 29 // 5 - if (pos === 23) return 30 // 6 - if (pos === 26) return 31 // 7 - if (pos === 28) return 32 // 8 - if (pos === 25) return 33 // 9 - if (pos === 29) return 34 // 0 - - - if (pos === 187) return 100 // ^ - if (pos === 192) return 95 // ´ - - - return - }*/ - - // 34->0 - /*public find_pos_ofVK_in_ArrayOf_VK_US(vk_in: any, data: any): any { - for (let i = 0; i < data.ArrayOf_VK_US.length; i++) { - if (data.ArrayOf_VK_US[i][0] === vk_in) { - return i - } - } - return - }*/ - - // 34->0 - /* public find_pos_ofkmn_in_ArrayOf_kmn(pos_kmn: any, data: any): any { - for (let i = 0; i < data.ArrayOf_Kmn.length; i++) { - if (data.ArrayOf_Kmn[i][1] === pos_kmn) { - return i - } - } - return - }*/ - - //'^' -> 10 - /*public find_dk_in_uku_action(dk_in: any, data: any): any { - const chr = new TextDecoder().decode(data.ArrayOf_Ukelele_output[0][10]) - console.log("dk_in", dk_in, "chr", chr) - for (let j = 0; j < 8; j++) { - // console.log(data.ArrayOf_Ukelele[0]) - } - return 777 - }*/ - - // dk->"dk K_EQUAL" - /* public find_VK_X_in_ArrayOf_dk(vk_in: any, data: any): any { - for (let i = 0; i < data.ArrayOf_dk.length; i++) { - if (data.ArrayOf_dk[i][0] === vk_in) { - return data.ArrayOf_dk[i][1] - } - } - return - }*/ - } -/* -function iscapsUsedInVal(num:any) { - if (String(num)===("caps")) - return true -else return false -}*/ - -/*function iscapsUsedInVal_(accumulator:any, num:any) { - if (String(num)===("caps")) - return (accumulator && true) -else return (accumulator && false) -}*/ - - - // _S2 can probably go -export const USVirtualKeyCodes = { - K_BKSP: 8, - K_TAB: 9, - K_ENTER: 13, - K_SHIFT: 16, - K_CONTROL: 17, - K_ALT: 18, - K_PAUSE: 19, - K_CAPS: 20, - K_ESC: 27, - K_SPACE: 32, - K_PGUP: 33, - K_PGDN: 34, - K_END: 35, - K_HOME: 36, - K_LEFT: 37, - K_UP: 38, - K_RIGHT: 39, - K_DOWN: 40, - K_SEL: 41, - K_PRINT: 42, - K_EXEC: 43, - K_INS: 45, - K_DEL: 46, - K_HELP: 47, - K_0: 48, - K_1: 49, - K_2: 50, - K_3: 51, - K_4: 52, - K_5: 53, - K_6: 54, - K_7: 55, - K_8: 56, - K_9: 57, - K_A: 65, - K_B: 66, - K_C: 67, - K_D: 68, - K_E: 69, - K_F: 70, - K_G: 71, - K_H: 72, - K_I: 73, - K_J: 74, - K_K: 75, - K_L: 76, - K_M: 77, - K_N: 78, - K_O: 79, - K_P: 80, - K_Q: 81, - K_R: 82, - K_S: 83, - K_T: 84, - K_U: 85, - K_V: 86, - K_W: 87, - K_X: 88, - K_Y: 89, - K_Z: 90, - K_NP0: 96, - K_NP1: 97, - K_NP2: 98, - K_NP3: 99, - K_NP4: 100, - K_NP5: 101, - K_NP6: 102, - K_NP7: 103, - K_NP8: 104, - K_NP9: 105, - K_NPSTAR: 106, - K_NPPLUS: 107, - K_SEPARATOR: 108, - K_NPMINUS: 109, - K_NPDOT: 110, - K_NPSLASH: 111, - K_F1: 112, - K_F2: 113, - K_F3: 114, - K_F4: 115, - K_F5: 116, - K_F6: 117, - K_F7: 118, - K_F8: 119, - K_F9: 120, - K_F10: 121, - K_F11: 122, - K_F12: 123, - K_NUMLOCK: 144, - K_SCROLL: 145, - K_LSHIFT: 160, - K_RSHIFT: 161, - K_LCONTROL: 162, - K_RCONTROL: 163, - K_LALT: 164, - K_RALT: 165, - K_COLON: 186, - K_EQUAL: 187, - K_COMMA: 188, - K_HYPHEN: 189, - K_PERIOD: 190, - K_SLASH: 191, - K_BKQUOTE: 192, - K_LBRKT: 219, - /** - * == K_OEM_5, 0xDC - */ - K_BKSLASH: 220, - K_RBRKT: 221, - K_QUOTE: 222, - /** - * ISO B00, key to right of left shift, not on US keyboard, - * 0xE2, K_OEM_102 - */ - K_oE2: 226, - K_OE2: 226, - K_oC1: 193, // ISO B11, ABNT-2 key to left of right shift, not on US keyboard - K_OC1: 193, - 'K_?C1': 193, - 'k_?C1': 193, - K_oDF: 0xDF, - K_ODF: 0xDF, - K_LOPT: 50001, - K_ROPT: 50002, - K_NUMERALS: 50003, - K_SYMBOLS: 50004, - K_CURRENCIES: 50005, - K_UPPER: 50006, - K_LOWER: 50007, - K_ALPHA: 50008, - K_SHIFTED: 50009, - K_ALTGR: 50010, - K_TABBACK: 50011, - K_TABFWD: 50012 -}; - - // _S2 can probably go -const k = USVirtualKeyCodes; - - // _S2 can probably go -export const UkeleleScanToUSVirtualKeyCodes = { - 0x12: k.K_1, /* 18 */ - 0x13: k.K_2, /* 19 */ - 0x14: k.K_3, /* 20 */ - 0x15: k.K_4, /* 21 */ - 0x17: k.K_5, /* 23 */ - 0x16: k.K_6, /* 22 */ - 0x1A: k.K_7, /* 26 */ - 0x1C: k.K_8, /* 28 */ - 0x19: k.K_9, /* 25 */ - 0x1D: k.K_0, /* 29 */ - 0x18: k.K_HYPHEN, /* 24 */ - 0x0A: k.K_EQUAL, /* 187 */ //changed - - 0x0C: k.K_Q, /* 12 */ - 0x0D: k.K_W, /* 13 */ - 0x0E: k.K_E, /* 14 */ - 0x0F: k.K_R, /* 15 */ - 0x11: k.K_T, /* 17 */ - 0x10: k.K_Y, /* 16 */ - 0x20: k.K_U, /* 32 */ - 0x22: k.K_I, /* 34 */ - 0x1F: k.K_O, /* 31 */ - 0x23: k.K_P, /* 35 */ - 0x21: k.K_LBRKT, - 0x1E: k.K_RBRKT, - - 0x00: k.K_A, /* 0 */ - 0x01: k.K_S, /* 1 */ - 0x02: k.K_D, /* 2 */ - 0x03: k.K_F, /* 3 */ - 0x05: k.K_G, /* 5 */ - 0x04: k.K_H, /* 4 */ - 0x26: k.K_J, /* 38 */ - 0x28: k.K_K, /* 40 */ - 0x25: k.K_L, /* 37 */ - 0x29: k.K_COLON, - 0x27: k.K_QUOTE, - 0x2A: k.K_BKQUOTE, /* 192 */ // changed - - 0x32: k.K_BKSLASH, /* ???*/ - - 0x06: k.K_Z, - 0x07: k.K_X, - 0x08: k.K_C, - 0x09: k.K_V, - 0x0B: k.K_B, - 0x2D: k.K_N, - 0x2E: k.K_M, - 0x2B: k.K_COMMA, - 0x2F: k.K_PERIOD, - 0x2C: k.K_SLASH, - - 0x31: k.K_SPACE, - - 0x56: k.K_oE2, // 86 << Same as 0x7D; found on iso, abnt2 - 0x73: k.K_oC1, - 0x7D: k.K_oE2, // << Same as 0x56; found on jis - -}; - -const kk = UkeleleScanToUSVirtualKeyCodes; -// _S2 can probably go -/* -export const UkeleleKeyCodeToScanCodes = { - - 0x00: 0x1E, /* A, /* 0 - 0x01: 0x1F, /* S, /* 1 - 0x02: 0x20 ,/* D, /* 2 - 0x03: 0x21 ,/* F, /* 3 - 0x05: 0x22 ,/* G, /* 5 - 0x04: 0x23 ,/* H, /* 4 - 0x26: 0x24 ,/* J, /* 38 - 0x28: 0x25 ,/* K, /* 40 - 0x25: 0x26 ,/* L, /* 37 - /* 0x29: 0x ,/* COLON, - 0x27: 0x ,/* QUOTE, - 0x2A: 0x ,/* BKQUOTE, /* 192 // changed -/* - 0x32: 0x ,/* BKSLASH, /* ??? - 0x0C: 0x10 ,/* Q, /* 12 - 0x0D: 0x11 ,/* W, /* 13 - 0x0E: 0x12 ,/* E, /* 14 - 0x0F: 0x13 ,/* R, /* 15 - 0x11: 0x14 ,/* T, /* 17 - 0x10: 0x15 ,/* Y, /* 16 - 0x20: 0x16 ,/* U, /* 32 - 0x22: 0x17 ,/* I, /* 4 - 0x1F: 0x18 ,/* O, /* 31 - 0x23: 0x19 ,/* P, /* 35 - 0x21: k.K_LBRKT, - 0x1E: k.K_RBRKT, - -/* - 0x2B: 0x ,/* COMMA, - 0x2F: 0x ,/* PERIOD, - 0x2C: 0x ,/* SLASH, - - 0x31: 0x ,/* SPACE, - 0x56: 0x ,/* oE2, // 86 << Same as 0x7D; found on iso, abnt2 - 0x73: 0x ,/* oC1, - 0x7D: 0x ,/* oE2, // << Same as 0x56; found on jis -};*/ From ffc9bc62a55c6b86cb26e83f9c95dc0c6c3d0ead Mon Sep 17 00:00:00 2001 From: Sabine Date: Wed, 27 Nov 2024 03:54:24 +0100 Subject: [PATCH 018/251] feat(developer): kmc-convert: handle keyMapSets --- .../keylayout-to-kmn-converter.ts | 140 ++++++++++++------ 1 file changed, 96 insertions(+), 44 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 729ac8b2fe8..694908301ff 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -6,39 +6,38 @@ import { CompilerCallbacks, CompilerOptions } from "@keymanapp/developer-utils"; import { ConverterToKmnArtifacts } from "../converter-artifacts.js"; -// TODO keylayout->kmn -//modifiers: The identifier of the element to use for this range of hardware keyboard types. -//defaultIndex: The table number to use for modifier key combinations which are not explicitly specified by any element within the . -// write read, convert, write -// tests for 3 functions read write convert -// add data to object -// Use filter functions -// action/output:use filter etc to shorten func -// deadkeyables:use filter etc to shorten func -// dk-> for all action:use filter etc to shorten func -// remove unneccessa´ry data from dataObject -// rename symbols -// remove part using kmn_key_Name1 -// remove unnecceaasry map_UkeleleKC_To_kmn_Key_Name_Array_Position_n etc -// loop throught ANSI, JIS- art moment only use [keyMapSet_count] (keyMapSet_count=0) -// remove funcs at teh end -// import { makePathToFixture } from '../../test/helpers/index.js'; // _S2 my imports -// Mapping 0->30 or 0->K_A-> missing entries in mapping -// Replace any-types -// Several steps action-> action-> action->character ( not only action->character) -// Usable for all keylayout files -// Return conditions -// Use callbacks as for writeFileSync -// Tests throws -// Conditions NCAPS,OPT;... -// Which stores -// TODO move func outside of class -// Functions as object methods? -// objects contain only used stuff READ in: -- out: only read arrays / CONVERT in: only read arrays out: return only to write arrays -// Use catch blocks for file read -// TODO waht about using actions twice in a row??? -// read: _S2 answer : + [K_A] > 'a' is OK / TODO which format to use in output ? + [K_A] > 'a' (character code) or + [K_A] > U+0061 (virt Keycode) -// read // _S2 TODO which stores? +// TODO keylayout->kmn +// modifiers: The identifier of the element to use for this range of hardware keyboard types. +// defaultIndex: The table number to use for modifier key combinations which are not explicitly specified by any element within the . +// write read, convert, write +// tests for 3 functions read write convert +// add data to object +// Use filter functions +// action/output:use filter etc to shorten func +// deadkeyables:use filter etc to shorten func +// dk-> for all action:use filter etc to shorten func +// remove unneccessary data from dataObject +// rename symbols +// OK remove part using kmn_key_Name1 +// OK remove unnecceaasry map_UkeleleKC_To_kmn_Key_Name_Array_Position_n etc +// OK loop throught ANSI, JIS- at moment only use [keyMapSet_count] (keyMapSet_count=0) +// OK remove funcs at teh end +// import { makePathToFixture } from '../../test/helpers/index.js'; +// OK Mapping 0->30 or 0->K_A-> missing entries in mapping +// Replace any-types +// Several steps action-> action-> action->character ( not only action->character) +// TODO waht about using actions twice in a row??? +// Usable for all keylayout files +// Return conditions +// Use callbacks as for writeFileSync +// Tests throws +// Conditions NCAPS,OPT;... +// TODO move func outside of class +// Functions as object methods? +// objects contain only used stuff READ in: -- out: only read arrays / CONVERT in: only read arrays out: return only to write arrays +// Use catch blocks for file read +// read: answer : + [K_A] > 'a' is OK / TODO which format to use in output ? + [K_A] > 'a' (character code) or + [K_A] > U+0061 (virt Keycode) +// read TODO which stores? // _S2 imports Sabine import { XMLParser } from 'fast-xml-parser'; // for reading a file @@ -47,6 +46,24 @@ import { writeFileSync } from "fs"; // for writing a file import * as fs from 'fs'; // what is this/do I need it? - either import all or seperately like above + + + +export interface convert_object { + instrument: string + name: string, // needed?? remove + ArrayOf_Layouts: any[], // needed?? I think no + ArrayOf_Ukelele_output: any[], + ArrayOf_Ukelele_action: any[], + ArrayOf_Modifiers: any[], + ArrayOf_VK_from_keylayout: any[], + ArrayOf_dk: any[], // add dk-mapping ( dk1 <-> '^' ) + ArrayOf_Dk: any[], // add plain dk ( '^', '´','`') + ArrayOf_deadkeyables: any[], // add char that can be modified with dk ( a,e,i,o,u) + ArrayOf_deadkeyedChar: any[], // add modified keys ( â,ê,î,ô,û) + ArrayOf_Terminators: any[] // add terminators ( ^,´,`) +}; + export class KeylayoutToKmnConverter { static readonly INPUT_FILE_EXTENSION = '.keylayout'; static readonly OUTPUT_FILE_EXTENSION = '.kmn'; @@ -78,7 +95,7 @@ export class KeylayoutToKmnConverter { } console.log(' _S2 then CONVERT ........................................'); - const outArray: any = await this.convert(inArray); + const outArray: convert_object = await this.convert(inArray); if (!outArray) { return null; @@ -117,34 +134,62 @@ export class KeylayoutToKmnConverter { console.log("xmlFile1",xmlFile1)*/ //console.log("xmlFile",xmlFile) + console.log("layouts_array read ") const parser = new XMLParser(options); const jsonObj = parser.parse(xmlFile); // get plain Object - const keyMapSet_count = 0 - const nrOfStates = jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap.length - const nrOfKeys_inLayer = jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap[0].key.length // will they all have the same length later ? - // ToDo naming // TODO array-> object - const duplicate_layouts_array: any[] = [] // array holding the layouts e.g. ANSI or JIS const modifierMap_array: any[] = [] // array holding all MODIFIER strings e.g. "anyShift caps anyOption" -why not put modifiers into Uint8Array along with values of keys of layer const keys_output_all_Layers: any[] = [] const keys_action_all_Layers: any[] = [] // array holding all values with ACTION attribute (needed for finding deadkeys) const deadkeyedChars_all_Layers: any[] = [] // array holding all DEADKEYS for each mod state â, ê, ,.... const terminators_all_Layers: any[] = [] // array holding all DEADKEYS for each mod state â, ê, ,.... + const duplicate_layouts_array: any[] = [] // array holding the layouts e.g. ANSI or JIS // needed?? I think no + // TODO call: get only ANSI + // Do I need to care or is there always ANSI which is always keyMapSet[0] + // if so code can be shortened // ......................................................... - // LAYOUTS: get all groups like ANSI JIS + // LAYOUTS: get all groups like ANSI JIS, remove JIS // ......................................................... - for (let i = 0; i < jsonObj.keyboard.layouts.layout.length; i++) { + /* in case we need to find ANSI + for (let i = 0; i < jsonObj.keyboard.layouts.layout.length; i++) { duplicate_layouts_array[i] = jsonObj.keyboard.layouts.layout[i]['@_mapSet'] } + // remove duplicates const layouts_array: any[] = duplicate_layouts_array.filter(function (item, pos, self) { return self.indexOf(item) == pos; }) + // remove JIS (if keyMap contains baseMapSet it`s JIS) + for (let i = 0; i < layouts_array.length; i++) { + if(jsonObj.keyboard.keyMapSet[i].keyMap[0]['@_baseMapSet']) + layouts_array.splice(i, 1); + } + + // TODO implement error & do what? + if(layouts_array.length > 1 ) + console.log("ERROR! too many layouts") + if(layouts_array.length < 1 ) + console.log("One layouts") + + // Todo better way ?? + const keyMapSet_count = layouts_array.length-1 +*/ + + // in case there always ANSI which is always keyMapSet[0] + const layouts_array: any[] = duplicate_layouts_array + const keyMapSet_count = 0 + + // ----- + + const nrOfStates = jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap.length + const nrOfKeys_inLayer = jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap[0].key.length // will they all have the same length later ? + + // ......................................................... // KEYMAP: get all keys for attribute "output" and "action" - TODO can i use shorter function? // ......................................................... @@ -233,6 +278,9 @@ export class KeylayoutToKmnConverter { // ......................................................... // TODO can i use shorter function? -> yes use terminators, filter, map or reduce + // this addresses state+output and none+output + // but not state+next or none+next + // loop through all dk, key-actions and find @_action // find this value in // in their 'when' find output for dk @@ -250,7 +298,11 @@ export class KeylayoutToKmnConverter { for (let m = 0; m < jsonObj.keyboard.actions.action[l].when.length; m++) { // and get their @_output if (jsonObj.keyboard.actions.action[l].when[m]['@_state'] === dk_pairs_all_Layers[j][0]) { + // todo push only if @output is found. if next is found: get value from terminators + //if (typeof jsonObj.keyboard.actions.action[l].when[m]['@_output'].property !== 'undefined') deadkeys_One_dk.push(jsonObj.keyboard.actions.action[l].when[m]['@_output']) + //else + //console.log(deadkeys_One_dk, "§§§§§§ PROP UNDEFINED", j, "-", k, "-", l, "-", m, "-", dk_pairs_all_Layers[j][0], jsonObj.keyboard.actions.action[l].when[m].property) } } } @@ -262,8 +314,8 @@ export class KeylayoutToKmnConverter { // TODO remove unneccassary elements const DataObject = { - name: "Ukelele-kmn", - ArrayOf_Layouts: layouts_array, + name: "Ukelele-kmn", // needed?? remove + ArrayOf_Layouts: layouts_array, // needed?? I think no ArrayOf_Ukelele_output: keys_output_all_Layers, ArrayOf_Ukelele_action: keys_action_all_Layers, ArrayOf_Modifiers: modifierMap_array, @@ -307,7 +359,7 @@ export class KeylayoutToKmnConverter { * @return true if data has been written; false if not */ //TODO need to use export const USVirtualKeyCodes here - public write(kmn_array: any): boolean { + public write(kmn_array: convert_object): boolean { // ************************************************************* // **** write stores ******************************************* From 17ffb14d9194720a7bd5dfea03a5bcfe7132f4ca Mon Sep 17 00:00:00 2001 From: Sabine Date: Wed, 27 Nov 2024 04:23:33 +0100 Subject: [PATCH 019/251] feat(developer): kmc-convert: exchange any-types read, write, convert, inArray,outArray --- .../keylayout-to-kmn-converter.ts | 25 +++++++++++-------- .../test/test-keylayout-to-kmn-converter.ts | 4 ++- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 694908301ff..5ecfc3e65c2 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -50,7 +50,6 @@ import * as fs from 'fs'; // what is this/do I need it? - either import all o export interface convert_object { - instrument: string name: string, // needed?? remove ArrayOf_Layouts: any[], // needed?? I think no ArrayOf_Ukelele_output: any[], @@ -64,6 +63,11 @@ export interface convert_object { ArrayOf_Terminators: any[] // add terminators ( ^,´,`) }; +export interface deadkey_all_object { + deadkeyedChars_all_Layers: string[][], // needed?? I think no +}; + + export class KeylayoutToKmnConverter { static readonly INPUT_FILE_EXTENSION = '.keylayout'; static readonly OUTPUT_FILE_EXTENSION = '.kmn'; @@ -88,7 +92,7 @@ export class KeylayoutToKmnConverter { } console.log(' _S2 first READ file ........................................in:', inputFilename); - const inArray: object = this.read(inputFilename) + const inArray: convert_object = this.read(inputFilename) if (!inArray) { return null; @@ -117,7 +121,7 @@ export class KeylayoutToKmnConverter { * @param filename the ukelele .keylayout-file to be converted * @return in case of success Uint8Array keys_all_Layers; else null */ - public read(filename: string): object { + public read(filename: string): convert_object { console.log("inputFilename read", filename) const options = { @@ -187,7 +191,7 @@ export class KeylayoutToKmnConverter { // ----- const nrOfStates = jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap.length - const nrOfKeys_inLayer = jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap[0].key.length // will they all have the same length later ? + //const nrOfKeys_inLayer = jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap[0].key.length // will they all have the same length later ? // ......................................................... @@ -286,7 +290,7 @@ export class KeylayoutToKmnConverter { // in their 'when' find output for dk // for all 'action' at keys paragraph for (let j = 0; j < dk_pairs_all_Layers.length; j++) { - const deadkeys_One_dk: any[] = [] + const deadkeys_One_dk: string[] = [] // find in action e.g. for (let k = 0; k < keys_action_all_Layers[j].length; k++) { const action_from_keys_prargraph = new TextDecoder().decode(keys_action_all_Layers[j][k]) @@ -310,16 +314,17 @@ export class KeylayoutToKmnConverter { } } deadkeyedChars_all_Layers.push(deadkeys_One_dk) + console.log("typeof(deadkeyedChars_all_Layers)", typeof(deadkeyedChars_all_Layers),deadkeyedChars_all_Layers) } - +const vk : any[] =[""] // TODO remove unneccassary elements - const DataObject = { + const DataObject: convert_object = { name: "Ukelele-kmn", // needed?? remove ArrayOf_Layouts: layouts_array, // needed?? I think no ArrayOf_Ukelele_output: keys_output_all_Layers, ArrayOf_Ukelele_action: keys_action_all_Layers, ArrayOf_Modifiers: modifierMap_array, - ArrayOf_VK_from_keylayout: "", + ArrayOf_VK_from_keylayout: vk, ArrayOf_dk: dk_pairs_all_Layers, // add dk-mapping ( dk1 <-> '^' ) ArrayOf_Dk: dk, // add plain dk ( '^', '´','`') ArrayOf_deadkeyables: deadkeyables_all_Layers, // add char that can be modified with dk ( a,e,i,o,u) @@ -329,7 +334,7 @@ export class KeylayoutToKmnConverter { // TODO review condition return DataObject - return ((keys_output_all_Layers.length === nrOfStates + 5) && keys_output_all_Layers[0].length === nrOfKeys_inLayer) ? keys_output_all_Layers : null; + //return ((keys_output_all_Layers.length === nrOfStates + 5) && keys_output_all_Layers[0].length === nrOfKeys_inLayer) ? keys_output_all_Layers : null; } /** @@ -337,7 +342,7 @@ export class KeylayoutToKmnConverter { * @param data_ukelele (Uint8Array) data of the ukelele .keylayout-file * @return outArray Uint8Array keys_all_Layers, the converted data for kmn-files if all layers have been converted; else null */ - public convert(data_ukelele: any): any { + public convert(data_ukelele: any): convert_object { const data_VK_from_keylayout: any[][] = []; for (let i = 0; i < data_ukelele.ArrayOf_Ukelele_output[0].length; i++) { diff --git a/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts index dbe813f0dc9..55f5516bed9 100644 --- a/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts @@ -36,9 +36,11 @@ describe('KeylayoutToKmnConverter', function() { //const inputFilename = makePathToFixture('../data/Mysample.keylayout'); // all keys, some deadkeys const inputFilename = makePathToFixture('../data/My_dk_Keyboard.keylayout'); + //const inputFilename = makePathToFixture('../data/US_complete.keylayout'); + //const inputFilename = makePathToFixture('../data/Italian_copy.keylayout'); const outputFilename = makePathToFixture('../data/MyResult.kmn'); - +// TODO check filename if correct console.log(' inputFilename', inputFilename) console.log(' outputFilename', outputFilename) From 83461d4810e28a5f6594e716cbc490481647c0d3 Mon Sep 17 00:00:00 2001 From: Sabine Date: Wed, 27 Nov 2024 07:37:26 +0100 Subject: [PATCH 020/251] feat(developer): kmc-convert: exchange more any-types --- .../keylayout-to-kmn-converter.ts | 78 +++++++++---------- 1 file changed, 36 insertions(+), 42 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 5ecfc3e65c2..099617460bd 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -7,8 +7,8 @@ import { CompilerCallbacks, CompilerOptions } from "@keymanapp/developer-utils"; import { ConverterToKmnArtifacts } from "../converter-artifacts.js"; // TODO keylayout->kmn -// modifiers: The identifier of the element to use for this range of hardware keyboard types. -// defaultIndex: The table number to use for modifier key combinations which are not explicitly specified by any element within the . +// OK modifiers: The identifier of the element to use for this range of hardware keyboard types. +// OK defaultIndex: The table number to use for modifier key combinations which are not explicitly specified by any element within the . // write read, convert, write // tests for 3 functions read write convert // add data to object @@ -51,20 +51,15 @@ import * as fs from 'fs'; // what is this/do I need it? - either import all o export interface convert_object { name: string, // needed?? remove - ArrayOf_Layouts: any[], // needed?? I think no - ArrayOf_Ukelele_output: any[], - ArrayOf_Ukelele_action: any[], - ArrayOf_Modifiers: any[], - ArrayOf_VK_from_keylayout: any[], - ArrayOf_dk: any[], // add dk-mapping ( dk1 <-> '^' ) - ArrayOf_Dk: any[], // add plain dk ( '^', '´','`') - ArrayOf_deadkeyables: any[], // add char that can be modified with dk ( a,e,i,o,u) - ArrayOf_deadkeyedChar: any[], // add modified keys ( â,ê,î,ô,û) - ArrayOf_Terminators: any[] // add terminators ( ^,´,`) -}; - -export interface deadkey_all_object { - deadkeyedChars_all_Layers: string[][], // needed?? I think no + ArrayOf_Layouts: string[], // needed?? I think no + ArrayOf_Ukelele_output: any[], + ArrayOf_Ukelele_action: any[], + ArrayOf_Modifiers: string[], + ArrayOf_VK_from_keylayout: (string | number)[][], + ArrayOf_dk: string[][], // add dk-mapping ( dk1 <-> '^' ) + ArrayOf_deadkeyables: string[][], // add char that can be modified with dk ( a,e,i,o,u) + ArrayOf_deadkeyedChar: string[][], // add modified keys ( â,ê,î,ô,û) + ArrayOf_Terminators: Uint8Array[] // add terminators ( ^,´,`) }; @@ -144,12 +139,12 @@ export class KeylayoutToKmnConverter { // ToDo naming // TODO array-> object - const modifierMap_array: any[] = [] // array holding all MODIFIER strings e.g. "anyShift caps anyOption" -why not put modifiers into Uint8Array along with values of keys of layer - const keys_output_all_Layers: any[] = [] + const modifierMap_array: string[] = [] // array holding all MODIFIER strings e.g. "anyShift caps anyOption" -why not put modifiers into Uint8Array along with values of keys of layer + const keys_output_all_Layers: Uint8Array[][] = [] const keys_action_all_Layers: any[] = [] // array holding all values with ACTION attribute (needed for finding deadkeys) - const deadkeyedChars_all_Layers: any[] = [] // array holding all DEADKEYS for each mod state â, ê, ,.... - const terminators_all_Layers: any[] = [] // array holding all DEADKEYS for each mod state â, ê, ,.... - const duplicate_layouts_array: any[] = [] // array holding the layouts e.g. ANSI or JIS // needed?? I think no + const deadkeyedChars_all_Layers: string[][] = [] // array holding all DEADKEYS for each mod state â, ê, ,.... + const terminators_all_Layers: Uint8Array[] = [] // array holding all DEADKEYS for each mod state â, ê, ,.... + const duplicate_layouts_array: string[] = [] // array holding the layouts e.g. ANSI or JIS // needed?? I think no // TODO call: get only ANSI // Do I need to care or is there always ANSI which is always keyMapSet[0] @@ -185,7 +180,7 @@ export class KeylayoutToKmnConverter { */ // in case there always ANSI which is always keyMapSet[0] - const layouts_array: any[] = duplicate_layouts_array + const layouts_array: string[] = duplicate_layouts_array const keyMapSet_count = 0 // ----- @@ -243,14 +238,6 @@ export class KeylayoutToKmnConverter { } } - // ......................................................... - // ACTION: create array of deadkey base ^ ´ ` // TODO needed to add and distribute? - // ......................................................... - const dk: string[] = []; - for (let k = 0; k < dk_pairs_all_Layers.length; k++) { - dk.push(dk_pairs_all_Layers[k][1]) - } - // ......................................................... // ACTION: create array of "deadkeyables_all_Layers" - TODO can i use shorter function? // ......................................................... @@ -263,6 +250,11 @@ export class KeylayoutToKmnConverter { deadkeyables_one.push(resulting_character) } + const dk: string[] = []; + for (let k = 0; k < dk_pairs_all_Layers.length; k++) { + dk.push(dk_pairs_all_Layers[k][1]) + } + if (deadkeyables_one.length !== 0) { deadkeyables_all_Layers.push(deadkeyables_one) // filter out dk -> plain deadkeyables_all_Layers ( a,^, e,i,´,u => a,e,i,u) @@ -314,9 +306,9 @@ export class KeylayoutToKmnConverter { } } deadkeyedChars_all_Layers.push(deadkeys_One_dk) - console.log("typeof(deadkeyedChars_all_Layers)", typeof(deadkeyedChars_all_Layers),deadkeyedChars_all_Layers) } -const vk : any[] =[""] + + const vk: any[] = [""] // TODO remove unneccassary elements const DataObject: convert_object = { name: "Ukelele-kmn", // needed?? remove @@ -326,7 +318,6 @@ const vk : any[] =[""] ArrayOf_Modifiers: modifierMap_array, ArrayOf_VK_from_keylayout: vk, ArrayOf_dk: dk_pairs_all_Layers, // add dk-mapping ( dk1 <-> '^' ) - ArrayOf_Dk: dk, // add plain dk ( '^', '´','`') ArrayOf_deadkeyables: deadkeyables_all_Layers, // add char that can be modified with dk ( a,e,i,o,u) ArrayOf_deadkeyedChar: deadkeyedChars_all_Layers, // add modified keys ( â,ê,î,ô,û) ArrayOf_Terminators: terminators_all_Layers // add terminators ( ^,´,`) @@ -342,12 +333,12 @@ const vk : any[] =[""] * @param data_ukelele (Uint8Array) data of the ukelele .keylayout-file * @return outArray Uint8Array keys_all_Layers, the converted data for kmn-files if all layers have been converted; else null */ - public convert(data_ukelele: any): convert_object { - const data_VK_from_keylayout: any[][] = []; + public convert(data_ukelele: convert_object): convert_object { + const data_VK_from_keylayout: (string | number)[][] = []; for (let i = 0; i < data_ukelele.ArrayOf_Ukelele_output[0].length; i++) { - const data_VK_from_keylayout_pair: any[] = []; - const vk_from_Ukelele = this.map_UkeleleKC_To_VK(i) + const data_VK_from_keylayout_pair: (string | number)[] = []; + const vk_from_Ukelele: string = this.map_UkeleleKC_To_VK(i) data_VK_from_keylayout_pair.push(i) data_VK_from_keylayout_pair.push(vk_from_Ukelele) data_VK_from_keylayout.push(data_VK_from_keylayout_pair) @@ -417,7 +408,7 @@ const vk : any[] =[""] // get the character from keymap-section of .keylayout-file that will be written as result in kmn-file const resulting_character = new TextDecoder().decode(kmn_array.ArrayOf_Ukelele_output[i][j]) - const VK: number[][] = kmn_array.ArrayOf_VK_from_keylayout + const VK: (string | number)[][] = kmn_array.ArrayOf_VK_from_keylayout const vk_label = VK.filter(item => item[0] === kmn_array.ArrayOf_VK_from_keylayout[j][0]) // TODO remove j @@ -443,7 +434,7 @@ const vk : any[] =[""] const resulting_character = new TextDecoder().decode(kmn_array.ArrayOf_Ukelele_action[j][i]) if (resulting_character !== "") { - const VK: number[][] = kmn_array.ArrayOf_VK_from_keylayout + const VK: (string | number)[][] = kmn_array.ArrayOf_VK_from_keylayout const vk_label = VK.filter(item => item[0] === kmn_array.ArrayOf_VK_from_keylayout[i][0]) for (let k = 0; k < kmn_array.ArrayOf_dk.length; k++) { @@ -497,7 +488,7 @@ const vk : any[] =[""] * @param keylayout_modifier the modifier value used in the .keylayout-file * @return kmn_modifier the modifier value used in the .kmn-file */ - public create_modifier(keylayout_modifier: any, isCAPSused: boolean): string { + public create_modifier(keylayout_modifier: string, isCAPSused: boolean): string { let add_modifier = "" let kmn_modifier = "" let kmn_ncaps = "" @@ -563,7 +554,7 @@ const vk : any[] =[""] * @return keycode on Win Keyboard */ // TODO finish all entries - public map_UkeleleKC_To_VK(pos: any): any { + public map_UkeleleKC_To_VK(pos: number): string { // ukelele KC --> // VK_US if (pos === 0x0A) return "K_BKQUOTE" /* ^ */ @@ -592,7 +583,9 @@ const vk : any[] =[""] if (pos === 0x23) return "K_P" /* P */ if (pos === 0x21) return "K_LBRKT" /* [ */ if (pos === 0x1E) return "K_RBRKT" /* ] */ - if (pos === 0x32) return "K_BKSLASH" /* \ */ + //if (pos === 0x32) return "K_BKSLASH" /* \ */ + if (pos === 0x30) return "K_BKSLASH" /* \ */ // for ANSI correct?? + if (pos === 0x2A) return "K_BKSLASH" /* \ */ // for ISO correct?? if (pos === 0x00) return "K_A" /* A */ if (pos === 0x01) return "K_S" /* S */ @@ -620,6 +613,7 @@ const vk : any[] =[""] if (pos === 36) return "K_ENTER" if (pos === 49) return "K_SPACE" + else return "" } } From 0c0b3c1ab1c122771858551585051b35bbff8487 Mon Sep 17 00:00:00 2001 From: Sabine Date: Wed, 27 Nov 2024 07:57:26 +0100 Subject: [PATCH 021/251] feat(developer): kmc-convert: exchange even more any-types --- .../keylayout-to-kmn/keylayout-to-kmn-converter.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 099617460bd..3620883524f 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -24,7 +24,7 @@ import { ConverterToKmnArtifacts } from "../converter-artifacts.js"; // OK remove funcs at teh end // import { makePathToFixture } from '../../test/helpers/index.js'; // OK Mapping 0->30 or 0->K_A-> missing entries in mapping -// Replace any-types +// OK Replace any-types // Several steps action-> action-> action->character ( not only action->character) // TODO waht about using actions twice in a row??? // Usable for all keylayout files @@ -52,8 +52,8 @@ import * as fs from 'fs'; // what is this/do I need it? - either import all o export interface convert_object { name: string, // needed?? remove ArrayOf_Layouts: string[], // needed?? I think no - ArrayOf_Ukelele_output: any[], - ArrayOf_Ukelele_action: any[], + ArrayOf_Ukelele_output: Uint8Array[][], + ArrayOf_Ukelele_action: Uint8Array[][], ArrayOf_Modifiers: string[], ArrayOf_VK_from_keylayout: (string | number)[][], ArrayOf_dk: string[][], // add dk-mapping ( dk1 <-> '^' ) @@ -141,7 +141,7 @@ export class KeylayoutToKmnConverter { // TODO array-> object const modifierMap_array: string[] = [] // array holding all MODIFIER strings e.g. "anyShift caps anyOption" -why not put modifiers into Uint8Array along with values of keys of layer const keys_output_all_Layers: Uint8Array[][] = [] - const keys_action_all_Layers: any[] = [] // array holding all values with ACTION attribute (needed for finding deadkeys) + const keys_action_all_Layers: Uint8Array[][] = [] // array holding all values with ACTION attribute (needed for finding deadkeys) const deadkeyedChars_all_Layers: string[][] = [] // array holding all DEADKEYS for each mod state â, ê, ,.... const terminators_all_Layers: Uint8Array[] = [] // array holding all DEADKEYS for each mod state â, ê, ,.... const duplicate_layouts_array: string[] = [] // array holding the layouts e.g. ANSI or JIS // needed?? I think no @@ -307,8 +307,8 @@ export class KeylayoutToKmnConverter { } deadkeyedChars_all_Layers.push(deadkeys_One_dk) } - - const vk: any[] = [""] + + const vk: (string | number)[][] = [] // TODO remove unneccassary elements const DataObject: convert_object = { name: "Ukelele-kmn", // needed?? remove From 3188e57ecf2f7e7a2e4cb9cabfc255779490defe Mon Sep 17 00:00:00 2001 From: Sabine Date: Wed, 27 Nov 2024 15:47:42 +0100 Subject: [PATCH 022/251] feat(developer): kmc-convert: use callback for writing file --- .../keylayout-to-kmn-converter.ts | 240 ++++++++++++------ .../test/test-keylayout-to-kmn-converter.ts | 2 +- 2 files changed, 160 insertions(+), 82 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 3620883524f..a79f549490a 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -6,6 +6,9 @@ import { CompilerCallbacks, CompilerOptions } from "@keymanapp/developer-utils"; import { ConverterToKmnArtifacts } from "../converter-artifacts.js"; +/*import { util } from '@keymanapp/common-types'; //_S2 +import boxXmlArray = util.boxXmlArray;*/ + // TODO keylayout->kmn // OK modifiers: The identifier of the element to use for this range of hardware keyboard types. // OK defaultIndex: The table number to use for modifier key combinations which are not explicitly specified by any element within the . @@ -38,28 +41,86 @@ import { ConverterToKmnArtifacts } from "../converter-artifacts.js"; // Use catch blocks for file read // read: answer : + [K_A] > 'a' is OK / TODO which format to use in output ? + [K_A] > 'a' (character code) or + [K_A] > U+0061 (virt Keycode) // read TODO which stores? +// one entry vs several entry in tags + -// _S2 imports Sabine import { XMLParser } from 'fast-xml-parser'; // for reading a file import { readFileSync } from 'fs'; -import { writeFileSync } from "fs"; // for writing a file -import * as fs from 'fs'; // what is this/do I need it? - either import all or seperately like above +//import { writeFileSync } from "fs"; // for writing a file +//import * as fs from 'fs'; // what is this/do I need it? - either import all or seperately like above + + + +/*function boxXmlArray_S(o: any, x: string): void { + if(typeof o == 'object' && !Array.isArray(o[x])) { + if(o[x] === null || o[x] === undefined) { + o[x] = []; + } + else { + o[x] = [o[x]]; + } + } +}*/ +/* +// example: + + + + + + + + + + + + + + +then write: +if(source?.keyboard3?.AAA) { + + // parent tag child-tag + boxXmlArray(source?.keyboard3?.AAA, 'BBB'); + for(const BBB_Var of source?.keyboard3?.AAA?.BBB) { + boxXmlArray(BBB_Var, 'CCC'); + } +} +*/ + +// need to specify all elements!!! +// source = jsonObj.keyboard +/*function boxArrays_S(source: any) { + + // parent tag child-tag + // boxXmlArray(source.visualkeyboard, 'encoding'); + boxXmlArray_S(source.layoutsX, 'layoutX'); + + /* if(source?.keyboard3?.modifierMap) { + boxXmlArray_S(source?.keyboard3?.modifierMap, 'keyMapSelect'); + for(const keyMapSelect_Var of source?.keyboard3?.modifierMap?.keyMapSelect) { + boxXmlArray_S(keyMapSelect_Var, 'modifier'); + } + }*/ + //console.log("source",source) +/* return source; +}*/ export interface convert_object { - name: string, // needed?? remove - ArrayOf_Layouts: string[], // needed?? I think no - ArrayOf_Ukelele_output: Uint8Array[][], - ArrayOf_Ukelele_action: Uint8Array[][], - ArrayOf_Modifiers: string[], - ArrayOf_VK_from_keylayout: (string | number)[][], - ArrayOf_dk: string[][], // add dk-mapping ( dk1 <-> '^' ) - ArrayOf_deadkeyables: string[][], // add char that can be modified with dk ( a,e,i,o,u) - ArrayOf_deadkeyedChar: string[][], // add modified keys ( â,ê,î,ô,û) - ArrayOf_Terminators: Uint8Array[] // add terminators ( ^,´,`) + name: string, // needed?? remove + ArrayOf_Element_Layouts: string[], // needed?? I think no + ArrayOf_Element_KeyOutput: Uint8Array[][], + ArrayOf_Element_KeyAction: Uint8Array[][], + ArrayOf_Element_ModifierMaps: string[], + ArrayOf_Element_Terminators: Uint8Array[] // add terminators ( ^,´,`) + ArrayOf_processed_VK_from_keylayout: (string | number)[][], + ArrayOf_processed_dk: string[][], // add dk-mapping ( dk1 <-> '^' ) + ArrayOf_processed_deadkeyables: string[][], // add char that can be modified with dk ( a,e,i,o,u) + ArrayOf_processed_deadkeyedChar: string[][], // add modified keys ( â,ê,î,ô,û) }; @@ -68,8 +129,8 @@ export class KeylayoutToKmnConverter { static readonly OUTPUT_FILE_EXTENSION = '.kmn'; // TODO use callbacks - constructor(/*private*/ _callbacks: CompilerCallbacks, /*private*/ _options: CompilerOptions) { - // constructor(private callbacks: CompilerCallbacks, /*private*/ _options: CompilerOptions) { + //constructor(/*private*/ _callbacks: CompilerCallbacks, /*private*/ _options: CompilerOptions) { + constructor(private callbacks: CompilerCallbacks, options: CompilerOptions) { // TODO: if these are needed, uncomment /*private*/ and remove _, and they will then // be available as class properties } @@ -112,18 +173,33 @@ export class KeylayoutToKmnConverter { } /** - * @brief member function to read filename ( a .keylayout-file) and write contents into Uint8Array keys_all_Layers + * @brief take filename, open and read data from .keylayout-file and store in several arrays of the data object + * member function to read filename ( a .keylayout-file) and write contents into Uint8Array keys_all_Layers * @param filename the ukelele .keylayout-file to be converted * @return in case of success Uint8Array keys_all_Layers; else null */ public read(filename: string): convert_object { + /*const stringOptions = [ + 'layoutX', 'layoutsX', 'layout', 'layouts' + ]*/ + console.log("inputFilename read", filename) const options = { ignoreAttributes: false, - attributeNamePrefix: '@_', // to access the attribute + attributeNamePrefix: '@_' // to access the attribute + // ,arrayMode: true // create one single ele as array + // arrayMode: /layoutsX/ + // ,transformTagName: (layoutsX:any) => layoutsX.toLowerCase() + /*,isArray: (tagName: any) => { + if (stringOptions.includes(tagName)) return true; + else return false; + }*/ + }; + + //const xmlFile = readFileSync(`${process.cwd()}/data/MySample.keylayout`, 'utf8') const xmlFile = readFileSync((process.cwd() + "\\data" + filename.substring(filename.lastIndexOf("\\"))).replace(" ", ""), 'utf8'); @@ -137,15 +213,14 @@ export class KeylayoutToKmnConverter { const parser = new XMLParser(options); const jsonObj = parser.parse(xmlFile); // get plain Object - // ToDo naming - // TODO array-> object - const modifierMap_array: string[] = [] // array holding all MODIFIER strings e.g. "anyShift caps anyOption" -why not put modifiers into Uint8Array along with values of keys of layer + const modifierMap_all_Layers: string[] = [] // array holding all MODIFIER strings e.g. "anyShift caps anyOption" -why not put modifiers into Uint8Array along with values of keys of layer const keys_output_all_Layers: Uint8Array[][] = [] - const keys_action_all_Layers: Uint8Array[][] = [] // array holding all values with ACTION attribute (needed for finding deadkeys) - const deadkeyedChars_all_Layers: string[][] = [] // array holding all DEADKEYS for each mod state â, ê, ,.... - const terminators_all_Layers: Uint8Array[] = [] // array holding all DEADKEYS for each mod state â, ê, ,.... - const duplicate_layouts_array: string[] = [] // array holding the layouts e.g. ANSI or JIS // needed?? I think no + const keys_action_all_Layers: Uint8Array[][] = [] // array holding all values with ACTION attribute (needed for finding deadkeys) + const terminators_all_Layers: Uint8Array[] = [] // array holding all DEADKEYS for each mod state â, ê, ,.... + const duplicate_layouts_array: string[] = [] // array holding the layouts e.g. ANSI or JIS // needed?? I think no + const deadkeyedChars_all_Layers: string[][] = [] // array holding all DEADKEYS for each mod state â, ê, ,.... + // boxArrays_S(jsonObj.keyboard); // TODO call: get only ANSI // Do I need to care or is there always ANSI which is always keyMapSet[0] // if so code can be shortened @@ -153,7 +228,7 @@ export class KeylayoutToKmnConverter { // LAYOUTS: get all groups like ANSI JIS, remove JIS // ......................................................... - /* in case we need to find ANSI + // in case we need to find ANSI for (let i = 0; i < jsonObj.keyboard.layouts.layout.length; i++) { duplicate_layouts_array[i] = jsonObj.keyboard.layouts.layout[i]['@_mapSet'] } @@ -169,20 +244,11 @@ export class KeylayoutToKmnConverter { layouts_array.splice(i, 1); } - // TODO implement error & do what? - if(layouts_array.length > 1 ) - console.log("ERROR! too many layouts") - if(layouts_array.length < 1 ) - console.log("One layouts") - - // Todo better way ?? - const keyMapSet_count = layouts_array.length-1 -*/ - // in case there always ANSI which is always keyMapSet[0] - const layouts_array: string[] = duplicate_layouts_array + //const layouts_array: string[] = duplicate_layouts_array const keyMapSet_count = 0 + //console.log("layouts_array",layouts_array) // ----- const nrOfStates = jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap.length @@ -190,13 +256,14 @@ export class KeylayoutToKmnConverter { // ......................................................... - // KEYMAP: get all keys for attribute "output" and "action" - TODO can i use shorter function? + // KEYMAP: get all keys for attribute "modifiers" - TODO can i use shorter function? + // modifiers type string // ......................................................... // loop through all ss-combin for (let j = 0; j < nrOfStates; j++) { // get modifier list e.g. "anyshift caps? anyOption" - modifierMap_array[j] = jsonObj.keyboard.modifierMap.keyMapSelect[j].modifier['@_keys'] + modifierMap_all_Layers[j] = jsonObj.keyboard.modifierMap.keyMapSelect[j].modifier['@_keys'] // create a new array of keys_in_Layer (type Uint8tarray) const keys_output_One_Layer: Uint8Array[] = [] @@ -204,6 +271,7 @@ export class KeylayoutToKmnConverter { // ......................................................... // KEYMAP: get all keys for attribute "output" ( y,c,b,...) - TODO can i use shorter function? + // output type Uint8Array -> string // ......................................................... for (let i = 0; i < jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap[j].key.length; i++) { if (jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap[j].key[i]['@_output'] !== "\0") { @@ -214,6 +282,7 @@ export class KeylayoutToKmnConverter { // ......................................................... // KEYMAP: get all keys for attribute "action" ( ^,a,e,i,...) - TODO can i use shorter function? + // action type Uint8Array -> string // ......................................................... if (jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap[j].key[i]['@_action'] !== "\0") { keys_action_One_Layer[i] = new TextEncoder().encode(jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap[j].key[i]['@_action']); @@ -226,6 +295,7 @@ export class KeylayoutToKmnConverter { } // ......................................................... // ACTION: create array of "deadkey" / "deadkey names" - TODO can i use shorter function? + // action type string[] -> string[][] // ......................................................... const dk_pairs_all_Layers: string[][] = [] for (let jj = 0; jj < jsonObj.keyboard.actions.action.length; jj++) { @@ -240,6 +310,7 @@ export class KeylayoutToKmnConverter { // ......................................................... // ACTION: create array of "deadkeyables_all_Layers" - TODO can i use shorter function? + // deadkeyables_one type Uint8Array -> string[][] // ......................................................... const deadkeyables_all_Layers: string[][] = [] for (let j = 0; j < jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap.length; j++) { @@ -266,6 +337,7 @@ export class KeylayoutToKmnConverter { } // ......................................................... // TERMINATOR: create array of "terminators" - TODO can i use shorter function? what element of terminators do i need + // terminators when state type Uint8Array[] // ......................................................... for (let i = 0; i < jsonObj.keyboard.terminators.when.length; i++) { terminators_all_Layers[i] = jsonObj.keyboard.terminators.when[i] @@ -309,18 +381,19 @@ export class KeylayoutToKmnConverter { } const vk: (string | number)[][] = [] + // TODO remove unneccassary elements const DataObject: convert_object = { - name: "Ukelele-kmn", // needed?? remove - ArrayOf_Layouts: layouts_array, // needed?? I think no - ArrayOf_Ukelele_output: keys_output_all_Layers, - ArrayOf_Ukelele_action: keys_action_all_Layers, - ArrayOf_Modifiers: modifierMap_array, - ArrayOf_VK_from_keylayout: vk, - ArrayOf_dk: dk_pairs_all_Layers, // add dk-mapping ( dk1 <-> '^' ) - ArrayOf_deadkeyables: deadkeyables_all_Layers, // add char that can be modified with dk ( a,e,i,o,u) - ArrayOf_deadkeyedChar: deadkeyedChars_all_Layers, // add modified keys ( â,ê,î,ô,û) - ArrayOf_Terminators: terminators_all_Layers // add terminators ( ^,´,`) + name: "Ukelele-kmn", // needed?? remove + ArrayOf_Element_Layouts: layouts_array, // needed?? I think no + ArrayOf_Element_KeyOutput: keys_output_all_Layers, + ArrayOf_Element_KeyAction: keys_action_all_Layers, + ArrayOf_Element_ModifierMaps: modifierMap_all_Layers, + ArrayOf_Element_Terminators: terminators_all_Layers, // add terminators ( ^,´,`) + ArrayOf_processed_VK_from_keylayout: vk, + ArrayOf_processed_dk: dk_pairs_all_Layers, // add dk-mapping ( dk1 <-> '^' ) + ArrayOf_processed_deadkeyables: deadkeyables_all_Layers, // add char that can be modified with dk ( a,e,i,o,u) + ArrayOf_processed_deadkeyedChar: deadkeyedChars_all_Layers // add modified keys ( â,ê,î,ô,û) }; // TODO review condition @@ -330,32 +403,34 @@ export class KeylayoutToKmnConverter { /** * @brief member function to convert data of .keylayout-file to kmn-file This will convert/rename modifiers, position of Keys and deadkeys and save into an array - * @param data_ukelele (Uint8Array) data of the ukelele .keylayout-file + * @param take data_ukelele and create a mapping from mac Keycodes to key-names and save to data_ukelele object + * @param data_ukelele (Uint8Array) data of the ukelele .keylayout-file * @return outArray Uint8Array keys_all_Layers, the converted data for kmn-files if all layers have been converted; else null */ public convert(data_ukelele: convert_object): convert_object { const data_VK_from_keylayout: (string | number)[][] = []; - for (let i = 0; i < data_ukelele.ArrayOf_Ukelele_output[0].length; i++) { + for (let i = 0; i < data_ukelele.ArrayOf_Element_KeyOutput[0].length; i++) { + const data_VK_from_keylayout_pair: (string | number)[] = []; const vk_from_Ukelele: string = this.map_UkeleleKC_To_VK(i) + data_VK_from_keylayout_pair.push(i) data_VK_from_keylayout_pair.push(vk_from_Ukelele) data_VK_from_keylayout.push(data_VK_from_keylayout_pair) } - data_ukelele.ArrayOf_VK_from_keylayout = data_VK_from_keylayout - + data_ukelele.ArrayOf_processed_VK_from_keylayout = data_VK_from_keylayout return data_ukelele } /** - * @brief member function to write data to file - * @param kmn_array the array holding keyboard data + * @brief member function to write data fro object to file + * @param data_ukelele the array holding keyboard data * @return true if data has been written; false if not */ //TODO need to use export const USVirtualKeyCodes here - public write(kmn_array: convert_object): boolean { + public write(data_ukelele: convert_object): boolean { // ************************************************************* // **** write stores ******************************************* @@ -385,7 +460,7 @@ export class KeylayoutToKmnConverter { // if caps is used in .keylayout-file we need to add NCAPS in kmn-file let isCAPSused = false const used_Keys_count = 50 // do we need more than 50 keys?? - const modi: string[] = kmn_array.ArrayOf_Modifiers; + const modi: string[] = data_ukelele.ArrayOf_Element_ModifierMaps; const filteredModifiers: string[] = modi.filter((mod) => (String(mod) === ("caps"))) if (filteredModifiers.indexOf("caps") >= 0) isCAPSused = true @@ -401,19 +476,23 @@ export class KeylayoutToKmnConverter { data += '\n' // loop through modifiers - for (let i = 0; i < kmn_array.ArrayOf_Modifiers.length; i++) { + for (let i = 0; i < data_ukelele.ArrayOf_Element_ModifierMaps.length; i++) { - // get the modifier for the layer - const label_modifier = this.create_modifier(kmn_array.ArrayOf_Modifiers[i], isCAPSused) + // get the modifier for the layer e.g. "CAPS SHIFT" + const label_modifier = this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ModifierMaps[i], isCAPSused) + + // get Key name e.g. K_A + const VK: (string | number)[][] = data_ukelele.ArrayOf_processed_VK_from_keylayout + const vk_label = VK.filter(item => item[0] === data_ukelele.ArrayOf_processed_VK_from_keylayout[j][0]) // get the character from keymap-section of .keylayout-file that will be written as result in kmn-file - const resulting_character = new TextDecoder().decode(kmn_array.ArrayOf_Ukelele_output[i][j]) - const VK: (string | number)[][] = kmn_array.ArrayOf_VK_from_keylayout - const vk_label = VK.filter(item => item[0] === kmn_array.ArrayOf_VK_from_keylayout[j][0]) + const resulting_character = new TextDecoder().decode(data_ukelele.ArrayOf_Element_KeyOutput[i][j]) // TODO remove j - if (resulting_character !== '') + if (resulting_character !== '') { + // e.g. [ NCAPS K_J ] > ' j ' data += j + `+ [` + (label_modifier + ' ' + vk_label[0][1]).trim() + `] > \'` + resulting_character + '\'\n' + } } } @@ -423,23 +502,23 @@ export class KeylayoutToKmnConverter { // **** write deadkeys ***************************************** // ************************************************************* - for (let i = 0; i < kmn_array.ArrayOf_Ukelele_action[0].length; i++) { + for (let i = 0; i < data_ukelele.ArrayOf_Element_KeyAction[0].length; i++) { // loop through modifiers - for (let j = 0; j < kmn_array.ArrayOf_Modifiers.length; j++) { + for (let j = 0; j < data_ukelele.ArrayOf_Element_ModifierMaps.length; j++) { // get the modifier for the layer - const label_modifier = this.create_modifier(kmn_array.ArrayOf_Modifiers[j], isCAPSused) + const label_modifier = this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ModifierMaps[j], isCAPSused) // get the character from keymap-section of .keylayout-file that will be written as result in kmn-file - const resulting_character = new TextDecoder().decode(kmn_array.ArrayOf_Ukelele_action[j][i]) + const resulting_character = new TextDecoder().decode(data_ukelele.ArrayOf_Element_KeyAction[j][i]) if (resulting_character !== "") { - const VK: (string | number)[][] = kmn_array.ArrayOf_VK_from_keylayout - const vk_label = VK.filter(item => item[0] === kmn_array.ArrayOf_VK_from_keylayout[i][0]) + const VK: (string | number)[][] = data_ukelele.ArrayOf_processed_VK_from_keylayout + const vk_label = VK.filter(item => item[0] === data_ukelele.ArrayOf_processed_VK_from_keylayout[i][0]) - for (let k = 0; k < kmn_array.ArrayOf_dk.length; k++) { - if ((resulting_character !== "") && (resulting_character === kmn_array.ArrayOf_dk[k][1])) { - data += '[' + (label_modifier + ' ' + vk_label[0][1]).trim() + '] ' + "> dk(" + this.getHexFromChar(kmn_array.ArrayOf_dk[k][1]) + ") " + '\n' + for (let k = 0; k < data_ukelele.ArrayOf_processed_dk.length; k++) { + if ((resulting_character !== "") && (resulting_character === data_ukelele.ArrayOf_processed_dk[k][1])) { + data += '[' + (label_modifier + ' ' + vk_label[0][1]).trim() + '] ' + "> dk(" + this.getHexFromChar(data_ukelele.ArrayOf_processed_dk[k][1]) + ") " + '\n' } } } @@ -451,18 +530,17 @@ export class KeylayoutToKmnConverter { data += "group(deadkeys)\n" data += "\n" - for (let i = 0; i < kmn_array.ArrayOf_deadkeyables.length; i++) { - if (kmn_array.ArrayOf_deadkeyedChar[i] !== undefined) { - data += "store(dkf" + this.getHexFromChar(kmn_array.ArrayOf_dk[i][1]) + ") " + ("\'" + String(kmn_array.ArrayOf_deadkeyables[i])).replace(/\,+/g, "' '") + "'\n" - data += "store(dkt" + this.getHexFromChar(kmn_array.ArrayOf_dk[i][1]) + ") " + ("\'" + String(kmn_array.ArrayOf_deadkeyedChar[i])).replace(/\,+/g, "' '") + "'\n" + for (let i = 0; i < data_ukelele.ArrayOf_processed_deadkeyables.length; i++) { + if (data_ukelele.ArrayOf_processed_deadkeyedChar[i] !== undefined) { + data += "store(dkf" + this.getHexFromChar(data_ukelele.ArrayOf_processed_dk[i][1]) + ") " + ("\'" + String(data_ukelele.ArrayOf_processed_deadkeyables[i])).replace(/\,+/g, "' '") + "'\n" + data += "store(dkt" + this.getHexFromChar(data_ukelele.ArrayOf_processed_dk[i][1]) + ") " + ("\'" + String(data_ukelele.ArrayOf_processed_deadkeyedChar[i])).replace(/\,+/g, "' '") + "'\n" data += '\n' } } - // Todo use writefile from elsewhere - writeFileSync("data/MyResult.kmn", data, { flag: "w" }) - fs.writeFileSync("data/MyResult_fs.kmn", data, { flag: "w" }) - //this.callbacks.fs.writeFileSync("data/MyResult_callb_fs.kmn", data) // not usable here since it takes UInt8array data + /*writeFileSync("data/MyResult.kmn", data, { flag: "w" })*/ + const data_encoded = new TextEncoder().encode(data) + this.callbacks.fs.writeFileSync("data/MyResult.kmn", data_encoded) // not usable here since it takes UInt8array data // ToDo conditions? if (data.length > 0) @@ -488,7 +566,7 @@ export class KeylayoutToKmnConverter { * @param keylayout_modifier the modifier value used in the .keylayout-file * @return kmn_modifier the modifier value used in the .kmn-file */ - public create_modifier(keylayout_modifier: string, isCAPSused: boolean): string { + public create_kmn_modifier(keylayout_modifier: string, isCAPSused: boolean): string { let add_modifier = "" let kmn_modifier = "" let kmn_ncaps = "" diff --git a/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts index 55f5516bed9..0491b11688f 100644 --- a/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts @@ -38,7 +38,7 @@ describe('KeylayoutToKmnConverter', function() { const inputFilename = makePathToFixture('../data/My_dk_Keyboard.keylayout'); //const inputFilename = makePathToFixture('../data/US_complete.keylayout'); //const inputFilename = makePathToFixture('../data/Italian_copy.keylayout'); - + const outputFilename = makePathToFixture('../data/MyResult.kmn'); // TODO check filename if correct console.log(' inputFilename', inputFilename) From d3bfdc275efcfef3219ddcc1f40f6f2eb21d27fa Mon Sep 17 00:00:00 2001 From: Sabine Date: Fri, 29 Nov 2024 07:11:58 +0100 Subject: [PATCH 023/251] feat(developer): kmc-convert: box Layout, keyMapSelect, Terminators-when --- .../keylayout-to-kmn-converter.ts | 126 ++++++++++++------ 1 file changed, 83 insertions(+), 43 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index a79f549490a..a8df1551535 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -51,31 +51,31 @@ import { readFileSync } from 'fs'; -/*function boxXmlArray_S(o: any, x: string): void { - if(typeof o == 'object' && !Array.isArray(o[x])) { - if(o[x] === null || o[x] === undefined) { +function boxXmlArray_S(o: any, x: string): void { + if (typeof o == 'object' && !Array.isArray(o[x])) { + if (o[x] === null || o[x] === undefined) { o[x] = []; } else { o[x] = [o[x]]; } } -}*/ +} /* // example: - - - - - - - - - - - - + + + + + + + + + + + + then write: if(source?.keyboard3?.AAA) { @@ -90,23 +90,29 @@ if(source?.keyboard3?.AAA) { // need to specify all elements!!! // source = jsonObj.keyboard -/*function boxArrays_S(source: any) { - +function boxArrays_S(source: any) { + + //console.log("source... before boxing",typeof(source.layoutsX),source.layoutsX) + console.log("source... before boxing", typeof (source.terminators), source.terminators) // parent tag child-tag // boxXmlArray(source.visualkeyboard, 'encoding'); - boxXmlArray_S(source.layoutsX, 'layoutX'); - - /* if(source?.keyboard3?.modifierMap) { - boxXmlArray_S(source?.keyboard3?.modifierMap, 'keyMapSelect'); - for(const keyMapSelect_Var of source?.keyboard3?.modifierMap?.keyMapSelect) { - boxXmlArray_S(keyMapSelect_Var, 'modifier'); - } - }*/ - - - //console.log("source",source) -/* return source; -}*/ + //boxXmlArray_S(source.layoutsX, 'layoutX'); + boxXmlArray_S(source.layouts, 'layout'); + boxXmlArray_S(source.modifierMap, 'keyMapSelect'); + boxXmlArray_S(source.terminators, 'when'); + + /* if(source?.keyboard3?.modifierMap) { + boxXmlArray_S(source?.keyboard3?.modifierMap, 'keyMapSelect'); + for(const keyMapSelect_Var of source?.keyboard3?.modifierMap?.keyMapSelect) { + boxXmlArray_S(keyMapSelect_Var, 'modifier'); + } + }*/ + + + //console.log("source... after boxing",typeof(source.layoutsX),source.layoutsX) + console.log("source... after boxing", typeof (source.terminators), source.terminators) + return source; +} @@ -130,7 +136,7 @@ export class KeylayoutToKmnConverter { // TODO use callbacks //constructor(/*private*/ _callbacks: CompilerCallbacks, /*private*/ _options: CompilerOptions) { - constructor(private callbacks: CompilerCallbacks, options: CompilerOptions) { + constructor(private callbacks: CompilerCallbacks, options: CompilerOptions) { // TODO: if these are needed, uncomment /*private*/ and remove _, and they will then // be available as class properties } @@ -195,10 +201,10 @@ export class KeylayoutToKmnConverter { if (stringOptions.includes(tagName)) return true; else return false; }*/ - + }; - + //const xmlFile = readFileSync(`${process.cwd()}/data/MySample.keylayout`, 'utf8') const xmlFile = readFileSync((process.cwd() + "\\data" + filename.substring(filename.lastIndexOf("\\"))).replace(" ", ""), 'utf8'); @@ -220,7 +226,7 @@ export class KeylayoutToKmnConverter { const duplicate_layouts_array: string[] = [] // array holding the layouts e.g. ANSI or JIS // needed?? I think no const deadkeyedChars_all_Layers: string[][] = [] // array holding all DEADKEYS for each mod state â, ê, ,.... - // boxArrays_S(jsonObj.keyboard); + boxArrays_S(jsonObj.keyboard); // TODO call: get only ANSI // Do I need to care or is there always ANSI which is always keyMapSet[0] // if so code can be shortened @@ -228,8 +234,8 @@ export class KeylayoutToKmnConverter { // LAYOUTS: get all groups like ANSI JIS, remove JIS // ......................................................... - // in case we need to find ANSI - for (let i = 0; i < jsonObj.keyboard.layouts.layout.length; i++) { + // in case we need to find ANSI + for (let i = 0; i < jsonObj.keyboard.layouts.layout.length; i++) { duplicate_layouts_array[i] = jsonObj.keyboard.layouts.layout[i]['@_mapSet'] } @@ -240,10 +246,10 @@ export class KeylayoutToKmnConverter { // remove JIS (if keyMap contains baseMapSet it`s JIS) for (let i = 0; i < layouts_array.length; i++) { - if(jsonObj.keyboard.keyMapSet[i].keyMap[0]['@_baseMapSet']) - layouts_array.splice(i, 1); + if (jsonObj.keyboard.keyMapSet[i].keyMap[0]['@_baseMapSet']) + layouts_array.splice(i, 1); } - + // in case there always ANSI which is always keyMapSet[0] //const layouts_array: string[] = duplicate_layouts_array const keyMapSet_count = 0 @@ -261,10 +267,9 @@ export class KeylayoutToKmnConverter { // ......................................................... // loop through all ss-combin + console.log("nrOfStates", nrOfStates) for (let j = 0; j < nrOfStates; j++) { - // get modifier list e.g. "anyshift caps? anyOption" modifierMap_all_Layers[j] = jsonObj.keyboard.modifierMap.keyMapSelect[j].modifier['@_keys'] - // create a new array of keys_in_Layer (type Uint8tarray) const keys_output_One_Layer: Uint8Array[] = [] const keys_action_One_Layer: Uint8Array[] = [] @@ -380,7 +385,7 @@ export class KeylayoutToKmnConverter { deadkeyedChars_all_Layers.push(deadkeys_One_dk) } - const vk: (string | number)[][] = [] + const vk: (string | number)[][] = [] // TODO remove unneccassary elements const DataObject: convert_object = { @@ -396,6 +401,41 @@ export class KeylayoutToKmnConverter { ArrayOf_processed_deadkeyedChar: deadkeyedChars_all_Layers // add modified keys ( â,ê,î,ô,û) }; + console.log("-----\nTypeOf:") + console.log("\n" + , "\n jsonObj.keyboard: ", typeof (jsonObj.keyboard) + , "\n jsonObj.keyboard.layouts: ", typeof (jsonObj.keyboard.layouts) + , "\n jsonObj.keyboard.layouts.layout: ", typeof (jsonObj.keyboard.layouts.layout) + , "\n jsonObj.keyboard.modifierMap: ", typeof (jsonObj.keyboard.modifierMap) + , "\n jsonObj.keyboard.modifierMap.keyMapSelect: ", typeof (jsonObj.keyboard.modifierMap.keyMapSelect) + , "\n jsonObj.keyboard.modifierMap.keyMapSelect[0].modifier: ", typeof (jsonObj.keyboard.modifierMap.keyMapSelect[0].modifier) + , "\n jsonObj.keyboard.keyMapSet: ", typeof (jsonObj.keyboard.keyMapSet) + , "\n jsonObj.keyboard.keyMapSet[0].keyMap: ", typeof (jsonObj.keyboard.keyMapSet[0].keyMap) + , "\n jsonObj.keyboard.keyMapSet[0].keyMap[0].key: ", typeof (jsonObj.keyboard.keyMapSet[0].keyMap[0].key) + , "\n jsonObj.keyboard.actions : ", typeof (jsonObj.keyboard.actions) + , "\n jsonObj.keyboard.actions.action[0] : ", typeof (jsonObj.keyboard.actions.action[0]) + , "\n jsonObj.keyboard.terminators: ", typeof (jsonObj.keyboard.terminators) + , "\n jsonObj.keyboard.terminators.when: ", typeof (jsonObj.keyboard.terminators.when) + , "\n jsonObj.keyboard.actions.action[0].when: ", typeof (jsonObj.keyboard.actions.action[0].when) + ) + + console.log("-----\nplus:") + console.log("Address loke\n" + , "\n jsonObj.keyboard: ", (jsonObj.keyboard) + , "\n jsonObj.keyboard.layouts: ", (jsonObj.keyboard.layouts) + , "\n jsonObj.keyboard.layouts.layout: ", (jsonObj.keyboard.layouts.layout) + , "\n jsonObj.keyboard.modifierMap: ", (jsonObj.keyboard.modifierMap) + , "\n jsonObj.keyboard.modifierMap.keyMapSelect: ", (jsonObj.keyboard.modifierMap.keyMapSelect) + , "\n jsonObj.keyboard.modifierMap.keyMapSelect[0].modifier: ", (jsonObj.keyboard.modifierMap.keyMapSelect[0].modifier) + , "\n jsonObj.keyboard.keyMapSet: ", (jsonObj.keyboard.keyMapSet) + , "\n jsonObj.keyboard.keyMapSet[0].keyMap: ", (jsonObj.keyboard.keyMapSet[0].keyMap) + , "\n jsonObj.keyboard.keyMapSet[0].keyMap[0].key: ", (jsonObj.keyboard.keyMapSet[0].keyMap[0].key) + , "\n jsonObj.keyboard.actions : ", (jsonObj.keyboard.actions) + , "\n jsonObj.keyboard.actions.action[0] : ", (jsonObj.keyboard.actions.action[0]) + , "\n jsonObj.keyboard.actions.action[0].when: ", (jsonObj.keyboard.actions.action[0].when) + , "\n jsonObj.keyboard.terminators: ", (jsonObj.keyboard.terminators) + , "\n jsonObj.keyboard.terminators.when: ", (jsonObj.keyboard.terminators.when) + ) // TODO review condition return DataObject //return ((keys_output_all_Layers.length === nrOfStates + 5) && keys_output_all_Layers[0].length === nrOfKeys_inLayer) ? keys_output_all_Layers : null; From 6296cfcea2e85e8abffae34c77b17deae394f377 Mon Sep 17 00:00:00 2001 From: Sabine Date: Thu, 5 Dec 2024 14:32:25 +0100 Subject: [PATCH 024/251] feat(developer): kmc-convert: write deadkeys --- .../keylayout-to-kmn-converter.ts | 395 ++++++++++++------ .../test/test-keylayout-to-kmn-converter.ts | 10 +- 2 files changed, 269 insertions(+), 136 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index a8df1551535..f07a0869ede 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -42,6 +42,11 @@ import boxXmlArray = util.boxXmlArray;*/ // read: answer : + [K_A] > 'a' is OK / TODO which format to use in output ? + [K_A] > 'a' (character code) or + [K_A] > U+0061 (virt Keycode) // read TODO which stores? // one entry vs several entry in tags +// false arrangement of tags +// no added NCAPS when first modifier in modifierMap does not contain "caps" or"caps?" +// use length to clear array instead of defining evetry time new (modifierMap_ONE_InKeymapSelect.length=0 +// naming of for-loop var i,j,k?... + import { XMLParser } from 'fast-xml-parser'; // for reading a file @@ -91,26 +96,21 @@ if(source?.keyboard3?.AAA) { // need to specify all elements!!! // source = jsonObj.keyboard function boxArrays_S(source: any) { - - //console.log("source... before boxing",typeof(source.layoutsX),source.layoutsX) - console.log("source... before boxing", typeof (source.terminators), source.terminators) - // parent tag child-tag - // boxXmlArray(source.visualkeyboard, 'encoding'); - //boxXmlArray_S(source.layoutsX, 'layoutX'); + // parent tag child-tag boxXmlArray_S(source.layouts, 'layout'); - boxXmlArray_S(source.modifierMap, 'keyMapSelect'); boxXmlArray_S(source.terminators, 'when'); + boxXmlArray_S(source, 'keyMapSet'); + boxXmlArray_S(source.keyMapSet, 'keyMap'); + boxXmlArray_S(source.action, 'actions'); - /* if(source?.keyboard3?.modifierMap) { - boxXmlArray_S(source?.keyboard3?.modifierMap, 'keyMapSelect'); - for(const keyMapSelect_Var of source?.keyboard3?.modifierMap?.keyMapSelect) { - boxXmlArray_S(keyMapSelect_Var, 'modifier'); - } - }*/ - - - //console.log("source... after boxing",typeof(source.layoutsX),source.layoutsX) - console.log("source... after boxing", typeof (source.terminators), source.terminators) + boxXmlArray_S(source?.modifierMap, 'keyMapSelect'); + for (const keyMapSelect of source?.modifierMap?.keyMapSelect) { + boxXmlArray_S(keyMapSelect, 'modifier'); + } + boxXmlArray_S(source?.actions, 'action'); + for (const action of source?.actions?.action) { + boxXmlArray_S(action, 'when'); + } return source; } @@ -121,7 +121,8 @@ export interface convert_object { ArrayOf_Element_Layouts: string[], // needed?? I think no ArrayOf_Element_KeyOutput: Uint8Array[][], ArrayOf_Element_KeyAction: Uint8Array[][], - ArrayOf_Element_ModifierMaps: string[], + ArrayOf_Element_ALL_ModifierMaps: string[], + ArrayOf_Element_ModifierMaps_ALLKeyMapSelect: string[][], ArrayOf_Element_Terminators: Uint8Array[] // add terminators ( ^,´,`) ArrayOf_processed_VK_from_keylayout: (string | number)[][], ArrayOf_processed_dk: string[][], // add dk-mapping ( dk1 <-> '^' ) @@ -168,6 +169,7 @@ export class KeylayoutToKmnConverter { } console.log(' _S2 then WRITE to kmn .....................................'); + const out = this.write(outArray) if (!out) { return null; @@ -186,26 +188,14 @@ export class KeylayoutToKmnConverter { */ public read(filename: string): convert_object { - /*const stringOptions = [ - 'layoutX', 'layoutsX', 'layout', 'layouts' - ]*/ - console.log("inputFilename read", filename) const options = { ignoreAttributes: false, attributeNamePrefix: '@_' // to access the attribute - // ,arrayMode: true // create one single ele as array - // arrayMode: /layoutsX/ - // ,transformTagName: (layoutsX:any) => layoutsX.toLowerCase() - /*,isArray: (tagName: any) => { - if (stringOptions.includes(tagName)) return true; - else return false; - }*/ - }; - + console.log("xmlFile_name", (process.cwd() + "\\data" + filename.substring(filename.lastIndexOf("\\"))).replace(" ", "")) //const xmlFile = readFileSync(`${process.cwd()}/data/MySample.keylayout`, 'utf8') const xmlFile = readFileSync((process.cwd() + "\\data" + filename.substring(filename.lastIndexOf("\\"))).replace(" ", ""), 'utf8'); @@ -213,12 +203,12 @@ export class KeylayoutToKmnConverter { /*const fullPath = (process.cwd() + "\\data" + filename.substring(filename.lastIndexOf("\\"))).replace(" ", "") const xmlFile1 = this.callbacks.loadFile(fullPath) console.log("xmlFile1",xmlFile1)*/ - //console.log("xmlFile",xmlFile) + console.log("layouts_array read ") const parser = new XMLParser(options); const jsonObj = parser.parse(xmlFile); // get plain Object - + const modifierMap_ALL_KeyMapSelects: string[][] = [] // modifier for each keymapselect const modifierMap_all_Layers: string[] = [] // array holding all MODIFIER strings e.g. "anyShift caps anyOption" -why not put modifiers into Uint8Array along with values of keys of layer const keys_output_all_Layers: Uint8Array[][] = [] const keys_action_all_Layers: Uint8Array[][] = [] // array holding all values with ACTION attribute (needed for finding deadkeys) @@ -226,7 +216,11 @@ export class KeylayoutToKmnConverter { const duplicate_layouts_array: string[] = [] // array holding the layouts e.g. ANSI or JIS // needed?? I think no const deadkeyedChars_all_Layers: string[][] = [] // array holding all DEADKEYS for each mod state â, ê, ,.... + let dk_pairs_all_Layers: string[][] = [] // add dk-mapping ( dk1 <-> '^' ) + boxArrays_S(jsonObj.keyboard); + + // fill arrays // TODO call: get only ANSI // Do I need to care or is there always ANSI which is always keyMapSet[0] // if so code can be shortened @@ -243,37 +237,32 @@ export class KeylayoutToKmnConverter { const layouts_array: any[] = duplicate_layouts_array.filter(function (item, pos, self) { return self.indexOf(item) == pos; }) - // remove JIS (if keyMap contains baseMapSet it`s JIS) for (let i = 0; i < layouts_array.length; i++) { if (jsonObj.keyboard.keyMapSet[i].keyMap[0]['@_baseMapSet']) layouts_array.splice(i, 1); } - // in case there always ANSI which is always keyMapSet[0] //const layouts_array: string[] = duplicate_layouts_array const keyMapSet_count = 0 - //console.log("layouts_array",layouts_array) - // ----- + //#### end layouts ############################################################################################################################################### - const nrOfStates = jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap.length - //const nrOfKeys_inLayer = jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap[0].key.length // will they all have the same length later ? + for (let j = 0; j < jsonObj.keyboard.modifierMap.keyMapSelect.length; j++) { + const modifierMap_ONE_InKeymapSelect: string[] = [] + for (let k = 0; k < jsonObj.keyboard.modifierMap.keyMapSelect[j].modifier.length; k++) { + modifierMap_all_Layers.push(jsonObj.keyboard.modifierMap.keyMapSelect[j].modifier[k]['@_keys']) + modifierMap_ONE_InKeymapSelect.push(jsonObj.keyboard.modifierMap.keyMapSelect[j].modifier[k]['@_keys']) + } + modifierMap_ALL_KeyMapSelects.push(modifierMap_ONE_InKeymapSelect) - // ......................................................... - // KEYMAP: get all keys for attribute "modifiers" - TODO can i use shorter function? - // modifiers type string - // ......................................................... - - // loop through all ss-combin - console.log("nrOfStates", nrOfStates) - for (let j = 0; j < nrOfStates; j++) { - modifierMap_all_Layers[j] = jsonObj.keyboard.modifierMap.keyMapSelect[j].modifier['@_keys'] // create a new array of keys_in_Layer (type Uint8tarray) const keys_output_One_Layer: Uint8Array[] = [] const keys_action_One_Layer: Uint8Array[] = [] + //#### end modifierMap ############################################################################################################################################### + // ......................................................... // KEYMAP: get all keys for attribute "output" ( y,c,b,...) - TODO can i use shorter function? // output type Uint8Array -> string @@ -284,7 +273,7 @@ export class KeylayoutToKmnConverter { // textencoder is of Uint8Array(1) for A and Uint8Array(3) for ☺ keys_output_One_Layer[i] = new TextEncoder().encode(jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap[j].key[i]['@_output']); } - + // ToDo do I need empty fields in keys_output_all_Layers, keys_action_all_Layers // ......................................................... // KEYMAP: get all keys for attribute "action" ( ^,a,e,i,...) - TODO can i use shorter function? // action type Uint8Array -> string @@ -293,53 +282,118 @@ export class KeylayoutToKmnConverter { keys_action_One_Layer[i] = new TextEncoder().encode(jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap[j].key[i]['@_action']); } } + // ......................................................... // create array of "action" and array of "output" keys_output_all_Layers.push(keys_output_One_Layer) // save all @output data ( will be used for conversion, write...) keys_action_all_Layers.push(keys_action_One_Layer) // save all @action data ( will be used for deadkeys) + + + //#### end output+action ############################################################################################################################################### } + // ......................................................... // ACTION: create array of "deadkey" / "deadkey names" - TODO can i use shorter function? // action type string[] -> string[][] // ......................................................... - const dk_pairs_all_Layers: string[][] = [] + const dk_pairs_all_Layers_max: string[][] = [] + + // C3 state none + next Nr => deadkeys + console.log("--------------------------------") + + // loop through actions and get the value of attribute "next" (which indicates this is a deadkey) for (let jj = 0; jj < jsonObj.keyboard.actions.action.length; jj++) { - // if there is a "next" attribute-> it is a dk - if (jsonObj.keyboard.actions.action[jj].when['@_next'] !== undefined) { - const vec1d: string[] = [] - vec1d.push(jsonObj.keyboard.actions.action[jj].when['@_next']) - vec1d.push(jsonObj.keyboard.actions.action[jj]['@_id']) - dk_pairs_all_Layers.push(vec1d) + for (let kk = 0; kk < jsonObj.keyboard.actions.action[jj].when.length; kk++) { + + if (jsonObj.keyboard.actions.action[jj].when[kk]['@_next'] !== undefined) { + const vec1d: string[] = [] + let dk_to_print + + const text_attribute_next = jsonObj.keyboard.actions.action[jj].when[kk]['@_next'] + + // loop through terminators and get output of that next state + for (let n = 0; n < jsonObj.keyboard.terminators.when.length; n++) { + if (jsonObj.keyboard.terminators.when[n]['@_state'] === text_attribute_next) + dk_to_print = jsonObj.keyboard.terminators.when[n]['@_output'] + } + + vec1d.push(text_attribute_next) + vec1d.push(dk_to_print) + vec1d.push(jsonObj.keyboard.actions.action[jj]['@_id']) // todo remove later + dk_pairs_all_Layers_max.push(vec1d) + } } } + dk_pairs_all_Layers = dk_pairs_all_Layers_max.filter(function (item, pos, self) { + return self.indexOf(item) == pos; + }) + + const dk: string[] = []; // ......................................................... // ACTION: create array of "deadkeyables_all_Layers" - TODO can i use shorter function? // deadkeyables_one type Uint8Array -> string[][] // ......................................................... const deadkeyables_all_Layers: string[][] = [] + // needed? we just want ANSI = the first one for (let j = 0; j < jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap.length; j++) { const deadkeyables_one: string[] = [] + // loop through all keys of ANSI for (let i = 0; i < jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap[0].key.length; i++) { - const resulting_character = new TextDecoder().decode(keys_action_all_Layers[j][i]) + + // find output in action id + let dk_char + for (let jj = 0; jj < jsonObj.keyboard.actions.action.length; jj++) { + + // find the action ID which was specified in keymap->key->action e.g. a19 + const action_name = new TextDecoder().decode(keys_action_all_Layers[j][i]) + + if (action_name !== "") { + + // find action id in actions->action e.g. a19 + if (jsonObj.keyboard.actions.action[jj]['@_id'] === action_name) { + + //a85 + + // 4 cases: + // C1 state none + output => + // C2 state Nr + output => + // OK C3 state none + next Nr => deadkeys see above + // C4 state Nr + next Nr => loop deadkeyables + + if (jsonObj.keyboard.actions.action[jj].when[0]['@_state'] === "none") { + dk_char = jsonObj.keyboard.actions.action[jj].when[0]['@_output'] + } + } + } + } + + + + //const resulting_character = new TextDecoder().decode(keys_action_all_Layers[j][i]) + const resulting_character = dk_char + if (resulting_character !== "") deadkeyables_one.push(resulting_character) } - const dk: string[] = []; for (let k = 0; k < dk_pairs_all_Layers.length; k++) { dk.push(dk_pairs_all_Layers[k][1]) } if (deadkeyables_one.length !== 0) { deadkeyables_all_Layers.push(deadkeyables_one) - // filter out dk -> plain deadkeyables_all_Layers ( a,^, e,i,´,u => a,e,i,u) - // return all that don`t find ^,´, ` - deadkeyables_all_Layers[j] = deadkeyables_all_Layers[j].filter(function (el) { - return dk.indexOf(el) < 0; - }); } } + + for (let j = 0; j < deadkeyables_all_Layers.length; j++) { + // filter out dk -> plain deadkeyables_all_Layers ( a,^, e,i,´,u => a,e,i,u) + // return all that don`t find ^,´, ` + deadkeyables_all_Layers[j] = deadkeyables_all_Layers[j].filter(function (el) { + return dk.indexOf(el) < 0; + }); + } + // ......................................................... // TERMINATOR: create array of "terminators" - TODO can i use shorter function? what element of terminators do i need // terminators when state type Uint8Array[] @@ -358,17 +412,27 @@ export class KeylayoutToKmnConverter { // find this value in // in their 'when' find output for dk // for all 'action' at keys paragraph + + for (let j = 0; j < dk_pairs_all_Layers.length; j++) { + + //console.log("bis hier j", j) const deadkeys_One_dk: string[] = [] // find in action e.g. for (let k = 0; k < keys_action_all_Layers[j].length; k++) { + + //console.log("bis hier k", k) const action_from_keys_prargraph = new TextDecoder().decode(keys_action_all_Layers[j][k]) if (action_from_keys_prargraph !== "") { // find the same id (e.g. ) in the actions-paragraph for (let l = 0; l < jsonObj.keyboard.actions.action.length; l++) { + + //console.log("bis hier l", l) if (jsonObj.keyboard.actions.action[l]['@_id'] === action_from_keys_prargraph) { // loop through when until dk name (e.g. dk s0) for (let m = 0; m < jsonObj.keyboard.actions.action[l].when.length; m++) { + + // console.log("bis hier m", m) // and get their @_output if (jsonObj.keyboard.actions.action[l].when[m]['@_state'] === dk_pairs_all_Layers[j][0]) { // todo push only if @output is found. if next is found: get value from terminators @@ -385,6 +449,7 @@ export class KeylayoutToKmnConverter { deadkeyedChars_all_Layers.push(deadkeys_One_dk) } + const vk: (string | number)[][] = [] // TODO remove unneccassary elements @@ -393,49 +458,16 @@ export class KeylayoutToKmnConverter { ArrayOf_Element_Layouts: layouts_array, // needed?? I think no ArrayOf_Element_KeyOutput: keys_output_all_Layers, ArrayOf_Element_KeyAction: keys_action_all_Layers, - ArrayOf_Element_ModifierMaps: modifierMap_all_Layers, + ArrayOf_Element_ALL_ModifierMaps: modifierMap_all_Layers, // all 18 modifiers in 1 array + ArrayOf_Element_ModifierMaps_ALLKeyMapSelect: modifierMap_ALL_KeyMapSelects, // 18 modifiers in 8 KeyMapSelect(behaviors) ArrayOf_Element_Terminators: terminators_all_Layers, // add terminators ( ^,´,`) ArrayOf_processed_VK_from_keylayout: vk, ArrayOf_processed_dk: dk_pairs_all_Layers, // add dk-mapping ( dk1 <-> '^' ) + ArrayOf_processed_deadkeyables: deadkeyables_all_Layers, // add char that can be modified with dk ( a,e,i,o,u) ArrayOf_processed_deadkeyedChar: deadkeyedChars_all_Layers // add modified keys ( â,ê,î,ô,û) }; - console.log("-----\nTypeOf:") - console.log("\n" - , "\n jsonObj.keyboard: ", typeof (jsonObj.keyboard) - , "\n jsonObj.keyboard.layouts: ", typeof (jsonObj.keyboard.layouts) - , "\n jsonObj.keyboard.layouts.layout: ", typeof (jsonObj.keyboard.layouts.layout) - , "\n jsonObj.keyboard.modifierMap: ", typeof (jsonObj.keyboard.modifierMap) - , "\n jsonObj.keyboard.modifierMap.keyMapSelect: ", typeof (jsonObj.keyboard.modifierMap.keyMapSelect) - , "\n jsonObj.keyboard.modifierMap.keyMapSelect[0].modifier: ", typeof (jsonObj.keyboard.modifierMap.keyMapSelect[0].modifier) - , "\n jsonObj.keyboard.keyMapSet: ", typeof (jsonObj.keyboard.keyMapSet) - , "\n jsonObj.keyboard.keyMapSet[0].keyMap: ", typeof (jsonObj.keyboard.keyMapSet[0].keyMap) - , "\n jsonObj.keyboard.keyMapSet[0].keyMap[0].key: ", typeof (jsonObj.keyboard.keyMapSet[0].keyMap[0].key) - , "\n jsonObj.keyboard.actions : ", typeof (jsonObj.keyboard.actions) - , "\n jsonObj.keyboard.actions.action[0] : ", typeof (jsonObj.keyboard.actions.action[0]) - , "\n jsonObj.keyboard.terminators: ", typeof (jsonObj.keyboard.terminators) - , "\n jsonObj.keyboard.terminators.when: ", typeof (jsonObj.keyboard.terminators.when) - , "\n jsonObj.keyboard.actions.action[0].when: ", typeof (jsonObj.keyboard.actions.action[0].when) - ) - - console.log("-----\nplus:") - console.log("Address loke\n" - , "\n jsonObj.keyboard: ", (jsonObj.keyboard) - , "\n jsonObj.keyboard.layouts: ", (jsonObj.keyboard.layouts) - , "\n jsonObj.keyboard.layouts.layout: ", (jsonObj.keyboard.layouts.layout) - , "\n jsonObj.keyboard.modifierMap: ", (jsonObj.keyboard.modifierMap) - , "\n jsonObj.keyboard.modifierMap.keyMapSelect: ", (jsonObj.keyboard.modifierMap.keyMapSelect) - , "\n jsonObj.keyboard.modifierMap.keyMapSelect[0].modifier: ", (jsonObj.keyboard.modifierMap.keyMapSelect[0].modifier) - , "\n jsonObj.keyboard.keyMapSet: ", (jsonObj.keyboard.keyMapSet) - , "\n jsonObj.keyboard.keyMapSet[0].keyMap: ", (jsonObj.keyboard.keyMapSet[0].keyMap) - , "\n jsonObj.keyboard.keyMapSet[0].keyMap[0].key: ", (jsonObj.keyboard.keyMapSet[0].keyMap[0].key) - , "\n jsonObj.keyboard.actions : ", (jsonObj.keyboard.actions) - , "\n jsonObj.keyboard.actions.action[0] : ", (jsonObj.keyboard.actions.action[0]) - , "\n jsonObj.keyboard.actions.action[0].when: ", (jsonObj.keyboard.actions.action[0].when) - , "\n jsonObj.keyboard.terminators: ", (jsonObj.keyboard.terminators) - , "\n jsonObj.keyboard.terminators.when: ", (jsonObj.keyboard.terminators.when) - ) // TODO review condition return DataObject //return ((keys_output_all_Layers.length === nrOfStates + 5) && keys_output_all_Layers[0].length === nrOfKeys_inLayer) ? keys_output_all_Layers : null; @@ -471,6 +503,21 @@ export class KeylayoutToKmnConverter { */ //TODO need to use export const USVirtualKeyCodes here public write(data_ukelele: convert_object): boolean { + console.log("start write") + console.log("SizeOf elements: " + , "\n ArrayOf_Element_Layouts", data_ukelele.ArrayOf_Element_Layouts.length + , "\n ArrayOf_ALL_Element_ModifierMaps", data_ukelele.ArrayOf_Element_ALL_ModifierMaps.length + , "\n ArrayOf_Element_KeyAction", data_ukelele.ArrayOf_Element_KeyAction.length + , "\n ArrayOf_Element_KeyOutput", data_ukelele.ArrayOf_Element_KeyOutput.length + , "\n ArrayOf_Element_Terminators", data_ukelele.ArrayOf_Element_Terminators.length + , "\n ArrayOf_Element_ModifierMaps_ALLKeyMapSelect", data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect.length + , "\n ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[1]", data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[1].length + + , "\n ArrayOf_processed_VK_from_keylayout", data_ukelele.ArrayOf_processed_VK_from_keylayout.length + , "\n ArrayOf_processed_deadkeyables", data_ukelele.ArrayOf_processed_deadkeyables.length + , "\n ArrayOf_processed_deadkeyedChar", data_ukelele.ArrayOf_processed_deadkeyedChar.length + , "\n ArrayOf_processed_dk", data_ukelele.ArrayOf_processed_dk.length + ) // ************************************************************* // **** write stores ******************************************* @@ -497,10 +544,12 @@ export class KeylayoutToKmnConverter { // **** write rules ******************************************** // *************************************************************^ + console.log("start write 1") // if caps is used in .keylayout-file we need to add NCAPS in kmn-file let isCAPSused = false const used_Keys_count = 50 // do we need more than 50 keys?? - const modi: string[] = data_ukelele.ArrayOf_Element_ModifierMaps; + const modi: string[] = data_ukelele.ArrayOf_Element_ALL_ModifierMaps; + // const modi: string[] = data_ukelele.ArrayOf_Element_ALL_ModifierMaps; // Todo check 2darray of modifiuers const filteredModifiers: string[] = modi.filter((mod) => (String(mod) === ("caps"))) if (filteredModifiers.indexOf("caps") >= 0) isCAPSused = true @@ -509,75 +558,127 @@ export class KeylayoutToKmnConverter { // find all modifiers used per modifier combination // find resulting character from + // console.log("start write 2, ", "data_ukelele.ArrayOf_ALL_Element_ModifierMaps.length", data_ukelele.ArrayOf_Element_ALL_ModifierMaps.length) // loop through keys //for (let j = 0; j item[0] === data_ukelele.ArrayOf_processed_VK_from_keylayout[j][0]) + // loop through keyMapSelect[ii] (2,4,1,1,...) + for (let i = 0; i < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[ii].length; i++) { - // get the character from keymap-section of .keylayout-file that will be written as result in kmn-file - const resulting_character = new TextDecoder().decode(data_ukelele.ArrayOf_Element_KeyOutput[i][j]) + // get the modifier for the layer e.g. "CAPS SHIFT" - keyMapSelect[ii][i] = "CAPS SHIFT" + const label_modifier = this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[ii][i], isCAPSused) - // TODO remove j - if (resulting_character !== '') { - // e.g. [ NCAPS K_J ] > ' j ' - data += j + `+ [` + (label_modifier + ' ' + vk_label[0][1]).trim() + `] > \'` + resulting_character + '\'\n' + // get Key name e.g. K_A, K_SLASH + const VK: (string | number)[][] = data_ukelele.ArrayOf_processed_VK_from_keylayout + const vk_label = VK.filter(item => item[0] === data_ukelele.ArrayOf_processed_VK_from_keylayout[j][0]) + console.log("---", "vk_label", vk_label) + + console.log("start write 2C-", j, i) + //console.log("start write 2C-", j, i, data_ukelele.ArrayOf_Element_KeyOutput[i][j]) + // get the character from keymap-section of .keylayout-file that will be written as result in kmn-file + const resulting_character = new TextDecoder().decode(data_ukelele.ArrayOf_Element_KeyOutput[ii][j]) + + console.log("start write 2D") + // TODO remove j +"(modif:" + i + `) + if (resulting_character !== '') { + console.log("start write 2E") + // e.g. [ NCAPS K_J ] > ' j ' + data += j + "-(modif:" + ii + "-" + i + `) + [` + (label_modifier + ' ' + vk_label[0][1]).trim() + `] > \'` + resulting_character + '\'\n' + } + console.log("start write 2F") } } + console.log("start write 2G") } + console.log("start write 3") data += '\n' // ************************************************************* // **** write deadkeys ***************************************** // ************************************************************* - for (let i = 0; i < data_ukelele.ArrayOf_Element_KeyAction[0].length; i++) { - // loop through modifiers - for (let j = 0; j < data_ukelele.ArrayOf_Element_ModifierMaps.length; j++) { - - // get the modifier for the layer - const label_modifier = this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ModifierMaps[j], isCAPSused) - - // get the character from keymap-section of .keylayout-file that will be written as result in kmn-file - const resulting_character = new TextDecoder().decode(data_ukelele.ArrayOf_Element_KeyAction[j][i]) - - if (resulting_character !== "") { - const VK: (string | number)[][] = data_ukelele.ArrayOf_processed_VK_from_keylayout - const vk_label = VK.filter(item => item[0] === data_ukelele.ArrayOf_processed_VK_from_keylayout[i][0]) - for (let k = 0; k < data_ukelele.ArrayOf_processed_dk.length; k++) { - if ((resulting_character !== "") && (resulting_character === data_ukelele.ArrayOf_processed_dk[k][1])) { - data += '[' + (label_modifier + ' ' + vk_label[0][1]).trim() + '] ' + "> dk(" + this.getHexFromChar(data_ukelele.ArrayOf_processed_dk[k][1]) + ") " + '\n' + // all 109 keys with action a9 + for (let i = 0; i < data_ukelele.ArrayOf_Element_KeyAction[0].length; i++) { + // loop through keyMapSelect (8) + for (let ii = 0; ii < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect.length; ii++) { + //for (let ii = 0; ii < 8; ii++) { + // loop through modifiers + //for (let j = 0; j < data_ukelele.ArrayOf_Element_KeyAction.length; j++) { + // 8 behaviors + for (let j = 0; j < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect.length; j++) { + //console.log("start write 3A") + + // get the modifier for the layer + //const label_modifier = this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ALL_ModifierMaps[j], isCAPSused) + const label_modifier = this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ALL_ModifierMaps[j], isCAPSused) + + // get the character from keymap-section of .keylayout-file that will be written as result in kmn-file + //const resulting_character = new TextDecoder().decode(data_ukelele.ArrayOf_Element_KeyAction[j][i]) + // wrong since it attempts to convert a9 and not 4 ( the termínator id ) + const resulting_character = new TextDecoder().decode(data_ukelele.ArrayOf_Element_KeyAction[ii][i]) + + // therefore get character from ~ <- 4 <- a9 + //const realChar = this.getCharacterFromActionName(data_ukelele, data_ukelele.ArrayOf_Element_KeyAction[ii][i]) + //console.log("realChar", realChar,i,ii,j ) + // console.log("data_ukelele.ArrayOf_Element_KeyAction[ii][i],", + // data_ukelele.ArrayOf_Element_KeyAction[ii][i], + // realChar) + + if (resulting_character !== "") { + // console.log("start write 3B+3C", i, ii, j, label_modifier, "---", resulting_character) + + const VK: (string | number)[][] = data_ukelele.ArrayOf_processed_VK_from_keylayout + const vk_label = VK.filter(item => item[0] === data_ukelele.ArrayOf_processed_VK_from_keylayout[i][0]) + // console.log("VK", VK, "vk_label", vk_label) + + // console.log("start write 3D,data_ukelele.ArrayOf_processed_dk", data_ukelele.ArrayOf_processed_dk) + for (let k = 0; k < data_ukelele.ArrayOf_processed_dk.length; k++) { + /* console.log("start write 3E") + console.log("resulting_character", resulting_character, "data_ukelele.ArrayOf_processed_dk[k][1]", data_ukelele.ArrayOf_processed_dk[k][1]) + console.log("data_ukelele.ArrayOf_processed_dk is",data_ukelele.ArrayOf_processed_dk) + console.log("resulting_characte, data_ukelele.ArrayOf_processed_dk is",resulting_character, data_ukelele.ArrayOf_processed_dk[k][2])*/ + if ((resulting_character !== "") && (resulting_character === data_ukelele.ArrayOf_processed_dk[k][2])) { + data += '[' + (label_modifier + ' ' + vk_label[0][1]).trim() + '] ' + "> dk(" + this.getHexFromChar(data_ukelele.ArrayOf_processed_dk[k][1]) + ") " + '\n' + } } } } + } } + // console.log("start write 4") data += "\n" data += "match > use(deadkeys)\n\n" data += "group(deadkeys)\n" data += "\n" +console.log("data_ukelele.ArrayOf_processed_deadkeyables.length", data_ukelele.ArrayOf_processed_deadkeyables.length) +console.log("data_ukelele.String(data_ukelele.ArrayOf_processed_deadkeyables[i])).length", String(data_ukelele.ArrayOf_processed_deadkeyables[0])) +console.log("data_ukelele.String(data_ukelele.ArrayOf_processed_deadkeyables[i])).length--","\'", String(data_ukelele.ArrayOf_processed_deadkeyables[0]).trim().replace(/\,+/g, "' '"), ) + +const char ="\'" + String(data_ukelele.ArrayOf_processed_deadkeyables[0]).trim().replace(/\,+/g, "' '") +console.log("char",char) + +const char1 =char.slice(0,-1) +console.log("char1",char1) for (let i = 0; i < data_ukelele.ArrayOf_processed_deadkeyables.length; i++) { if (data_ukelele.ArrayOf_processed_deadkeyedChar[i] !== undefined) { - data += "store(dkf" + this.getHexFromChar(data_ukelele.ArrayOf_processed_dk[i][1]) + ") " + ("\'" + String(data_ukelele.ArrayOf_processed_deadkeyables[i])).replace(/\,+/g, "' '") + "'\n" - data += "store(dkt" + this.getHexFromChar(data_ukelele.ArrayOf_processed_dk[i][1]) + ") " + ("\'" + String(data_ukelele.ArrayOf_processed_deadkeyedChar[i])).replace(/\,+/g, "' '") + "'\n" + data += "store(dkf" + this.getHexFromChar(data_ukelele.ArrayOf_processed_dk[i][1]) + ") " + ("\'" + String(data_ukelele.ArrayOf_processed_deadkeyables[i])).replace(/\,+/g, "' '").slice(0,-1).trim() + "\n" + data += "store(dkt" + this.getHexFromChar(data_ukelele.ArrayOf_processed_dk[i][1]) + ") " + ("\'" + String(data_ukelele.ArrayOf_processed_deadkeyedChar[i])).replace(/\,+/g, "' '")+ "'\n" data += '\n' } } + // console.log("start write 5") /*writeFileSync("data/MyResult.kmn", data, { flag: "w" })*/ const data_encoded = new TextEncoder().encode(data) this.callbacks.fs.writeFileSync("data/MyResult.kmn", data_encoded) // not usable here since it takes UInt8array data @@ -592,6 +693,35 @@ export class KeylayoutToKmnConverter { //... helpers ............................................................................................. // TODO move outside of class? + + + public getCharacterFromActionName(data_ukelele: convert_object, ArrayOf_Element_KeyActionElement: Uint8Array): any { + //get character from ~ <- 4 <- a9 + //in: [ 97, 49 ] (a9) + // out: ~ + + //[ 97, 49 ]-> (a9) + console.log("ArrayOf_Element_KeyActionElement",ArrayOf_Element_KeyActionElement) + const ArrayOf_Element_KeyActionElement_string = new TextDecoder().decode(ArrayOf_Element_KeyActionElement) + + + if (ArrayOf_Element_KeyActionElement_string !== "") { + console.log("ArrayOf_Element_KeyActionElement_string in func", ArrayOf_Element_KeyActionElement_string) + + for (let jj = 0; jj < data_ukelele.ArrayOf_processed_dk.length; jj++) { + console.log(data_ukelele.ArrayOf_processed_dk[jj][2], "===?", ArrayOf_Element_KeyActionElement_string) + if (data_ukelele.ArrayOf_processed_dk[jj][2] === ArrayOf_Element_KeyActionElement_string) { + console.log("FOUND", data_ukelele.ArrayOf_processed_dk[jj][2]) + return data_ukelele.ArrayOf_processed_dk[jj][1] + } + + } + + return "" + } + + } + /** * @brief member function to return the unicode value of a character * @param character the value that will converted @@ -601,6 +731,7 @@ export class KeylayoutToKmnConverter { return '00' + character.charCodeAt(0).toString(16).slice(-4).toLowerCase() } + // TODO if the first in the list does not contain caps but later entries do contain caps-> no NCAPS is added(Todo check if caps/NCAPS are there after all entries are completed) /** * @brief member function to create a string of modifiers in kmn-style from the modifierMap section of .keylayout-file * @param keylayout_modifier the modifier value used in the .keylayout-file diff --git a/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts index 0491b11688f..b536e1c1ae3 100644 --- a/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts @@ -33,14 +33,16 @@ describe('KeylayoutToKmnConverter', function() { it('should throw on all elements loaded', async function () { // some keys, no deadkeys - //const inputFilename = makePathToFixture('../data/Mysample.keylayout'); + //const inputFilename = makePathToFixture('../data/Mysample.keylayout'); // all keys, some deadkeys - const inputFilename = makePathToFixture('../data/My_dk_Keyboard.keylayout'); //const inputFilename = makePathToFixture('../data/US_complete.keylayout'); + //const inputFilename = makePathToFixture('../data/Italian_copy.keylayout'); - + const inputFilename = makePathToFixture('../data/My_dk_Keyboard.keylayout'); + const outputFilename = makePathToFixture('../data/MyResult.kmn'); -// TODO check filename if correct + + // TODO check filename if correct console.log(' inputFilename', inputFilename) console.log(' outputFilename', outputFilename) From aa87e704c8cb8b260bb1f85057e390783890e203 Mon Sep 17 00:00:00 2001 From: Sabine Date: Mon, 9 Dec 2024 19:58:09 +0100 Subject: [PATCH 025/251] feat(developer): kmc-convert first version with chained actions --- developer/src/kmc-convert/data/MyResult.kmn | 246 +++- .../keylayout-to-kmn-converter.ts | 1272 ++++++++++++++++- .../test/test-keylayout-to-kmn-converter.ts | 9 +- 3 files changed, 1460 insertions(+), 67 deletions(-) diff --git a/developer/src/kmc-convert/data/MyResult.kmn b/developer/src/kmc-convert/data/MyResult.kmn index e426f096f72..55f55043a99 100644 --- a/developer/src/kmc-convert/data/MyResult.kmn +++ b/developer/src/kmc-convert/data/MyResult.kmn @@ -11,37 +11,217 @@ begin Unicode > use(main) group(main) using keys -+ [K_A] > 'a' -+ [K_B] > 'b' -+ [K_C] > 'c' -+ [K_Q] > 'q' -+ [K_Y] > 'y' -+ [K_3] > '3' -+ [K_HYPHEN] > 'ß' -+ [K_PERIOD] > '.' - -+ [K_A] > 'A' -+ [K_B] > 'B' -+ [K_C] > 'C' -+ [K_Q] > 'Q' -+ [K_Y] > 'Y' -+ [K_3] > '§' -+ [K_HYPHEN] > '?' -+ [K_PERIOD] > ':' - -+ [K_A] > ':' -+ [K_B] > '9' -+ [K_Q] > '@' -+ [K_Y] > ':' -+ [K_3] > '³' -+ [K_HYPHEN] > '\' -+ [K_PERIOD] > '·' - -+ [K_A] > 'A' -+ [K_B] > 'B' -+ [K_C] > 'C' -+ [K_Q] > 'Q' -+ [K_Y] > 'Y' -+ [K_3] > '3' -+ [K_HYPHEN] > 'ß' +Tipp: if K_? is replaced by undefined-> no enry in kmn_Key_Name=> add K_? there and it will be shown here +Tipp: keys that are marked with sction do not aoear in ukelele_Array_output->do not appear in kmn + + +0-(modif:4-0) + [SHIFT NCAPS RALT K_A] > 'A' + +1-(modif:0-0) + [NCAPS K_S] > 's' +1-(modif:1-0) + [NCAPS SHIFT K_S] > 'S' +1-(modif:2-0) + [NCAPS RALT K_S] > 'S' +1-(modif:4-0) + [SHIFT NCAPS RALT K_S] > 'S' + +2-(modif:0-0) + [NCAPS K_D] > 'd' +2-(modif:1-0) + [NCAPS SHIFT K_D] > 'D' +2-(modif:2-0) + [NCAPS RALT K_D] > 'D' + +3-(modif:0-0) + [NCAPS K_F] > 'f' +3-(modif:1-0) + [NCAPS SHIFT K_F] > 'F' +3-(modif:2-0) + [NCAPS RALT K_F] > 'F' + +4-(modif:0-0) + [NCAPS K_H] > 'h' +4-(modif:1-0) + [NCAPS SHIFT K_H] > 'H' +4-(modif:2-0) + [NCAPS RALT K_H] > 'H' + +5-(modif:0-0) + [NCAPS K_G] > 'g' +5-(modif:1-0) + [NCAPS SHIFT K_G] > 'G' +5-(modif:2-0) + [NCAPS RALT K_G] > 'G' + +6-(modif:0-0) + [NCAPS K_Z] > 'y' +6-(modif:1-0) + [NCAPS SHIFT K_Z] > 'Y' +6-(modif:2-0) + [NCAPS RALT K_Z] > 'Y' + +7-(modif:0-0) + [NCAPS K_X] > 'x' +7-(modif:1-0) + [NCAPS SHIFT K_X] > 'X' +7-(modif:2-0) + [NCAPS RALT K_X] > 'X' + +8-(modif:0-0) + [NCAPS K_C] > 'c' +8-(modif:1-0) + [NCAPS SHIFT K_C] > 'C' +8-(modif:2-0) + [NCAPS RALT K_C] > 'C' + +9-(modif:0-0) + [NCAPS K_V] > 'v' +9-(modif:1-0) + [NCAPS SHIFT K_V] > 'V' +9-(modif:2-0) + [NCAPS RALT K_V] > 'V' + +10-(modif:1-0) + [NCAPS SHIFT K_BKQUOTE] > '±' +10-(modif:2-0) + [NCAPS RALT K_BKQUOTE] > '³' + +11-(modif:0-0) + [NCAPS K_B] > 'b' +11-(modif:1-0) + [NCAPS SHIFT K_B] > 'B' +11-(modif:2-0) + [NCAPS RALT K_B] > 'B' + +12-(modif:0-0) + [NCAPS K_Q] > 'q' +12-(modif:1-0) + [NCAPS SHIFT K_Q] > 'Q' +12-(modif:2-0) + [NCAPS RALT K_Q] > '@' + +13-(modif:0-0) + [NCAPS K_W] > 'w' +13-(modif:1-0) + [NCAPS SHIFT K_W] > 'W' +13-(modif:2-0) + [NCAPS RALT K_W] > 'W' + + +15-(modif:0-0) + [NCAPS K_R] > 'r' +15-(modif:1-0) + [NCAPS SHIFT K_R] > 'R' +15-(modif:2-0) + [NCAPS RALT K_R] > 'R' + +16-(modif:0-0) + [NCAPS K_Y] > 'z' +16-(modif:1-0) + [NCAPS SHIFT K_Y] > 'Z' +16-(modif:2-0) + [NCAPS RALT K_Y] > 'Z' + +17-(modif:0-0) + [NCAPS K_T] > 't' +17-(modif:1-0) + [NCAPS SHIFT K_T] > 'T' +17-(modif:2-0) + [NCAPS RALT K_T] > 'T' + +18-(modif:0-0) + [NCAPS K_1] > '1' +18-(modif:1-0) + [NCAPS SHIFT K_1] > '!' +18-(modif:2-0) + [NCAPS RALT K_1] > '1' + +19-(modif:0-0) + [NCAPS K_2] > '2' +19-(modif:1-0) + [NCAPS SHIFT K_2] > '@' +19-(modif:2-0) + [NCAPS RALT K_2] > '2' + +20-(modif:0-0) + [NCAPS K_3] > '3' +20-(modif:1-0) + [NCAPS SHIFT K_3] > '#' +20-(modif:2-0) + [NCAPS RALT K_3] > '3' + +21-(modif:0-0) + [NCAPS K_4] > '4' +21-(modif:1-0) + [NCAPS SHIFT K_4] > '$' +21-(modif:2-0) + [NCAPS RALT K_4] > '4' + +22-(modif:0-0) + [NCAPS K_6] > '6' +22-(modif:1-0) + [NCAPS SHIFT K_6] > '^' +22-(modif:2-0) + [NCAPS RALT K_6] > '6' + +23-(modif:0-0) + [NCAPS K_5] > '5' +23-(modif:1-0) + [NCAPS SHIFT K_5] > '%' +23-(modif:2-0) + [NCAPS RALT K_5] > '5' + + +25-(modif:0-0) + [NCAPS K_9] > '9' +25-(modif:1-0) + [NCAPS SHIFT K_9] > '(' +25-(modif:2-0) + [NCAPS RALT K_9] > '9' + +26-(modif:0-0) + [NCAPS K_7] > '7' +26-(modif:1-0) + [NCAPS SHIFT K_7] > '&' +26-(modif:2-0) + [NCAPS RALT K_7] > '7' + +27-(modif:0-0) + [NCAPS K_HYPHEN] > '-' +27-(modif:1-0) + [NCAPS SHIFT K_HYPHEN] > '_' +27-(modif:2-0) + [NCAPS RALT K_HYPHEN] > '-' + +28-(modif:0-0) + [NCAPS K_8] > '8' +28-(modif:1-0) + [NCAPS SHIFT K_8] > '*' +28-(modif:2-0) + [NCAPS RALT K_8] > '8' + +29-(modif:0-0) + [NCAPS K_0] > '0' +29-(modif:1-0) + [NCAPS SHIFT K_0] > ')' +29-(modif:2-0) + [NCAPS RALT K_0] > '0' + +30-(modif:0-0) + [NCAPS K_RBRKT] > ']' +30-(modif:1-0) + [NCAPS SHIFT K_RBRKT] > '}' +30-(modif:2-0) + [NCAPS RALT K_RBRKT] > ']' + +31-(modif:2-0) + [NCAPS RALT K_O] > 'o' + + +33-(modif:0-0) + [NCAPS K_LBRKT] > 'ሴ' +33-(modif:1-0) + [NCAPS SHIFT K_LBRKT] > '{' +33-(modif:2-0) + [NCAPS RALT K_LBRKT] > '[' + + +35-(modif:0-0) + [NCAPS K_P] > 'p' +35-(modif:1-0) + [NCAPS SHIFT K_P] > 'P' +35-(modif:2-0) + [NCAPS RALT K_P] > 'P' + +36-(modif:0-0) + [NCAPS K_ENTER] > ' ' +36-(modif:1-0) + [NCAPS SHIFT K_ENTER] > ' ' +36-(modif:2-0) + [NCAPS RALT K_ENTER] > ' ' + +37-(modif:0-0) + [NCAPS K_L] > 'l' +37-(modif:1-0) + [NCAPS SHIFT K_L] > 'L' +37-(modif:2-0) + [NCAPS RALT K_L] > 'L' + +38-(modif:0-0) + [NCAPS K_J] > 'j' +38-(modif:1-0) + [NCAPS SHIFT K_J] > 'J' +38-(modif:2-0) + [NCAPS RALT K_J] > 'J' + +39-(modif:0-0) + [NCAPS K_QUOTE] > ''' +39-(modif:1-0) + [NCAPS SHIFT K_QUOTE] > '"' +39-(modif:2-0) + [NCAPS RALT K_QUOTE] > ''' + +40-(modif:0-0) + [NCAPS K_K] > 'k' +40-(modif:1-0) + [NCAPS SHIFT K_K] > 'K' +40-(modif:2-0) + [NCAPS RALT K_K] > 'K' + +41-(modif:0-0) + [NCAPS K_COLON] > ';' +41-(modif:1-0) + [NCAPS SHIFT K_COLON] > ':' +41-(modif:2-0) + [NCAPS RALT K_COLON] > ';' + +42-(modif:0-0) + [NCAPS K_BKSLASH] > '\' +42-(modif:1-0) + [NCAPS SHIFT K_BKSLASH] > '|' +42-(modif:2-0) + [NCAPS RALT K_BKSLASH] > '\' + +43-(modif:0-0) + [NCAPS K_COMMA] > ',' +43-(modif:1-0) + [NCAPS SHIFT K_COMMA] > '<' +43-(modif:2-0) + [NCAPS RALT K_COMMA] > ',' + +44-(modif:0-0) + [NCAPS K_SLASH] > '/' +44-(modif:1-0) + [NCAPS SHIFT K_SLASH] > '?' +44-(modif:2-0) + [NCAPS RALT K_SLASH] > '/' + +45-(modif:0-0) + [NCAPS K_N] > 'n' +45-(modif:1-0) + [NCAPS SHIFT K_N] > 'N' +45-(modif:2-0) + [NCAPS RALT K_N] > 'N' + +46-(modif:0-0) + [NCAPS K_M] > 'm' +46-(modif:1-0) + [NCAPS SHIFT K_M] > 'M' +46-(modif:2-0) + [NCAPS RALT K_M] > 'M' + +47-(modif:0-0) + [NCAPS K_PERIOD] > '.' +47-(modif:1-0) + [NCAPS SHIFT K_PERIOD] > '>' +47-(modif:2-0) + [NCAPS RALT K_PERIOD] > '.' + +48-(modif:0-0) + [NCAPS K_BKSLASH] > ' ' +48-(modif:1-0) + [NCAPS SHIFT K_BKSLASH] > ' ' +48-(modif:2-0) + [NCAPS RALT K_BKSLASH] > ' ' + + +[NCAPS K_BKQUOTE] > dk(005e) +[NCAPS SHIFT K_BKQUOTE] > dk(005e) +[NCAPS RALT K_BKQUOTE] > dk(005e) +[CAPS K_BKQUOTE] > dk(005e) +[SHIFT NCAPS RALT K_BKQUOTE] > dk(005e) +[NCAPS K_EQUAL] > dk(00b4) +[NCAPS SHIFT K_EQUAL] > dk(00b4) +[NCAPS RALT K_EQUAL] > dk(00b4) +[CAPS K_EQUAL] > dk(00b4) +[SHIFT NCAPS RALT K_EQUAL] > dk(00b4) +[NCAPS K_EQUAL] > dk(0060) +[NCAPS SHIFT K_EQUAL] > dk(0060) +[NCAPS RALT K_EQUAL] > dk(0060) +[CAPS K_EQUAL] > dk(0060) +[SHIFT NCAPS RALT K_EQUAL] > dk(0060) + +match > use(deadkeys) + +group(deadkeys) + +store(dkf005e) 'a' 'e' 'o' 'u' 'i' +store(dkt005e) 'â' 'ê' 'ô' 'û' 'î' + +store(dkf0060) 'a' 'e' 'o' 'u' 'i' +store(dkt0060) 'à' 'è' 'ò' 'ù' 'ì' + +store(dkf00b4) 'a' 'e' 'u' 'i' +store(dkt00b4) 'á' 'á' 'ú' 'í' diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index f07a0869ede..21f67849858 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -128,6 +128,7 @@ export interface convert_object { ArrayOf_processed_dk: string[][], // add dk-mapping ( dk1 <-> '^' ) ArrayOf_processed_deadkeyables: string[][], // add char that can be modified with dk ( a,e,i,o,u) ArrayOf_processed_deadkeyedChar: string[][], // add modified keys ( â,ê,î,ô,û) + ArrayOf_processed_RuleData: Uint8Array[][] // add modified keys ( â,ê,î,ô,û) }; @@ -155,7 +156,7 @@ export class KeylayoutToKmnConverter { } console.log(' _S2 first READ file ........................................in:', inputFilename); - const inArray: convert_object = this.read(inputFilename) + const inArray: convert_object = this.read_old(inputFilename) if (!inArray) { return null; @@ -195,6 +196,629 @@ export class KeylayoutToKmnConverter { }; + console.log("xmlFile_name", (process.cwd() + "\\data" + filename.substring(filename.lastIndexOf("\\"))).replace(" ", "")) + //const xmlFile = readFileSync(`${process.cwd()}/data/MySample.keylayout`, 'utf8') + const xmlFile = readFileSync((process.cwd() + "\\data" + filename.substring(filename.lastIndexOf("\\"))).replace(" ", ""), 'utf8'); + + // we don`t need file-read with uint8array return + /*const fullPath = (process.cwd() + "\\data" + filename.substring(filename.lastIndexOf("\\"))).replace(" ", "") + const xmlFile1 = this.callbacks.loadFile(fullPath) + console.log("xmlFile1",xmlFile1)*/ + + console.log("layouts_array read ") + const parser = new XMLParser(options); + const jsonObj = parser.parse(xmlFile); // get plain Object + boxArrays_S(jsonObj.keyboard); + + const modifierMap_ALL_KeyMapSelects: string[][] = [] // modifier for each keymapselect + const modifierMap_all_Layers: string[] = [] // array holding all MODIFIER strings e.g. "anyShift caps anyOption" -why not put modifiers into Uint8Array along with values of keys of layer + const keys_output_all_Layers: Uint8Array[][] = [] + const keys_action_all_Layers: Uint8Array[][] = [] // array holding all values with ACTION attribute (needed for finding deadkeys) + const terminators_all_Layers: Uint8Array[] = [] // array holding all DEADKEYS for each mod state â, ê, ,.... + const duplicate_layouts_array: string[] = [] // array holding the layouts e.g. ANSI or JIS // needed?? I think no + const deadkeyedChars_all_Layers: string[][] = [] // array holding all DEADKEYS for each mod state â, ê, ,.... + const kmn_Rules_AllLayers: Uint8Array[][] = [] + let dk_pairs_all_Layers: string[][] = [] // add dk-mapping ( dk1 <-> '^' ) + + + // fill arrays + // TODO call: get only ANSI + // Do I need to care or is there always ANSI which is always keyMapSet[0] + // if so code can be shortened + // ......................................................... + // LAYOUTS: get all groups like ANSI JIS, remove JIS + // ......................................................... + + // in case we need to find ANSI + for (let i = 0; i < jsonObj.keyboard.layouts.layout.length; i++) { + duplicate_layouts_array[i] = jsonObj.keyboard.layouts.layout[i]['@_mapSet'] + } + + // remove duplicates from array + const layouts_array_both: any[] = duplicate_layouts_array.filter(function (item, pos, self) { + return self.indexOf(item) == pos; + }) + + // use only ANSI - the first element + const layouts_array: any[] = layouts_array_both.filter(function (item, pos, self) { + return self.indexOf(item) == 0; + }) + + // in case there always ANSI which is always keyMapSet[0] + //const layouts_array: string[] = duplicate_layouts_array + const keyMapSet_count = 0 + + //#### end layouts ############################################################################################################################################### + + for (let j = 0; j < jsonObj.keyboard.modifierMap.keyMapSelect.length; j++) { + const modifierMap_ONE_InKeymapSelect: string[] = [] + + for (let k = 0; k < jsonObj.keyboard.modifierMap.keyMapSelect[j].modifier.length; k++) { + modifierMap_all_Layers.push(jsonObj.keyboard.modifierMap.keyMapSelect[j].modifier[k]['@_keys']) + modifierMap_ONE_InKeymapSelect.push(jsonObj.keyboard.modifierMap.keyMapSelect[j].modifier[k]['@_keys']) + } + modifierMap_ALL_KeyMapSelects.push(modifierMap_ONE_InKeymapSelect) + + // create a new array of keys_in_Layer (type Uint8tarray) + const keys_output_One_Layer: Uint8Array[] = [] + const keys_action_One_Layer: Uint8Array[] = [] + + //#### end modifierMap ############################################################################################################################################### + + // ......................................................... + // KEYMAP: get all keys for attribute "output" ( y,c,b,...) + // output type Uint8Array -> string + // ......................................................... + for (let i = 0; i < jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap[j].key.length; i++) { + if (jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap[j].key[i]['@_output'] !== "\0") { + // textencoder converts string -> bytes ( 'A' -> [ 65 ], '☺' -> [ 226, 152, 186 ]) + // textencoder is of Uint8Array(1) for A and Uint8Array(3) for ☺ + keys_output_One_Layer[i] = new TextEncoder().encode(jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap[j].key[i]['@_output']); + } + // ToDo do I need empty fields in keys_output_all_Layers, keys_action_all_Layers + // ......................................................... + // KEYMAP: get all keys for attribute "action" ( ^,a,e,i,...) + // action type Uint8Array -> string + // ......................................................... + if (jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap[j].key[i]['@_action'] !== "\0") { + keys_action_One_Layer[i] = new TextEncoder().encode(jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap[j].key[i]['@_action']); + } + } + + // ......................................................... + // create array of "action" and array of "output" + keys_output_all_Layers.push(keys_output_One_Layer) // save all @output data ( will be used for conversion, write...) + keys_action_all_Layers.push(keys_action_One_Layer) // save all @action data ( will be used for deadkeys) + //#### end output+action ############################################################################################################################################### + } + + // ......................................................... + // ACTION: create array of "deadkey" / "deadkey names" + // action type string[] -> string[][] + // ......................................................... + const dk_pairs_all_Layers_max: string[][] = [] + // here replace with function to find + // C3 state none + next Nr => deadkeys + console.log("--------------------------------") + + // loop through actions and get the value of attribute "next" (which indicates this is a deadkey) + for (let jj = 0; jj < jsonObj.keyboard.actions.action.length; jj++) { + for (let kk = 0; kk < jsonObj.keyboard.actions.action[jj].when.length; kk++) { + + if (jsonObj.keyboard.actions.action[jj].when[kk]['@_next'] !== undefined) { + const vec1d: string[] = [] + let dk_to_print + + const text_attribute_next = jsonObj.keyboard.actions.action[jj].when[kk]['@_next'] + + // loop through terminators and get output of that next state + for (let n = 0; n < jsonObj.keyboard.terminators.when.length; n++) { + if (jsonObj.keyboard.terminators.when[n]['@_state'] === text_attribute_next) + dk_to_print = jsonObj.keyboard.terminators.when[n]['@_output'] + } + + vec1d.push(text_attribute_next) + vec1d.push(dk_to_print) + vec1d.push(jsonObj.keyboard.actions.action[jj]['@_id']) // todo remove later + dk_pairs_all_Layers_max.push(vec1d) + } + } + } + dk_pairs_all_Layers = dk_pairs_all_Layers_max.filter(function (item, pos, self) { + return self.indexOf(item) == pos; + }) + console.log("dk_pairs_all_Layers", dk_pairs_all_Layers) + const dk: string[] = []; + + // ......................................................... + // ACTION: create array of "deadkeyables_all_Layers" - TODO can i use shorter function? + // deadkeyables_one type Uint8Array -> string[][] + // ......................................................... + const deadkeyables_all_Layers: string[][] = [] + const action_name = "" + // needed? we just want ANSI = the first one + for (let j = 0; j < jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap.length; j++) { + const deadkeyables_one: string[] = [] + // loop through all keys of ANSI 109 + /*for (let i = 0; i < jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap[0].key.length; i++) { + + let dk_char + // find output in action id 20 + for (let jj = 0; jj < jsonObj.keyboard.actions.action.length; jj++) { + + // find the action ID which was specified in keymap->key->action e.g. a19 + action_name = new TextDecoder().decode(keys_action_all_Layers[j][i]) + + if (action_name !== "") { + // find action id in actions->action e.g. a19 + if (jsonObj.keyboard.actions.action[jj]['@_id'] === action_name) { + + //a85 + + // 4 cases: + // C1 state none + output => + // C2 state Nr + output => + // OK C3 state none + next Nr => deadkeys see above + // C4 state Nr + next Nr => loop deadkeyables + + + const mytestVar = this.get_Terminator_Output_from_Next(jsonObj.keyboard, "a16", '@_state', '@_output') + console.log("mytestVar", mytestVar) + + if (jsonObj.keyboard.actions.action[jj].when[0]['@_state'] === "none") { + dk_char = jsonObj.keyboard.actions.action[jj].when[0]['@_output'] + console.log("++++++++++++++++++++++dk_char", j, i, jj, "action_name", action_name, + jsonObj.keyboard.actions.action[jj].when[0], "===>", dk_char, "mytestVar", mytestVar) + + // if @_next instead of @_output + // loop again + // and again... again...( -> recursive func!!) + } + } + } + } + + // fills correct entries into modifier 1-3 then false ( because of no action any more) + + //const resulting_character = new TextDecoder().decode(keys_action_all_Layers[j][i]) + const resulting_character = dk_char + + if (resulting_character !== "") + deadkeyables_one.push(resulting_character) + } +*/ + + + + + + + + for (let k = 0; k < dk_pairs_all_Layers.length; k++) { + dk.push(dk_pairs_all_Layers[k][1]) + } + + if (deadkeyables_one.length !== 0) { + deadkeyables_all_Layers.push(deadkeyables_one) + } + } + + + console.log("ction_name", action_name) + //console.log("deadkeyables_all_Layers before",deadkeyables_all_Layers) + for (let j = 0; j < deadkeyables_all_Layers.length; j++) { + // filter out dk -> plain deadkeyables_all_Layers ( a,^, e,i,´,u => a,e,i,u) + // return all that don`t find ^,´, ` + deadkeyables_all_Layers[j] = deadkeyables_all_Layers[j].filter(function (el) { + return dk.indexOf(el) < 0; + }); + + } + + //console.log("deadkeyables_all_Layers after", deadkeyables_all_Layers) + + //double not needed??? + // ......................................................... + // TERMINATOR: create array of "terminators" - TODO can i use shorter function? what element of terminators do i need + // terminators when state type Uint8Array[] + // ......................................................... + for (let i = 0; i < jsonObj.keyboard.terminators.when.length; i++) { + terminators_all_Layers[i] = jsonObj.keyboard.terminators.when[i] + } + + // ......................................................... + // TODO can i use shorter function? -> yes use terminators, filter, map or reduce + + // this addresses state+output and none+output + // but not state+next or none+next + + // loop through all dk, key-actions and find @_action + // find this value in + // in their 'when' find output for dk + // for all 'action' at keys paragraph + + + for (let j = 0; j < dk_pairs_all_Layers.length; j++) { + + //console.log("bis hier j", j) + const deadkeys_One_dk: string[] = [] + // find in action e.g. + for (let k = 0; k < keys_action_all_Layers[j].length; k++) { + + //console.log("bis hier k", k) + const action_from_keys_prargraph = new TextDecoder().decode(keys_action_all_Layers[j][k]) + if (action_from_keys_prargraph !== "") { + // find the same id (e.g. ) in the actions-paragraph + for (let l = 0; l < jsonObj.keyboard.actions.action.length; l++) { + + //console.log("bis hier l", l) + if (jsonObj.keyboard.actions.action[l]['@_id'] === action_from_keys_prargraph) { + // loop through when until dk name (e.g. dk s0) + for (let m = 0; m < jsonObj.keyboard.actions.action[l].when.length; m++) { + + // console.log("bis hier m", m) + // and get their @_output + if (jsonObj.keyboard.actions.action[l].when[m]['@_state'] === dk_pairs_all_Layers[j][0]) { + // todo push only if @output is found. if next is found: get value from terminators + //if (typeof jsonObj.keyboard.actions.action[l].when[m]['@_output'].property !== 'undefined') + deadkeys_One_dk.push(jsonObj.keyboard.actions.action[l].when[m]['@_output']) + //else + //console.log(deadkeys_One_dk, "§§§§§§ PROP UNDEFINED", j, "-", k, "-", l, "-", m, "-", dk_pairs_all_Layers[j][0], jsonObj.keyboard.actions.action[l].when[m].property) + } + } + } + } + } + } + // console.log("deadkeys_One_dk", deadkeys_One_dk) + deadkeyedChars_all_Layers.push(deadkeys_One_dk) + + //console.log("deadkeyedChars_all_Layers", deadkeyedChars_all_Layers) + } + + + const vk: (string | number)[][] = [] + + // TODO remove unneccassary elements + const DataObject: convert_object = { + name: "Ukelele-kmn", // needed?? remove + ArrayOf_Element_Layouts: layouts_array, // needed?? I think no + ArrayOf_Element_KeyOutput: keys_output_all_Layers, + ArrayOf_Element_KeyAction: keys_action_all_Layers, + ArrayOf_Element_ALL_ModifierMaps: modifierMap_all_Layers, // all 18 modifiers in 1 array + ArrayOf_Element_ModifierMaps_ALLKeyMapSelect: modifierMap_ALL_KeyMapSelects, // 18 modifiers in 8 KeyMapSelect(behaviors) + ArrayOf_Element_Terminators: terminators_all_Layers, // add terminators ( ^,´,`) + ArrayOf_processed_VK_from_keylayout: vk, + ArrayOf_processed_dk: dk_pairs_all_Layers, // add dk-mapping ( dk1 <-> '^' ) + + ArrayOf_processed_deadkeyables: deadkeyables_all_Layers, // add char that can be modified with dk ( a,e,i,o,u) + ArrayOf_processed_deadkeyedChar: deadkeyedChars_all_Layers, // add modified keys ( â,ê,î,ô,û) + ArrayOf_processed_RuleData: kmn_Rules_AllLayers + }; + + // TODO review condition + return DataObject + //return ((keys_output_all_Layers.length === nrOfStates + 5) && keys_output_all_Layers[0].length === nrOfKeys_inLayer) ? keys_output_all_Layers : null; + } + + public read_old(filename: string): convert_object { + + console.log("inputFilename read", filename) + const options = { + ignoreAttributes: false, + attributeNamePrefix: '@_' // to access the attribute + }; + + + console.log("xmlFile_name", (process.cwd() + "\\data" + filename.substring(filename.lastIndexOf("\\"))).replace(" ", "")) + //const xmlFile = readFileSync(`${process.cwd()}/data/MySample.keylayout`, 'utf8') + const xmlFile = readFileSync((process.cwd() + "\\data" + filename.substring(filename.lastIndexOf("\\"))).replace(" ", ""), 'utf8'); + + // we don`t need file-read with uint8array return + /*const fullPath = (process.cwd() + "\\data" + filename.substring(filename.lastIndexOf("\\"))).replace(" ", "") + const xmlFile1 = this.callbacks.loadFile(fullPath) + console.log("xmlFile1",xmlFile1)*/ + + + console.log("layouts_array read ") + const parser = new XMLParser(options); + const jsonObj = parser.parse(xmlFile); // get plain Object + const modifierMap_ALL_KeyMapSelects: string[][] = [] // modifier for each keymapselect + const modifierMap_all_Layers: string[] = [] // array holding all MODIFIER strings e.g. "anyShift caps anyOption" -why not put modifiers into Uint8Array along with values of keys of layer + const keys_output_all_Layers: Uint8Array[][] = [] + const keys_action_all_Layers: Uint8Array[][] = [] // array holding all values with ACTION attribute (needed for finding deadkeys) + const terminators_all_Layers: Uint8Array[] = [] // array holding all DEADKEYS for each mod state â, ê, ,.... + const duplicate_layouts_array: string[] = [] // array holding the layouts e.g. ANSI or JIS // needed?? I think no + const deadkeyedChars_all_Layers: string[][] = [] // array holding all DEADKEYS for each mod state â, ê, ,.... + const kmn_Rules_AllLayers: Uint8Array[][] = [] + let dk_pairs_all_Layers: string[][] = [] // add dk-mapping ( dk1 <-> '^' ) + + boxArrays_S(jsonObj.keyboard); + + // fill arrays + // TODO call: get only ANSI + // Do I need to care or is there always ANSI which is always keyMapSet[0] + // if so code can be shortened + // ......................................................... + // LAYOUTS: get all groups like ANSI JIS, remove JIS + // ......................................................... + + // in case we need to find ANSI + for (let i = 0; i < jsonObj.keyboard.layouts.layout.length; i++) { + duplicate_layouts_array[i] = jsonObj.keyboard.layouts.layout[i]['@_mapSet'] + } + + // remove duplicates + const layouts_array: any[] = duplicate_layouts_array.filter(function (item, pos, self) { + return self.indexOf(item) == pos; + }) + // remove JIS (if keyMap contains baseMapSet it`s JIS) + for (let i = 0; i < layouts_array.length; i++) { + if (jsonObj.keyboard.keyMapSet[i].keyMap[0]['@_baseMapSet']) + layouts_array.splice(i, 1); + } + // in case there always ANSI which is always keyMapSet[0] + //const layouts_array: string[] = duplicate_layouts_array + const keyMapSet_count = 0 + + //#### end layouts ############################################################################################################################################### + + for (let j = 0; j < jsonObj.keyboard.modifierMap.keyMapSelect.length; j++) { + const modifierMap_ONE_InKeymapSelect: string[] = [] + + for (let k = 0; k < jsonObj.keyboard.modifierMap.keyMapSelect[j].modifier.length; k++) { + modifierMap_all_Layers.push(jsonObj.keyboard.modifierMap.keyMapSelect[j].modifier[k]['@_keys']) + modifierMap_ONE_InKeymapSelect.push(jsonObj.keyboard.modifierMap.keyMapSelect[j].modifier[k]['@_keys']) + } + modifierMap_ALL_KeyMapSelects.push(modifierMap_ONE_InKeymapSelect) + + // create a new array of keys_in_Layer (type Uint8tarray) + const keys_output_One_Layer: Uint8Array[] = [] + const keys_action_One_Layer: Uint8Array[] = [] + + //#### end modifierMap ############################################################################################################################################### + + // ......................................................... + // KEYMAP: get all keys for attribute "output" ( y,c,b,...) - TODO can i use shorter function? + // output type Uint8Array -> string + // ......................................................... + for (let i = 0; i < jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap[j].key.length; i++) { + if (jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap[j].key[i]['@_output'] !== "\0") { + // textencoder converts string -> bytes ( 'A' -> [ 65 ], '☺' -> [ 226, 152, 186 ]) + // textencoder is of Uint8Array(1) for A and Uint8Array(3) for ☺ + keys_output_One_Layer[i] = new TextEncoder().encode(jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap[j].key[i]['@_output']); + } + // ToDo do I need empty fields in keys_output_all_Layers, keys_action_all_Layers + // ......................................................... + // KEYMAP: get all keys for attribute "action" ( ^,a,e,i,...) - TODO can i use shorter function? + // action type Uint8Array -> string + // ......................................................... + if (jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap[j].key[i]['@_action'] !== "\0") { + keys_action_One_Layer[i] = new TextEncoder().encode(jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap[j].key[i]['@_action']); + } + } + + // ......................................................... + // create array of "action" and array of "output" + keys_output_all_Layers.push(keys_output_One_Layer) // save all @output data ( will be used for conversion, write...) + keys_action_all_Layers.push(keys_action_One_Layer) // save all @action data ( will be used for deadkeys) + + + //#### end output+action ############################################################################################################################################### + } + + // ......................................................... + // ACTION: create array of "deadkey" / "deadkey names" - TODO can i use shorter function? + // action type string[] -> string[][] + // ......................................................... + const dk_pairs_all_Layers_max: string[][] = [] + // here replace with function to find + // C3 state none + next Nr => deadkeys + console.log("--------------------------------") + + // loop through actions and get the value of attribute "next" (which indicates this is a deadkey) + for (let jj = 0; jj < jsonObj.keyboard.actions.action.length; jj++) { + for (let kk = 0; kk < jsonObj.keyboard.actions.action[jj].when.length; kk++) { + + if (jsonObj.keyboard.actions.action[jj].when[kk]['@_next'] !== undefined) { + const vec1d: string[] = [] + let dk_to_print + + const text_attribute_next = jsonObj.keyboard.actions.action[jj].when[kk]['@_next'] + + // loop through terminators and get output of that next state + for (let n = 0; n < jsonObj.keyboard.terminators.when.length; n++) { + if (jsonObj.keyboard.terminators.when[n]['@_state'] === text_attribute_next) + dk_to_print = jsonObj.keyboard.terminators.when[n]['@_output'] + } + + vec1d.push(text_attribute_next) + vec1d.push(dk_to_print) + vec1d.push(jsonObj.keyboard.actions.action[jj]['@_id']) // todo remove later + dk_pairs_all_Layers_max.push(vec1d) + } + } + } + dk_pairs_all_Layers = dk_pairs_all_Layers_max.filter(function (item, pos, self) { + return self.indexOf(item) == pos; + }) + console.log("dk_pairs_all_Layers", dk_pairs_all_Layers) + const dk: string[] = []; + + // ......................................................... + // ACTION: create array of "deadkeyables_all_Layers" - TODO can i use shorter function? + // deadkeyables_one type Uint8Array -> string[][] + // ......................................................... + const deadkeyables_all_Layers: string[][] = [] + // needed? we just want ANSI = the first one + for (let j = 0; j < jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap.length; j++) { + const deadkeyables_one: string[] = [] + // loop through all keys of ANSI + for (let i = 0; i < jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap[0].key.length; i++) { + + let dk_char + // find output in action id + for (let jj = 0; jj < jsonObj.keyboard.actions.action.length; jj++) { + + // find the action ID which was specified in keymap->key->action e.g. a19 + const action_name = new TextDecoder().decode(keys_action_all_Layers[j][i]) + + if (action_name !== "") { + //console.log("ction_name",action_name) + // find action id in actions->action e.g. a19 + if (jsonObj.keyboard.actions.action[jj]['@_id'] === action_name) { + + //a85 + + // 4 cases: + // C1 state none + output => + // C2 state Nr + output => + // OK C3 state none + next Nr => deadkeys see above + // C4 state Nr + next Nr => loop deadkeyables + + + /*const mytestVar = this.get_Terminator_Output_from_Next(jsonObj.keyboard, "a16", '@_state', '@_output') + console.log("mytestVar", mytestVar)*/ + + if (jsonObj.keyboard.actions.action[jj].when[0]['@_state'] === "none") { + dk_char = jsonObj.keyboard.actions.action[jj].when[0]['@_output'] + /* console.log("++++++++++++++++++++++dk_char", j, i, jj, "action_name", action_name, + jsonObj.keyboard.actions.action[jj].when[0], "===>", dk_char, "mytestVar", mytestVar)*/ + + // if @_next instead of @_output + // loop again + // and again... again...( -> recursive func!!) + } + } + } + } + + // fills correct entries into modifier 1-3 then false ( because of no action any more) + + //const resulting_character = new TextDecoder().decode(keys_action_all_Layers[j][i]) + const resulting_character = dk_char + + if (resulting_character !== "") + deadkeyables_one.push(resulting_character) + } + + for (let k = 0; k < dk_pairs_all_Layers.length; k++) { + dk.push(dk_pairs_all_Layers[k][1]) + } + + if (deadkeyables_one.length !== 0) { + deadkeyables_all_Layers.push(deadkeyables_one) + } + } + //console.log("deadkeyables_all_Layers before",deadkeyables_all_Layers) + for (let j = 0; j < deadkeyables_all_Layers.length; j++) { + // filter out dk -> plain deadkeyables_all_Layers ( a,^, e,i,´,u => a,e,i,u) + // return all that don`t find ^,´, ` + deadkeyables_all_Layers[j] = deadkeyables_all_Layers[j].filter(function (el) { + return dk.indexOf(el) < 0; + }); + + } + + //console.log("deadkeyables_all_Layers after", deadkeyables_all_Layers) + + //double??? + // ......................................................... + // TERMINATOR: create array of "terminators" - TODO can i use shorter function? what element of terminators do i need + // terminators when state type Uint8Array[] + // ......................................................... + for (let i = 0; i < jsonObj.keyboard.terminators.when.length; i++) { + terminators_all_Layers[i] = jsonObj.keyboard.terminators.when[i] + } + + // ......................................................... + // TODO can i use shorter function? -> yes use terminators, filter, map or reduce + + // this addresses state+output and none+output + // but not state+next or none+next + + // loop through all dk, key-actions and find @_action + // find this value in + // in their 'when' find output for dk + // for all 'action' at keys paragraph + + + for (let j = 0; j < dk_pairs_all_Layers.length; j++) { + + //console.log("bis hier j", j) + const deadkeys_One_dk: string[] = [] + // find in action e.g. + for (let k = 0; k < keys_action_all_Layers[j].length; k++) { + + //console.log("bis hier k", k) + const action_from_keys_prargraph = new TextDecoder().decode(keys_action_all_Layers[j][k]) + if (action_from_keys_prargraph !== "") { + // find the same id (e.g. ) in the actions-paragraph + for (let l = 0; l < jsonObj.keyboard.actions.action.length; l++) { + + //console.log("bis hier l", l) + if (jsonObj.keyboard.actions.action[l]['@_id'] === action_from_keys_prargraph) { + // loop through when until dk name (e.g. dk s0) + for (let m = 0; m < jsonObj.keyboard.actions.action[l].when.length; m++) { + + // console.log("bis hier m", m) + // and get their @_output + if (jsonObj.keyboard.actions.action[l].when[m]['@_state'] === dk_pairs_all_Layers[j][0]) { + // todo push only if @output is found. if next is found: get value from terminators + //if (typeof jsonObj.keyboard.actions.action[l].when[m]['@_output'].property !== 'undefined') + deadkeys_One_dk.push(jsonObj.keyboard.actions.action[l].when[m]['@_output']) + //else + //console.log(deadkeys_One_dk, "§§§§§§ PROP UNDEFINED", j, "-", k, "-", l, "-", m, "-", dk_pairs_all_Layers[j][0], jsonObj.keyboard.actions.action[l].when[m].property) + } + } + } + } + } + } + // console.log("deadkeys_One_dk", deadkeys_One_dk) + deadkeyedChars_all_Layers.push(deadkeys_One_dk) + + //console.log("deadkeyedChars_all_Layers", deadkeyedChars_all_Layers) + } + + + const vk: (string | number)[][] = [] + + // TODO remove unneccassary elements + const DataObject: convert_object = { + name: "Ukelele-kmn", // needed?? remove + ArrayOf_Element_Layouts: layouts_array, // needed?? I think no + ArrayOf_Element_KeyOutput: keys_output_all_Layers, + ArrayOf_Element_KeyAction: keys_action_all_Layers, + ArrayOf_Element_ALL_ModifierMaps: modifierMap_all_Layers, // all 18 modifiers in 1 array + ArrayOf_Element_ModifierMaps_ALLKeyMapSelect: modifierMap_ALL_KeyMapSelects, // 18 modifiers in 8 KeyMapSelect(behaviors) + ArrayOf_Element_Terminators: terminators_all_Layers, // add terminators ( ^,´,`) + ArrayOf_processed_VK_from_keylayout: vk, + ArrayOf_processed_dk: dk_pairs_all_Layers, // add dk-mapping ( dk1 <-> '^' ) + + ArrayOf_processed_deadkeyables: deadkeyables_all_Layers, // add char that can be modified with dk ( a,e,i,o,u) + ArrayOf_processed_deadkeyedChar: deadkeyedChars_all_Layers, // add modified keys ( â,ê,î,ô,û) + ArrayOf_processed_RuleData: kmn_Rules_AllLayers + }; + + const filled_Data = this.collect_Data_From_File(DataObject, jsonObj) + + // TODO review condition + return filled_Data + return DataObject + //return ((keys_output_all_Layers.length === nrOfStates + 5) && keys_output_all_Layers[0].length === nrOfKeys_inLayer) ? keys_output_all_Layers : null; + } + + + public read_backup_runableMinimalVersion(filename: string): convert_object { + + console.log("inputFilename read", filename) + const options = { + ignoreAttributes: false, + attributeNamePrefix: '@_' // to access the attribute + }; + + console.log("xmlFile_name", (process.cwd() + "\\data" + filename.substring(filename.lastIndexOf("\\"))).replace(" ", "")) //const xmlFile = readFileSync(`${process.cwd()}/data/MySample.keylayout`, 'utf8') const xmlFile = readFileSync((process.cwd() + "\\data" + filename.substring(filename.lastIndexOf("\\"))).replace(" ", ""), 'utf8'); @@ -215,7 +839,7 @@ export class KeylayoutToKmnConverter { const terminators_all_Layers: Uint8Array[] = [] // array holding all DEADKEYS for each mod state â, ê, ,.... const duplicate_layouts_array: string[] = [] // array holding the layouts e.g. ANSI or JIS // needed?? I think no const deadkeyedChars_all_Layers: string[][] = [] // array holding all DEADKEYS for each mod state â, ê, ,.... - + const kmn_Rules_AllLayers: Uint8Array[][] = [] let dk_pairs_all_Layers: string[][] = [] // add dk-mapping ( dk1 <-> '^' ) boxArrays_S(jsonObj.keyboard); @@ -297,7 +921,7 @@ export class KeylayoutToKmnConverter { // action type string[] -> string[][] // ......................................................... const dk_pairs_all_Layers_max: string[][] = [] - + // here replace with function to find // C3 state none + next Nr => deadkeys console.log("--------------------------------") @@ -327,7 +951,7 @@ export class KeylayoutToKmnConverter { dk_pairs_all_Layers = dk_pairs_all_Layers_max.filter(function (item, pos, self) { return self.indexOf(item) == pos; }) - + console.log("dk_pairs_all_Layers", dk_pairs_all_Layers) const dk: string[] = []; // ......................................................... @@ -341,15 +965,15 @@ export class KeylayoutToKmnConverter { // loop through all keys of ANSI for (let i = 0; i < jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap[0].key.length; i++) { - // find output in action id let dk_char + // find output in action id for (let jj = 0; jj < jsonObj.keyboard.actions.action.length; jj++) { // find the action ID which was specified in keymap->key->action e.g. a19 const action_name = new TextDecoder().decode(keys_action_all_Layers[j][i]) if (action_name !== "") { - + //console.log("ction_name",action_name) // find action id in actions->action e.g. a19 if (jsonObj.keyboard.actions.action[jj]['@_id'] === action_name) { @@ -357,18 +981,28 @@ export class KeylayoutToKmnConverter { // 4 cases: // C1 state none + output => - // C2 state Nr + output => + // C2 state Nr + output => // OK C3 state none + next Nr => deadkeys see above // C4 state Nr + next Nr => loop deadkeyables + + const mytestVar = this.get_Terminator_Output_from_Next(jsonObj.keyboard, "a16", '@_state', '@_output') + console.log("mytestVar", mytestVar) + if (jsonObj.keyboard.actions.action[jj].when[0]['@_state'] === "none") { dk_char = jsonObj.keyboard.actions.action[jj].when[0]['@_output'] + console.log("++++++++++++++++++++++dk_char", j, i, jj, "action_name", action_name, + jsonObj.keyboard.actions.action[jj].when[0], "===>", dk_char, "mytestVar", mytestVar) + + // if @_next instead of @_output + // loop again + // and again... again...( -> recursive func!!) } } } } - + // fills correct entries into modifier 1-3 then false ( because of no action any more) //const resulting_character = new TextDecoder().decode(keys_action_all_Layers[j][i]) const resulting_character = dk_char @@ -385,15 +1019,19 @@ export class KeylayoutToKmnConverter { deadkeyables_all_Layers.push(deadkeyables_one) } } - + //console.log("deadkeyables_all_Layers before",deadkeyables_all_Layers) for (let j = 0; j < deadkeyables_all_Layers.length; j++) { // filter out dk -> plain deadkeyables_all_Layers ( a,^, e,i,´,u => a,e,i,u) // return all that don`t find ^,´, ` deadkeyables_all_Layers[j] = deadkeyables_all_Layers[j].filter(function (el) { return dk.indexOf(el) < 0; }); + } + console.log("deadkeyables_all_Layers after", deadkeyables_all_Layers) + + //double??? // ......................................................... // TERMINATOR: create array of "terminators" - TODO can i use shorter function? what element of terminators do i need // terminators when state type Uint8Array[] @@ -446,7 +1084,10 @@ export class KeylayoutToKmnConverter { } } } + // console.log("deadkeys_One_dk", deadkeys_One_dk) deadkeyedChars_all_Layers.push(deadkeys_One_dk) + + console.log("deadkeyedChars_all_Layers", deadkeyedChars_all_Layers) } @@ -465,7 +1106,8 @@ export class KeylayoutToKmnConverter { ArrayOf_processed_dk: dk_pairs_all_Layers, // add dk-mapping ( dk1 <-> '^' ) ArrayOf_processed_deadkeyables: deadkeyables_all_Layers, // add char that can be modified with dk ( a,e,i,o,u) - ArrayOf_processed_deadkeyedChar: deadkeyedChars_all_Layers // add modified keys ( â,ê,î,ô,û) + ArrayOf_processed_deadkeyedChar: deadkeyedChars_all_Layers, // add modified keys ( â,ê,î,ô,û) + ArrayOf_processed_RuleData: kmn_Rules_AllLayers }; // TODO review condition @@ -558,7 +1200,7 @@ export class KeylayoutToKmnConverter { // find all modifiers used per modifier combination // find resulting character from - // console.log("start write 2, ", "data_ukelele.ArrayOf_ALL_Element_ModifierMaps.length", data_ukelele.ArrayOf_Element_ALL_ModifierMaps.length) + // console.log("start write 2, ", "data_ukelele.ArrayOf_ALL_Element_ModifierMaps.length", data_ukelele.ArrayOf_Element_ALL_ModifierMaps.length) // loop through keys //for (let j = 0; j item[0] === data_ukelele.ArrayOf_processed_VK_from_keylayout[j][0]) - console.log("---", "vk_label", vk_label) + //console.log("---", "vk_label", vk_label) - console.log("start write 2C-", j, i) + //console.log("start write 2C-", j, i) //console.log("start write 2C-", j, i, data_ukelele.ArrayOf_Element_KeyOutput[i][j]) // get the character from keymap-section of .keylayout-file that will be written as result in kmn-file const resulting_character = new TextDecoder().decode(data_ukelele.ArrayOf_Element_KeyOutput[ii][j]) - console.log("start write 2D") + //console.log("start write 2D") // TODO remove j +"(modif:" + i + `) if (resulting_character !== '') { - console.log("start write 2E") + //console.log("start write 2E") // e.g. [ NCAPS K_J ] > ' j ' data += j + "-(modif:" + ii + "-" + i + `) + [` + (label_modifier + ' ' + vk_label[0][1]).trim() + `] > \'` + resulting_character + '\'\n' } - console.log("start write 2F") + //console.log("start write 2F") } } - console.log("start write 2G") + //console.log("start write 2G") } - console.log("start write 3") + //console.log("start write 3") data += '\n' // ************************************************************* @@ -608,8 +1250,8 @@ export class KeylayoutToKmnConverter { // all 109 keys with action a9 for (let i = 0; i < data_ukelele.ArrayOf_Element_KeyAction[0].length; i++) { // loop through keyMapSelect (8) - for (let ii = 0; ii < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect.length; ii++) { - //for (let ii = 0; ii < 8; ii++) { + for (let ii = 0; ii < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect.length; ii++) { + //for (let ii = 0; ii < 8; ii++) { // loop through modifiers //for (let j = 0; j < data_ukelele.ArrayOf_Element_KeyAction.length; j++) { // 8 behaviors @@ -626,8 +1268,8 @@ export class KeylayoutToKmnConverter { const resulting_character = new TextDecoder().decode(data_ukelele.ArrayOf_Element_KeyAction[ii][i]) // therefore get character from ~ <- 4 <- a9 - //const realChar = this.getCharacterFromActionName(data_ukelele, data_ukelele.ArrayOf_Element_KeyAction[ii][i]) - //console.log("realChar", realChar,i,ii,j ) + //const realChar = this.getCharacterFromActionName(data_ukelele, data_ukelele.ArrayOf_Element_KeyAction[ii][i]) + //console.log("realChar", realChar,i,ii,j ) // console.log("data_ukelele.ArrayOf_Element_KeyAction[ii][i],", // data_ukelele.ArrayOf_Element_KeyAction[ii][i], // realChar) @@ -660,20 +1302,20 @@ export class KeylayoutToKmnConverter { data += "match > use(deadkeys)\n\n" data += "group(deadkeys)\n" data += "\n" -console.log("data_ukelele.ArrayOf_processed_deadkeyables.length", data_ukelele.ArrayOf_processed_deadkeyables.length) -console.log("data_ukelele.String(data_ukelele.ArrayOf_processed_deadkeyables[i])).length", String(data_ukelele.ArrayOf_processed_deadkeyables[0])) -console.log("data_ukelele.String(data_ukelele.ArrayOf_processed_deadkeyables[i])).length--","\'", String(data_ukelele.ArrayOf_processed_deadkeyables[0]).trim().replace(/\,+/g, "' '"), ) + //console.log("data_ukelele.ArrayOf_processed_deadkeyables.length", data_ukelele.ArrayOf_processed_deadkeyables.length) + // console.log("data_ukelele.String(data_ukelele.ArrayOf_processed_deadkeyables[i])).length", String(data_ukelele.ArrayOf_processed_deadkeyables[0])) + //console.log("data_ukelele.String(data_ukelele.ArrayOf_processed_deadkeyables[i])).length--", "\'", String(data_ukelele.ArrayOf_processed_deadkeyables[0]).trim().replace(/\,+/g, "' '"),) -const char ="\'" + String(data_ukelele.ArrayOf_processed_deadkeyables[0]).trim().replace(/\,+/g, "' '") -console.log("char",char) + //const char = "\'" + String(data_ukelele.ArrayOf_processed_deadkeyables[0]).trim().replace(/\,+/g, "' '") + //console.log("char", char) -const char1 =char.slice(0,-1) -console.log("char1",char1) + //const char1 = char.slice(0, -1) + //console.log("char1", char1) for (let i = 0; i < data_ukelele.ArrayOf_processed_deadkeyables.length; i++) { if (data_ukelele.ArrayOf_processed_deadkeyedChar[i] !== undefined) { - data += "store(dkf" + this.getHexFromChar(data_ukelele.ArrayOf_processed_dk[i][1]) + ") " + ("\'" + String(data_ukelele.ArrayOf_processed_deadkeyables[i])).replace(/\,+/g, "' '").slice(0,-1).trim() + "\n" - data += "store(dkt" + this.getHexFromChar(data_ukelele.ArrayOf_processed_dk[i][1]) + ") " + ("\'" + String(data_ukelele.ArrayOf_processed_deadkeyedChar[i])).replace(/\,+/g, "' '")+ "'\n" + data += "store(dkf" + this.getHexFromChar(data_ukelele.ArrayOf_processed_dk[i][1]) + ") " + ("\'" + String(data_ukelele.ArrayOf_processed_deadkeyables[i])).replace(/\,+/g, "' '").slice(0, -1).trim() + "\n" + data += "store(dkt" + this.getHexFromChar(data_ukelele.ArrayOf_processed_dk[i][1]) + ") " + ("\'" + String(data_ukelele.ArrayOf_processed_deadkeyedChar[i])).replace(/\,+/g, "' '") + "'\n" data += '\n' } } @@ -694,6 +1336,572 @@ console.log("char1",char1) // TODO move outside of class? + public collect_Data_From_File(data_ukelele: convert_object, jsonObj: any): convert_object { + + //Testarray + const UintArray: Uint8Array[] = []; + const stringArray: Uint8Array[][] = []; + + UintArray.push(new TextEncoder().encode("K_A")) + UintArray.push(new TextEncoder().encode("K_B")) + UintArray.push(new TextEncoder().encode(">")) + UintArray.push(new TextEncoder().encode("ሴ")) + stringArray.push(UintArray) + console.log("UintArray", UintArray[0], UintArray[3]) + console.log("stringArray", stringArray) + // end + + + console.log("json", jsonObj.keyboard.terminators) + console.log("jsonObj.keyboard.keyMapSet.le", jsonObj.keyboard.keyMapSet[0].keyMap.length) + let action_id + for (let i = 0; i < jsonObj.keyboard.keyMapSet[0].keyMap.length; i++) { + let output_count = 0 + let action_count = 0 + let all_count = 0 + + // loop keys + for (let j = 0; j < jsonObj.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { + // ...................................................................................................... + // case C0: code + output ............................................................................... + // ...................................................................................................... + + all_count++ + if (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] !== undefined) { + + // ...................................................................................................... + // case C0: output .............................................................................DONE .... + // a key is mapped to a character ( code-> output) ...................................................... + // ...............e. g. ...................................................... + // ...................................................................................................... + // in keys at top for code 1 (K_S) take output ("s") [italian copy] + // get modifiers [modifer of Keymap index 0] + // write [modifer of Keymap index 0] + K_S > s + + output_count++ + if (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] !== "") + console.log("### Key Nr", jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], + "[ + C0 modifiers]", "+", "K_?", " (key Code", jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], ") > ", + jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output']) + } + + + // ...................................................................................................... + // actions ............................................................................... + // ...................................................................................................... + + else if (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] !== undefined) { + action_count++ + /* console.log("_action is ",i,j, jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'], + "--",action_count, "of ", action_count+output_count, all_count)*/ + + // ...................................................................................................... + // case C1: action + state none + output .......................................................DONE .. + // a key is mapped to an action and then to an output ................................................... + // code->action->action(none)->action(output) .......................................................... + // ...............e. g. a + action_id = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] + const resultC1 = this.lookup_6_ActionNone__To__ActionOutput(jsonObj, action_id) + + if (resultC1 !== undefined) + console.log("### Key Nr", jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], + "[ + C1 modifiers]", "+", "K_?", " (keycode", jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], ") > ", resultC1) + //Todo write into array + + // ...................................................................................................... + // case C2: action + state Nr + output .........................................................DONE .... + // a key is mapped to an action, then to an output+state ................................................ + // code->action->action(none) + state->action(output) ................................................... + // ...............e. g. .................................................... + // ...................................................................................................... + // in keys at top for code 0 (K_A) take actions id (a9) [italian copy] + // get modifiers [modifer of Keymap index 0] + // loop all actions and look for next="2" (state="2" => next="2") (=>a8) + // get action id of this row (id = a8) + // look for a8 in keymap-keys action at top + // take code = 25 = K_9 + // get modifiers [modifer of Keymap index 3] (=anyOption) + // [modifer of Keymap index 3] + K_A + K_9 > à + // write anyOption + K_A + K_9 > à + + + let outputval + let nextvalArray: string[] = [] + // a16 + action_id = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] + //°° id a16 ->id nr 8 + const indexInActions = this.lookup_10_ActionId__To__ActioIndex(jsonObj, action_id) + + + + // loop through all actionh/when find state and get action id + // + // + // + // + for (let j = 0; j < jsonObj.keyboard.actions.action[indexInActions].when.length; j++) { + // °°get state 3 <- + const stateVal = jsonObj.keyboard.actions.action[indexInActions].when[j]['@_state'] // a09 ->3 + + if (stateVal !== undefined) { + // get output  needed here?? CAse none-next (C3) + outputval = jsonObj.keyboard.actions.action[indexInActions].when[j]['@_output'] + // get all that result in state 3 + nextvalArray = this.lookup_5_ActionState__To__ActionNext(jsonObj, stateVal) + } + + for (let k = 0; k < nextvalArray.length; k++) { + console.log(" ### Key Nr", jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], + "[ + C2 modifiers]", "+", + nextvalArray[k] + + "-K_? +", + jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], + " > ", + outputval, "-", nextvalArray) + } + } + + + // ...................................................................................................... + // case C3: action + state Nr + Next .................................................................... + // ...............e. g. ..................................................... + // a key is mapped to an action and then to a terminator ................................................ + // code->action->action(state)->action(next)->terminator(output) ....................................... + // ...................................................................................................... + // in keys at top for code 10 (=K_BACKQUOTE) take actions id (a57) [German standard copy] + // code 10 = K_BACKQUOTE (or another key 93) + // get modifiers [modifer of Keymap index 0] + // goto action id a57 + // goto when 14 + + // loop through all actions to find next="14" ( might find several) + // get actionsId and output (a80 ) + // get modifiers [modifer of Keymap index 3] + // look at top for a80 => code 40 (= K_K) ( this is how we could get to state 14) + // take 20 and look for state = 20 in terminators ( because of "next") + // get output ("̭") + // [modifer of Keymap index 0] + a57 + +[modifer of Keymap index 3] state14 -> next 20 + // <=>[modifer of Keymap index 0] + K_BACKQUOTE +[modifer of Keymap index 3] K_K -> "̭" + + // get a57 + action_id = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] + const actionIdIndex = this.lookup_10_ActionId__To__ActioIndex(jsonObj, action_id) + + //loop through action a57 and get all states e.g state 14 +// what if mor linese xisted?? + let thatstate + let thatnext + let the_ContextKeyNr + for (let l = 0; l < jsonObj.keyboard.actions.action[actionIdIndex].when.length; l++) { + + if ((jsonObj.keyboard.actions.action[actionIdIndex].when[l]['@_state'] !== "none") && (jsonObj.keyboard.actions.action[actionIdIndex].when[l]['@_next'] !== undefined)) { + thatstate = jsonObj.keyboard.actions.action[actionIdIndex].when[l]['@_state'] + thatnext = jsonObj.keyboard.actions.action[actionIdIndex].when[l]['@_next'] + + let theContextID + for (let ll = 0; ll < jsonObj.keyboard.actions.action.length; ll++) { + for (let mm = 0; mm < jsonObj.keyboard.actions.action[ll].when.length; mm++) { + if ((jsonObj.keyboard.actions.action[ll].when[mm]['@_next'] === thatstate)) { + theContextID = jsonObj.keyboard.actions.action[ll]['@_id'] + + } + } + } + the_ContextKeyNr = this.lookup_11_KeyMapAction__To__KeyMapCode(jsonObj, theContextID) + } + } + const resultC3 = this.lookup_9_TerminatorState__To__TerminatorOutput_str(jsonObj, thatnext) + + if (the_ContextKeyNr !== undefined) + console.log(" ### Key Nr", jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], + "[ + C3 modifiers]", + "+ K_?-", "(key Code", jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], + ") +", "K_?-", "(keyCode", the_ContextKeyNr, ")", + " > ", resultC3, + ) + + // ...................................................................................................... + // case C4: action + state none + Next ............................................................DONE . + // ...............e. g. ................................................... + // a key is mapped to an action and then to a terminator ................................................ + // code->action->action(none)->action(next)->terminator(output) ........................................ + // ...................................................................................................... + // in keys for code 32 (K_U) at top find actions id a16 [italian copy] + // get modifiers [modifer of Keymap index 3] + // in actions a16 find state "none" and get next (=4) + // in terminators find the state (=4) + // take output ("¨") + // write [modifer of Keymap index 3] + K_U -> "¨" + + action_id = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] + + const next_id = this.lookup_3_ActionNone__To__ActionNext(jsonObj, action_id) + const resultC4 = this.lookup_9_TerminatorState__To__TerminatorOutput_str(jsonObj, next_id) + + if (resultC4 !== "") + console.log("### Key Nr", jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], + "[ + C4 modifiers]", "+ K_?-", "(key Code", jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], ") > ", resultC4, "[", action_id, next_id, "]") + } + else + console.log("ERROR : some entries are not available") + } + } + return data_ukelele + } + + /*public lookup_1_KeymapCode__To__keyMapAction(data: any, search: string): string { + for (let kk = 0; kk < data.keyboard.keyMapSet[0].keyMap.length; kk++) { + for (let jj = 0; jj < data.keyboard.keyMapSet[0].keyMap[kk].key.length; jj++) { + if (data.keyboard.keyMapSet[0].keyMap[kk].key ) + } + } + }*/ + public lookup_2_KeyMapAction__To__ActionAction() { } + public lookup_3_ActionNone__To__ActionNext(data: any, search: string): string { + for (let jj = 0; jj < data.keyboard.actions.action.length; jj++) { + if (data.keyboard.actions.action[jj]['@_id'] === search) { + for (let kk = 0; kk < data.keyboard.actions.action[jj].when.length; kk++) { + if (data.keyboard.actions.action[jj].when[kk]['@_state'] === "none") + return data.keyboard.actions.action[jj].when[kk]['@_next'] + } + } + } + return "" + } + public lookup_4_ActionNext__To__ActionState() { } + public lookup_5_ActionState__To__ActionNext(data: any, action_idName: string): string[] { + const returnarray: string[] = [] + // e.g. action_idName = 3 + if (action_idName !== "none") { + // loop all action/when + for (let k = 0; k < data.keyboard.actions.action.length; k++) { + for (let j = 0; j < data.keyboard.actions.action[k].when.length; j++) { + // find attribute next === 3 + if (data.keyboard.actions.action[k].when[j]['@_next'] === action_idName) { + returnarray.push(data.keyboard.actions.action[k]['@_id']) + } + } + } + } + return returnarray + } + public lookup_6_ActionNone__To__ActionOutput(data: any, search: any): any { + // a16-> id ==a16 ->4 + //todo what if douplicate value?? + let OutputValue = "" + for (let jj = 0; jj < data.keyboard.actions.action.length; jj++) { + if (data.keyboard.actions.action[jj]['@_id'] === search) { + for (let kk = 0; kk < data.keyboard.actions.action[jj].when.length; kk++) { + if (data.keyboard.actions.action[jj].when[kk]['@_state'] === "none") { + OutputValue = data.keyboard.actions.action[jj].when[kk]['@_output'] + } + } + } + } + return OutputValue + } + public lookup_7_ActionState__To__ActionOutput() { } + public lookup_8_ActionNext__To__TerminatorState() { + } + + public lookup_9_TerminatorState__To__TerminatorOutput_ui8(data: any, search: string): Uint8Array { + for (let jj = 0; jj < data.keyboard.terminators.when.length; jj++) { + if (data.keyboard.terminators.when[jj]['@_state'] === search) { + return new TextEncoder().encode(data.keyboard.terminators.when[jj]['@_output']); + } + } + return new TextEncoder().encode("") + } + public lookup_9_TerminatorState__To__TerminatorOutput_str(data: any, search: string): String { + let OutputValue = "" + for (let jj = 0; jj < data.keyboard.terminators.when.length; jj++) { + if (data.keyboard.terminators.when[jj]['@_state'] === search) { + OutputValue = data.keyboard.terminators.when[jj]['@_output'] + } + } + return OutputValue + } + public lookup_10_ActionId__To__ActioIndex(data: any, search: string): number { + for (let k = 0; k < data.keyboard.actions.action.length; k++) { + if (data.keyboard.actions.action[k]['@_id'] === search) + return k + } + return 0 + + } + + + public lookup_11_KeyMapAction__To__KeyMapCode(data: any, search: string): number { + for (let kk = 0; kk < data.keyboard.keyMapSet[0].keyMap.length; kk++) { + for (let jj = 0; jj < data.keyboard.keyMapSet[0].keyMap[kk].key.length; jj++) { + + // console.log( "A action_id-search",kk,jj, search, data.keyboard.keyMapSet[0].keyMap[kk].key[jj]['@_action']) + if (data.keyboard.keyMapSet[0].keyMap[kk].key[jj]['@_action'] === search) { + + //console.log( "FOUND action_id-search",kk,jj, search, data.keyboard.keyMapSet[0].keyMap[kk].key[jj]['@_action'] ) + return data.keyboard.keyMapSet[0].keyMap[kk].key[jj]['@_code'] + } + } + } + return 999 + } + // get all entries that result in state 3 + public lookup_12_ActionNext__from__ActionState(data: any, search: string): string { + + // loop all action + for (let jj = 0; jj < data.keyboard.actions.action.length; jj++) { + // loop all when + for (let kk = 0; kk < data.keyboard.actions.action[jj].when.length; kk++) { + // if next === a´search + if (data.keyboard.actions.action[jj].when[kk]['@_next'] === search) { + // return actionIDName + return data.keyboard.actions.action[jj]['@_id'] + } + } + } + + return "" + } + + + //___________________ + /* ?? check:*/ public get_Terminator_Output_from_Next(data: any, valSearch: any, at_In: any, at_Out: any): any { + const returnvalue = "XX" + // take jsonObj(data), valSearch, valReturn, at_In, at_Out // valSearch =18 from next=18 + // return valReturn + // do: + // loop (i) through jsonObj-terminator until VAlSearch is found in when-@state + // get i + // return jsonObj-termin[i][@_out] + + // a16: state = "none -> next =3" + + //console.log(" in:", valSearch, "->") + //const found_outputValue = this.get_Next_Output_from_None_and_id(data, valSearch, "none", at_In, at_Out) + + // console.log(" in:", valSearch, "->", found_outputValue) + //const returnvalue = this.get_Terminator_Output_from_Next(data, found_outputValue, at_In, at_Out) + + //console.log("§§§§§§§§§§§ in:", valSearch, "->", found_outputValue, "->", returnvalue) + return returnvalue + } + /* public get_all_next_from_state(data: any, action_idName: string): string[] { + const returnarray: string[] = [] + // e.g. action_idName = 3 + if (action_idName !== "none") { + // loop all action/when + for (let k = 0; k < data.keyboard.actions.action.length; k++) { + for (let j = 0; j < data.keyboard.actions.action[k].when.length; j++) { + // find attribute next === 3 + if (data.keyboard.actions.action[k].when[j]['@_next'] === action_idName) { + returnarray.push(data.keyboard.actions.action[k]['@_id']) + } + } + } + } + return returnarray + } */ + /* public get_Output_Output_from_None_and_id(data: any, actionId: any, valSearch: any): any { + // a16-> id ==a16 ->4 + //todo what if douplicate value?? + let OutputValue = "" + for (let jj = 0; jj < data.keyboard.actions.action.length; jj++) { + if (data.keyboard.actions.action[jj]['@_id'] === actionId) { + for (let kk = 0; kk < data.keyboard.actions.action[jj].when.length; kk++) { + if (data.keyboard.actions.action[jj].when[kk]['@_state'] === "none") { + OutputValue = data.keyboard.actions.action[jj].when[kk]['@_output'] + } + } + } + } + return OutputValue + } */ + /* public get_Output_Next_from_None_and_id(data: any, actionId: any, valSearch: any): any { + // a16-> id ==a16 ->4 + //todo what if douplicate value?? + let OutputValue = "" + + for (let jj = 0; jj < data.keyboard.actions.action.length; jj++) { + if (data.keyboard.actions.action[jj]['@_id'] === actionId) { + for (let kk = 0; kk < data.keyboard.actions.action[jj].when.length; kk++) { + if (data.keyboard.actions.action[jj].when[kk]['@_state'] === "none") + OutputValue = data.keyboard.actions.action[jj].when[kk]['@_next'] + } + } + } + return OutputValue + }*/ + /* public loop_Action_ToFind_index_from_ID_name(data: any, action_idName: string): number { + + for (let k = 0; k < data.keyboard.actions.action.length; k++) { + if (data.keyboard.actions.action[k]['@_id'] === action_idName) + + // console.log("data.actions.action[0]['@_id'] 2",data.keyboard.actions.action[0]['@_id'], k) + return k + } + return 0 + }*/ + /*public get_Next_Output_from_None(data: any, valSearch: any, at_In: any, at_Out: any): any { + + valSearch = "none" + + for (let k = 0; k < data.actions.action.length; k++) { + for (let j = 0; j < data.actions.action[k].when.length; j++) { + if ((data.actions.action[k].when[j]['@_state'] === valSearch && data.actions.action[k].when[j]['@_next'] !== "undefined")) { + const nextValue = data.actions.action[k].when[j]['@_next'] + // console.log("found pair: ", k, j, data.actions.action[k]['@_id'], data.actions.action[k].when[j]['@_state'], "nextValue",nextValue) + return nextValue + } + } + } + return "" + }*/ + /*public get_Next_Output_from_None_and_id(data: any, actionId: any, valSearch: any, at_In: any, at_Out: any): any { + // a16-> id ==a16 ->4 + valSearch = "none" + + let nextValue = "" + for (let jj = 0; jj < data.actions.action.length; jj++) { + if (data.actions.action[jj]['@_id'] === actionId) { + for (let kk = 0; kk < data.actions.action[jj].when.length; kk++) { + nextValue = data.actions.action[jj].when[kk]['@_next'] + } + } + } + return nextValue + }*/ + /*public get_Output_From_Terminator(data: any, actionId: any, valSearch: any): any { + // a16-> id ==a16 ->4 + //todo what if douplicate value?? + let OutputValue = "" + for (let jj = 0; jj < data.keyboard.terminators.when.length; jj++) { + if (data.keyboard.terminators.when[jj]['@_state'] === actionId) { + OutputValue = data.keyboard.terminators.when[jj]['@_output'] + } + } + return OutputValue + }*/ + /*public get_Attribut_follow(data: any, parent: any, child: any, actionId: any, findtag: any, returntag: any, findtagContents: any): any { + + console.log("Input:", + "\nchild", child, + "\nactionId", actionId, + "\nfindtag", findtag, + "\nreturntag", returntag, + "\nfindtagContents", findtagContents, + "\nfdata.child.length", parent + "." + child + ".length", + "\nparent.child[jj]['@_id'] ", parent + "." + child + ".[0]['@_id']", + "\nparent.child[jj].when.length ", parent + "." + child + ".[0].when.length", + "\nparent.child[jj].when[kk][findtag] ", parent + "." + child + ".d[0].when[0]["+findtag+"]" + ) + console.log("Input:" + ) + const parent_child= (parent + "." + child) + // a16-> id ==a16 ->4 + //todo what if douplicate value?? + let OutputValue = "" + for (let jj = 0; jj < parent_child.length; jj++) { + if (parent_child[jj]['@_id'] === actionId) { + for (let kk = 0; kk < parent.child[jj].when.length; kk++) { + if (parent.child[jj].when[kk][findtag] === findtagContents) { + OutputValue = parent.child[jj].when[kk][returntag] + } + } + } + } + return OutputValue + }*/ + /*public get_Terminator_Output_from_Next(data: any, valSearch: any, at_In: any, at_Out: any): any { + + const valReturn = 0 + // take jsonObj(data), valSearch, valReturn, at_In, at_Out // valSearch =18 from next=18 + // return valReturn + // do: + // loop (i) through jsonObj-terminator until VAlSearch is found in when-@state + // get i + // return jsonObj-termin[i][@_out] + + + let nextValue = 0 + let returnvalue =0 + + //for (let k = 0; k < data.actions.length; k++) { + for (let k = 0; k < data.actions.action.length; k++) { + for (let j = 0; j < data.actions.action[k].when.length; j++) { + if ((data.actions.action[k].when[j]['@_state'] === "none" && data.actions.action[k].when[j]['@_next'] !== "undefined")) { + // if ((data.actions.action[k].when[j]['@_state'] === "none" )) { + nextValue = data.actions.action[k].when[j]['@_next'] + // console.log("found pair: ", k, j, data.actions.action[k]['@_id'], data.actions.action[k].when[j]['@_state'], "nextValue",nextValue) + + + for (let i = 0; i < data.terminators.when.length; i++) { + if (data.terminators.when[i]['@_state'] === nextValue) { + + returnvalue= data.terminators.when[i]['@_output'] + // console.log("terminators pair: ", i, nextValue, data.terminators.when[i]['@_output'], returnvalue) + } + } + } + } + } + return valReturn + }*/ + /* public get_Next_Output_from_Any(data: any, valSearch: any, at_In: any, at_Out: any): any { + + for (let k = 0; k < data.actions.action.length; k++) { + for (let j = 0; j < data.actions.action[k].when.length; j++) { + if ((data.actions.action[k].when[j]['@_state'] === valSearch && data.actions.action[k].when[j]['@_next'] !== "undefined")) { + const nextValue = data.actions.action[k].when[j]['@_next'] + // console.log("found pair: ", k, j, data.actions.action[k]['@_id'], data.actions.action[k].when[j]['@_state'], "nextValue",nextValue) + return nextValue + } + } + } + return "" + } + */ + /* public find_ID_for_Next(data: any, state: string): string { + // a16-> id ==a16 ->4 + //todo what if douplicate value?? + for (let jj = 0; jj < data.keyboard.actions.length; jj++) { + for (let k = 0; k < data.keyboard.actions.action[jj].length; k++) { + if (data.keyboard.actions.action[jj].when[k]['@_next'] !== undefined) + return data.keyboard.actions.action[jj]['@_id'] + } + } + return "" + }*/ + /* public get_Next_Output_from_Any_and_id(data: any, actionId: any, valSearch: any, at_In: any, at_Out: any): any { + + for (let j = 0; j < data.actions.action[actionId].when.length; j++) { + if ((data.actions.action[actionId].when[j]['@_state'] === valSearch && data.actions.action[actionId].when[j]['@_next'] !== "undefined")) { + const nextValue = data.actions.action[actionId].when[j]['@_next'] + // console.log("found pair: ", k, j, data.actions.action[k]['@_id'], data.actions.action[k].when[j]['@_state'], "nextValue",nextValue) + return nextValue + } + } + return "" + } + */ + /* public get_Terminator_Output_from_State(data: any, actionId: any, valSearch: any, at_In: any, at_Out: any): any { + + for (let j = 0; j < data.terminators.when.length; j++) { + if (data.terminators.when[j]['@_state'] === valSearch) { + return data.terminators.when[j]['@_output'] + } + } + return "" + }*/ + + + public getCharacterFromActionName(data_ukelele: convert_object, ArrayOf_Element_KeyActionElement: Uint8Array): any { //get character from ~ <- 4 <- a9 @@ -701,7 +1909,7 @@ console.log("char1",char1) // out: ~ //[ 97, 49 ]-> (a9) - console.log("ArrayOf_Element_KeyActionElement",ArrayOf_Element_KeyActionElement) + console.log("ArrayOf_Element_KeyActionElement", ArrayOf_Element_KeyActionElement) const ArrayOf_Element_KeyActionElement_string = new TextDecoder().decode(ArrayOf_Element_KeyActionElement) diff --git a/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts index b536e1c1ae3..20bea0925cc 100644 --- a/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts @@ -1,6 +1,11 @@ /* * Keyman is copyright (C) SIL International. MIT License. */ +/*run with +cd developer/src/kmc-convert/ +./build_disp.sh test*/ + + import 'mocha'; import {assert} from 'chai'; import {compilerTestCallbacks, compilerTestOptions} from './helpers/index.js'; @@ -37,8 +42,8 @@ describe('KeylayoutToKmnConverter', function() { // all keys, some deadkeys //const inputFilename = makePathToFixture('../data/US_complete.keylayout'); - //const inputFilename = makePathToFixture('../data/Italian_copy.keylayout'); - const inputFilename = makePathToFixture('../data/My_dk_Keyboard.keylayout'); + const inputFilename = makePathToFixture('../data/Italian_copy.keylayout'); + //const inputFilename = makePathToFixture('../data/My_dk_Keyboard.keylayout'); const outputFilename = makePathToFixture('../data/MyResult.kmn'); From c5aa31a2430b62b3cd1dccf195a3ad78252189fc Mon Sep 17 00:00:00 2001 From: Sabine Date: Tue, 10 Dec 2024 16:20:14 +0100 Subject: [PATCH 026/251] feat(developer): kmc-convert seems to get correct output data --- .../keylayout-to-kmn-converter.ts | 93 ++++++++++++++----- 1 file changed, 70 insertions(+), 23 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 21f67849858..553b1b22aea 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -1446,31 +1446,41 @@ export class KeylayoutToKmnConverter { // // // - for (let j = 0; j < jsonObj.keyboard.actions.action[indexInActions].when.length; j++) { + for (let jj = 0; jj < jsonObj.keyboard.actions.action[indexInActions].when.length; jj++) { // °°get state 3 <- - const stateVal = jsonObj.keyboard.actions.action[indexInActions].when[j]['@_state'] // a09 ->3 + const stateVal = jsonObj.keyboard.actions.action[indexInActions].when[jj]['@_state'] // a09 ->3 + if (stateVal !== undefined) { // get output  needed here?? CAse none-next (C3) - outputval = jsonObj.keyboard.actions.action[indexInActions].when[j]['@_output'] + outputval = jsonObj.keyboard.actions.action[indexInActions].when[jj]['@_output'] // get all that result in state 3 - nextvalArray = this.lookup_5_ActionState__To__ActionNext(jsonObj, stateVal) + nextvalArray = this.lookup_5_ActionState__To__ActionNext_none(jsonObj, stateVal) } + // console.log("nextvalArray",nextvalArray, outputval) for (let k = 0; k < nextvalArray.length; k++) { - console.log(" ### Key Nr", jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], - "[ + C2 modifiers]", "+", - nextvalArray[k] + - "-K_? +", - jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], - " > ", - outputval, "-", nextvalArray) + + if (outputval !== undefined) { + console.log(" ### Key Nr", j, "[ + C2 modifiers]", "+", "+ stateV ", stateVal, jsonObj.keyboard.keyMapSet[0].keyMap[i].key[jj]['@_code'], + + nextvalArray[k] + + "-K_? +", + jsonObj.keyboard.keyMapSet[0].keyMap[i].key[jj]['@_code'], + " > ", + outputval, "-", nextvalArray, "-----", stateVal, + "### Key Nr", j, "+modixx2 +key nr", this.lookup_11_KeyMapAction__To__KeyMapCode(jsonObj, nextvalArray[k]), " +keymapindex of this", + this.lookup_11_KeyMapAction__To__KeyIndex(jsonObj, nextvalArray[k]), ">", outputval, "(", nextvalArray[k], ")-----", i, j, k, jj, stateVal, outputval, nextvalArray, jsonObj.keyboard.keyMapSet[0].keyMap[i].key[jj]['@_code']) + } } + + + } // ...................................................................................................... - // case C3: action + state Nr + Next .................................................................... + // case C3: action + state Nr + Next ........................4............................................ // ...............e. g. ..................................................... // a key is mapped to an action and then to a terminator ................................................ // code->action->action(state)->action(next)->terminator(output) ....................................... @@ -1495,7 +1505,7 @@ export class KeylayoutToKmnConverter { const actionIdIndex = this.lookup_10_ActionId__To__ActioIndex(jsonObj, action_id) //loop through action a57 and get all states e.g state 14 -// what if mor linese xisted?? + // what if mor linese xisted?? let thatstate let thatnext let the_ContextKeyNr @@ -1505,16 +1515,9 @@ export class KeylayoutToKmnConverter { thatstate = jsonObj.keyboard.actions.action[actionIdIndex].when[l]['@_state'] thatnext = jsonObj.keyboard.actions.action[actionIdIndex].when[l]['@_next'] - let theContextID - for (let ll = 0; ll < jsonObj.keyboard.actions.action.length; ll++) { - for (let mm = 0; mm < jsonObj.keyboard.actions.action[ll].when.length; mm++) { - if ((jsonObj.keyboard.actions.action[ll].when[mm]['@_next'] === thatstate)) { - theContextID = jsonObj.keyboard.actions.action[ll]['@_id'] - - } - } - } + const theContextID = this.lookup_13_ActionNext__To__ActionID(jsonObj, thatstate) the_ContextKeyNr = this.lookup_11_KeyMapAction__To__KeyMapCode(jsonObj, theContextID) + } } const resultC3 = this.lookup_9_TerminatorState__To__TerminatorOutput_str(jsonObj, thatnext) @@ -1528,7 +1531,7 @@ export class KeylayoutToKmnConverter { ) // ...................................................................................................... - // case C4: action + state none + Next ............................................................DONE . + // case C4: action + state none + Next .......................................3.....................DONE . // ...............e. g. ................................................... // a key is mapped to an action and then to a terminator ................................................ // code->action->action(none)->action(next)->terminator(output) ........................................ @@ -1592,6 +1595,24 @@ export class KeylayoutToKmnConverter { } return returnarray } + public lookup_5_ActionState__To__ActionNext_none(data: any, action_idName: string): string[] { + const returnarray: string[] = [] + // e.g. action_idName = 3 + if (action_idName !== "none") { + // loop all action/when + for (let k = 0; k < data.keyboard.actions.action.length; k++) { + for (let j = 0; j < data.keyboard.actions.action[k].when.length; j++) { + // find attribute next === 3 + if (data.keyboard.actions.action[k].when[j]['@_next'] === action_idName) { + if (data.keyboard.actions.action[k].when[j]['@_state'] === "none") + returnarray.push(data.keyboard.actions.action[k]['@_id']) + } + } + } + } + return returnarray + } + public lookup_6_ActionNone__To__ActionOutput(data: any, search: any): any { // a16-> id ==a16 ->4 //todo what if douplicate value?? @@ -1652,6 +1673,22 @@ export class KeylayoutToKmnConverter { } return 999 } + + + public lookup_11_KeyMapAction__To__KeyIndex(data: any, search: string): number { + for (let kk = 0; kk < data.keyboard.keyMapSet[0].keyMap.length; kk++) { + for (let jj = 0; jj < data.keyboard.keyMapSet[0].keyMap[kk].key.length; jj++) { + + // console.log( "A action_id-search",kk,jj, search, data.keyboard.keyMapSet[0].keyMap[kk].key[jj]['@_action']) + if (data.keyboard.keyMapSet[0].keyMap[kk].key[jj]['@_action'] === search) { + + //console.log( "FOUND action_id-search",kk,jj, search, data.keyboard.keyMapSet[0].keyMap[kk].key[jj]['@_action'] ) + return data.keyboard.keyMapSet[0].keyMap[kk]['@_index'] + } + } + } + return 999 + } // get all entries that result in state 3 public lookup_12_ActionNext__from__ActionState(data: any, search: string): string { @@ -1669,7 +1706,17 @@ export class KeylayoutToKmnConverter { return "" } + public lookup_13_ActionNext__To__ActionID(data: any, search: string) { + for (let ll = 0; ll < data.keyboard.actions.action.length; ll++) { + for (let mm = 0; mm < data.keyboard.actions.action[ll].when.length; mm++) { + if ((data.keyboard.actions.action[ll].when[mm]['@_next'] === search)) { + return data.keyboard.actions.action[ll]['@_id'] + } + } + } + return "" + } //___________________ /* ?? check:*/ public get_Terminator_Output_from_Next(data: any, valSearch: any, at_In: any, at_Out: any): any { From 4fe023d6c67d1c3e2f94c336959df8384ad13d96 Mon Sep 17 00:00:00 2001 From: Sabine Date: Tue, 10 Dec 2024 18:03:29 +0100 Subject: [PATCH 027/251] feat(developer): kmc-convert data (console) output changed --- .../keylayout-to-kmn-converter.ts | 73 +++++-------------- 1 file changed, 20 insertions(+), 53 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 553b1b22aea..82227c20d60 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -1377,11 +1377,13 @@ export class KeylayoutToKmnConverter { // in keys at top for code 1 (K_S) take output ("s") [italian copy] // get modifiers [modifer of Keymap index 0] // write [modifer of Keymap index 0] + K_S > s - output_count++ + + + if (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] !== "") - console.log("### Key Nr", jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], - "[ + C0 modifiers]", "+", "K_?", " (key Code", jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], ") > ", + console.log("### Key Nr ", jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], + "[ + C0 modifiers]", "+", this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), "\t\t (key Code", jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], ") > ", jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output']) } @@ -1411,8 +1413,8 @@ export class KeylayoutToKmnConverter { const resultC1 = this.lookup_6_ActionNone__To__ActionOutput(jsonObj, action_id) if (resultC1 !== undefined) - console.log("### Key Nr", jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], - "[ + C1 modifiers]", "+", "K_?", " (keycode", jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], ") > ", resultC1) + console.log("### Key Nr ", jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], + "[ + C1 modifiers]", "+", this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']))," (\t\t keycode", jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], ") > ", resultC1) //Todo write into array // ...................................................................................................... @@ -1439,8 +1441,6 @@ export class KeylayoutToKmnConverter { //°° id a16 ->id nr 8 const indexInActions = this.lookup_10_ActionId__To__ActioIndex(jsonObj, action_id) - - // loop through all actionh/when find state and get action id // // @@ -1450,7 +1450,6 @@ export class KeylayoutToKmnConverter { // °°get state 3 <- const stateVal = jsonObj.keyboard.actions.action[indexInActions].when[jj]['@_state'] // a09 ->3 - if (stateVal !== undefined) { // get output  needed here?? CAse none-next (C3) outputval = jsonObj.keyboard.actions.action[indexInActions].when[jj]['@_output'] @@ -1458,27 +1457,16 @@ export class KeylayoutToKmnConverter { nextvalArray = this.lookup_5_ActionState__To__ActionNext_none(jsonObj, stateVal) } - // console.log("nextvalArray",nextvalArray, outputval) for (let k = 0; k < nextvalArray.length; k++) { - if (outputval !== undefined) { console.log(" ### Key Nr", j, "[ + C2 modifiers]", "+", "+ stateV ", stateVal, jsonObj.keyboard.keyMapSet[0].keyMap[i].key[jj]['@_code'], - - nextvalArray[k] + - "-K_? +", - jsonObj.keyboard.keyMapSet[0].keyMap[i].key[jj]['@_code'], - " > ", - outputval, "-", nextvalArray, "-----", stateVal, + nextvalArray[k] ,"\t", this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])),"\t\t", jsonObj.keyboard.keyMapSet[0].keyMap[i].key[jj]['@_code'], " > ", outputval, "-", nextvalArray, "-----", stateVal, "### Key Nr", j, "+modixx2 +key nr", this.lookup_11_KeyMapAction__To__KeyMapCode(jsonObj, nextvalArray[k]), " +keymapindex of this", this.lookup_11_KeyMapAction__To__KeyIndex(jsonObj, nextvalArray[k]), ">", outputval, "(", nextvalArray[k], ")-----", i, j, k, jj, stateVal, outputval, nextvalArray, jsonObj.keyboard.keyMapSet[0].keyMap[i].key[jj]['@_code']) } } - - - } - // ...................................................................................................... // case C3: action + state Nr + Next ........................4............................................ // ...............e. g. ..................................................... @@ -1523,18 +1511,14 @@ export class KeylayoutToKmnConverter { const resultC3 = this.lookup_9_TerminatorState__To__TerminatorOutput_str(jsonObj, thatnext) if (the_ContextKeyNr !== undefined) - console.log(" ### Key Nr", jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], - "[ + C3 modifiers]", - "+ K_?-", "(key Code", jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], - ") +", "K_?-", "(keyCode", the_ContextKeyNr, ")", - " > ", resultC3, + console.log(" ### Key Nr", jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], "[ + C3 modifiers]", "+",this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])),"\t\t ", "(key Code", jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], ") +", "-",this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), "\t\t(keyCode", the_ContextKeyNr, ")", " > ", resultC3, ) // ...................................................................................................... - // case C4: action + state none + Next .......................................3.....................DONE . + // case C4: action + state none + Next ............................................................DONE . // ...............e. g. ................................................... // a key is mapped to an action and then to a terminator ................................................ - // code->action->action(none)->action(next)->terminator(output) ........................................ + // code->action->action(none)->action(next)->terminator(output) ......................................... // ...................................................................................................... // in keys for code 32 (K_U) at top find actions id a16 [italian copy] // get modifiers [modifer of Keymap index 3] @@ -1549,8 +1533,8 @@ export class KeylayoutToKmnConverter { const resultC4 = this.lookup_9_TerminatorState__To__TerminatorOutput_str(jsonObj, next_id) if (resultC4 !== "") - console.log("### Key Nr", jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], - "[ + C4 modifiers]", "+ K_?-", "(key Code", jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], ") > ", resultC4, "[", action_id, next_id, "]") + console.log("### Key Nr ", jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], + "[ + C4 modifiers]", "+ ", this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']))," \t\t","(key Code", jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], ") > ", resultC4, "[", action_id, next_id, "]") } else console.log("ERROR : some entries are not available") @@ -1566,7 +1550,7 @@ export class KeylayoutToKmnConverter { } } }*/ - public lookup_2_KeyMapAction__To__ActionAction() { } + // public lookup_2_KeyMapAction__To__ActionAction() { } public lookup_3_ActionNone__To__ActionNext(data: any, search: string): string { for (let jj = 0; jj < data.keyboard.actions.action.length; jj++) { if (data.keyboard.actions.action[jj]['@_id'] === search) { @@ -1578,7 +1562,7 @@ export class KeylayoutToKmnConverter { } return "" } - public lookup_4_ActionNext__To__ActionState() { } + //public lookup_4_ActionNext__To__ActionState() { } public lookup_5_ActionState__To__ActionNext(data: any, action_idName: string): string[] { const returnarray: string[] = [] // e.g. action_idName = 3 @@ -1612,10 +1596,9 @@ export class KeylayoutToKmnConverter { } return returnarray } - public lookup_6_ActionNone__To__ActionOutput(data: any, search: any): any { // a16-> id ==a16 ->4 - //todo what if douplicate value?? + //todo what if duplicate value?? let OutputValue = "" for (let jj = 0; jj < data.keyboard.actions.action.length; jj++) { if (data.keyboard.actions.action[jj]['@_id'] === search) { @@ -1628,9 +1611,8 @@ export class KeylayoutToKmnConverter { } return OutputValue } - public lookup_7_ActionState__To__ActionOutput() { } - public lookup_8_ActionNext__To__TerminatorState() { - } + //public lookup_7_ActionState__To__ActionOutput() { } + //public lookup_8_ActionNext__To__TerminatorState() { } public lookup_9_TerminatorState__To__TerminatorOutput_ui8(data: any, search: string): Uint8Array { for (let jj = 0; jj < data.keyboard.terminators.when.length; jj++) { @@ -1657,32 +1639,20 @@ export class KeylayoutToKmnConverter { return 0 } - - public lookup_11_KeyMapAction__To__KeyMapCode(data: any, search: string): number { for (let kk = 0; kk < data.keyboard.keyMapSet[0].keyMap.length; kk++) { for (let jj = 0; jj < data.keyboard.keyMapSet[0].keyMap[kk].key.length; jj++) { - - // console.log( "A action_id-search",kk,jj, search, data.keyboard.keyMapSet[0].keyMap[kk].key[jj]['@_action']) if (data.keyboard.keyMapSet[0].keyMap[kk].key[jj]['@_action'] === search) { - - //console.log( "FOUND action_id-search",kk,jj, search, data.keyboard.keyMapSet[0].keyMap[kk].key[jj]['@_action'] ) return data.keyboard.keyMapSet[0].keyMap[kk].key[jj]['@_code'] } } } return 999 } - - public lookup_11_KeyMapAction__To__KeyIndex(data: any, search: string): number { for (let kk = 0; kk < data.keyboard.keyMapSet[0].keyMap.length; kk++) { for (let jj = 0; jj < data.keyboard.keyMapSet[0].keyMap[kk].key.length; jj++) { - - // console.log( "A action_id-search",kk,jj, search, data.keyboard.keyMapSet[0].keyMap[kk].key[jj]['@_action']) if (data.keyboard.keyMapSet[0].keyMap[kk].key[jj]['@_action'] === search) { - - //console.log( "FOUND action_id-search",kk,jj, search, data.keyboard.keyMapSet[0].keyMap[kk].key[jj]['@_action'] ) return data.keyboard.keyMapSet[0].keyMap[kk]['@_index'] } } @@ -1946,11 +1916,7 @@ export class KeylayoutToKmnConverter { } return "" }*/ - - - - - public getCharacterFromActionName(data_ukelele: convert_object, ArrayOf_Element_KeyActionElement: Uint8Array): any { + /*public getCharacterFromActionName(data_ukelele: convert_object, ArrayOf_Element_KeyActionElement: Uint8Array): any { //get character from ~ <- 4 <- a9 //in: [ 97, 49 ] (a9) // out: ~ @@ -1976,6 +1942,7 @@ export class KeylayoutToKmnConverter { } } +*/ /** * @brief member function to return the unicode value of a character From 35e510e2defca456c36ecd10cde54c29680c3128 Mon Sep 17 00:00:00 2001 From: Sabine Date: Wed, 11 Dec 2024 16:30:09 +0100 Subject: [PATCH 028/251] feat(developer): kmc-convert add shiftstate combinations for output --- .../keylayout-to-kmn-converter.ts | 154 ++++++++++++++---- 1 file changed, 119 insertions(+), 35 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 82227c20d60..2926caefdcc 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -1351,17 +1351,21 @@ export class KeylayoutToKmnConverter { console.log("stringArray", stringArray) // end - + console.log("json", jsonObj.keyboard.terminators) console.log("jsonObj.keyboard.keyMapSet.le", jsonObj.keyboard.keyMapSet[0].keyMap.length) let action_id - for (let i = 0; i < jsonObj.keyboard.keyMapSet[0].keyMap.length; i++) { - let output_count = 0 - let action_count = 0 - let all_count = 0 - // loop keys - for (let j = 0; j < jsonObj.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { + const isCapsused = this.checkIfCapsUsed(data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect) + + // loop keys + //for (let j = 0; j < jsonObj.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { + for (let j = 0; j < 52; j++) { + for (let i = 0; i < jsonObj.keyboard.keyMapSet[0].keyMap.length; i++) { + let output_count = 0 + let action_count = 0 + let all_count = 0 + // ...................................................................................................... // case C0: code + output ............................................................................... // ...................................................................................................... @@ -1378,13 +1382,23 @@ export class KeylayoutToKmnConverter { // get modifiers [modifer of Keymap index 0] // write [modifer of Keymap index 0] + K_S > s output_count++ - - - - if (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] !== "") - console.log("### Key Nr ", jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], - "[ + C0 modifiers]", "+", this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), "\t\t (key Code", jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], ") > ", - jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output']) + for (let l = 0; l < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i].length; l++) { + const modifier_C0 = this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i][l], isCapsused) + if (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] !== "") + + console.log("### Key Nr ", + jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], + "[ + C0 modifiers->", i, modifier_C0.padEnd(25, " "), "] ", + this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])).padEnd(8, " "), + "> ", + jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output']) + + + DataArraySingleState.push(modifier_C0) + DataArraySingleState.push(this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']))) + DataArraySingleState.push(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output']) + } + DataArray.push(DataArraySingleState) } @@ -1411,10 +1425,18 @@ export class KeylayoutToKmnConverter { // write [modifer of Keymap index 0] + K_A > a action_id = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] const resultC1 = this.lookup_6_ActionNone__To__ActionOutput(jsonObj, action_id) - - if (resultC1 !== undefined) - console.log("### Key Nr ", jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], - "[ + C1 modifiers]", "+", this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']))," (\t\t keycode", jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], ") > ", resultC1) + for (let l = 0; l < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i].length; l++) { + const modifier_C1 = this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i][l], isCapsused) + + if (resultC1 !== undefined) + console.log( + "### Key Nr ", + jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], + "[ + C1 modifiers->", i, modifier_C1.padEnd(25, " "), "] ", + this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])).padEnd(8, " "), + "> ", + resultC1) + } //Todo write into array // ...................................................................................................... @@ -1456,13 +1478,33 @@ export class KeylayoutToKmnConverter { // get all that result in state 3 nextvalArray = this.lookup_5_ActionState__To__ActionNext_none(jsonObj, stateVal) } - - for (let k = 0; k < nextvalArray.length; k++) { - if (outputval !== undefined) { - console.log(" ### Key Nr", j, "[ + C2 modifiers]", "+", "+ stateV ", stateVal, jsonObj.keyboard.keyMapSet[0].keyMap[i].key[jj]['@_code'], - nextvalArray[k] ,"\t", this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])),"\t\t", jsonObj.keyboard.keyMapSet[0].keyMap[i].key[jj]['@_code'], " > ", outputval, "-", nextvalArray, "-----", stateVal, - "### Key Nr", j, "+modixx2 +key nr", this.lookup_11_KeyMapAction__To__KeyMapCode(jsonObj, nextvalArray[k]), " +keymapindex of this", - this.lookup_11_KeyMapAction__To__KeyIndex(jsonObj, nextvalArray[k]), ">", outputval, "(", nextvalArray[k], ")-----", i, j, k, jj, stateVal, outputval, nextvalArray, jsonObj.keyboard.keyMapSet[0].keyMap[i].key[jj]['@_code']) + for (let l = 0; l < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i].length; l++) { + const modifier_C2 = this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i][l], isCapsused) + + for (let k = 0; k < nextvalArray.length; k++) { + if (outputval !== undefined) { + console.log( + " ### Key Nr", + "nextvalArray.length",nextvalArray.length, + j, + "[ + C2 modifiers->", i, modifier_C2.padEnd(25, " "), "] ", + this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])).padEnd(8, " "), + "> ", + outputval, + "\t stateV ->", stateVal, + jsonObj.keyboard.keyMapSet[0].keyMap[i].key[jj]['@_code'], + nextvalArray[k], + + "-", + nextvalArray, + "-----", + "### Key Nr", + "+modixx2 +key nr", + this.lookup_11_KeyMapAction__To__KeyMapCode(jsonObj, nextvalArray[k]), + " +keymapindex of this", + this.lookup_11_KeyMapAction__To__KeyIndex(jsonObj, nextvalArray[k]) + ) + } } } } @@ -1509,11 +1551,26 @@ export class KeylayoutToKmnConverter { } } const resultC3 = this.lookup_9_TerminatorState__To__TerminatorOutput_str(jsonObj, thatnext) - - if (the_ContextKeyNr !== undefined) - console.log(" ### Key Nr", jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], "[ + C3 modifiers]", "+",this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])),"\t\t ", "(key Code", jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], ") +", "-",this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), "\t\t(keyCode", the_ContextKeyNr, ")", " > ", resultC3, - ) - + for (let l = 0; l < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i].length; l++) { + const modifier_C3 = this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i][l], isCapsused) + + if (the_ContextKeyNr !== undefined) + console.log( + " ### Key Nr", + jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], + "[ + C3 modifiers->", i, modifier_C3.padEnd(25, " "), "] ", + this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])).padEnd(8, " "), + "\t ", + "(key Code", jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], + ") + ", + this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), + "\t\t(keyCode", + the_ContextKeyNr, + ")", + "> ", + resultC3, + ) + } // ...................................................................................................... // case C4: action + state none + Next ............................................................DONE . // ...............e. g. ................................................... @@ -1531,11 +1588,24 @@ export class KeylayoutToKmnConverter { const next_id = this.lookup_3_ActionNone__To__ActionNext(jsonObj, action_id) const resultC4 = this.lookup_9_TerminatorState__To__TerminatorOutput_str(jsonObj, next_id) - - if (resultC4 !== "") - console.log("### Key Nr ", jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], - "[ + C4 modifiers]", "+ ", this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']))," \t\t","(key Code", jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], ") > ", resultC4, "[", action_id, next_id, "]") + for (let l = 0; l < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i].length; l++) { + const modifier_C4 = this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i][l], isCapsused) + + if (resultC4 !== "") + console.log( + "### Key Nr ", + jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], + "[ + C4 modifiers->", i, modifier_C4.padEnd(25, " "), "] ", + this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])).padEnd(8, " "), + "> ", + resultC4, + " [", + action_id, + next_id, + "]") + } } + else console.log("ERROR : some entries are not available") } @@ -1550,7 +1620,7 @@ export class KeylayoutToKmnConverter { } } }*/ - // public lookup_2_KeyMapAction__To__ActionAction() { } + // public lookup_2_KeyMapAction__To__ActionAction() { } public lookup_3_ActionNone__To__ActionNext(data: any, search: string): string { for (let jj = 0; jj < data.keyboard.actions.action.length; jj++) { if (data.keyboard.actions.action[jj]['@_id'] === search) { @@ -1973,6 +2043,8 @@ export class KeylayoutToKmnConverter { // opt?+ LOPT?+ ROPT? -> what will be result?? for (let i = 0; i < modifier_state.length; i++) { + /*if (String(modifier_state[i]) === "Command") + continue*/ if (isCAPSused && (String(keylayout_modifier).indexOf("caps") === -1)) kmn_ncaps = " NCAPS " @@ -2018,6 +2090,18 @@ export class KeylayoutToKmnConverter { return unique_Modifier.join(" ").replace(/\s+/g, " ").trim().toUpperCase() } + public checkIfCapsUsed(keylayout_modifier: string[][]): boolean { + for (let i = 0; i < keylayout_modifier.length; i++) { + for (let j = 0; j < keylayout_modifier[i].length; j++) { + const modifier_state: string[] = keylayout_modifier[i][j].split(" "); + for (let k = 0; k < modifier_state.length; k++) { + if ((modifier_state[k].indexOf("caps") !== -1) && (modifier_state[k].indexOf("caps?") === -1)) + return true + } + } + } + return false + } /** * @brief member function to map Ukelele keycodes to a Windows Keycodes From 2e100eff7c38cfde860cdaf0ef5874b8f005a30b Mon Sep 17 00:00:00 2001 From: Sabine Date: Fri, 13 Dec 2024 11:55:12 +0100 Subject: [PATCH 029/251] feat(developer): kmc-convert output for keys and shiftstates OK --- .../keylayout-to-kmn-converter.ts | 412 +++++++++++------- 1 file changed, 262 insertions(+), 150 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 2926caefdcc..551d14c246b 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -46,6 +46,7 @@ import boxXmlArray = util.boxXmlArray;*/ // no added NCAPS when first modifier in modifierMap does not contain "caps" or"caps?" // use length to clear array instead of defining evetry time new (modifierMap_ONE_InKeymapSelect.length=0 // naming of for-loop var i,j,k?... +// warning if contrADICTING RULES E:G: [ 'modifier_C0', 'SHIFT NCAPS', 'K_C', 'c', '0', '1' ], vs [ 'modifier_C0', 'SHIFT NCAPS', 'K_C', 'C', '1', '0' ], @@ -129,6 +130,7 @@ export interface convert_object { ArrayOf_processed_deadkeyables: string[][], // add char that can be modified with dk ( a,e,i,o,u) ArrayOf_processed_deadkeyedChar: string[][], // add modified keys ( â,ê,î,ô,û) ArrayOf_processed_RuleData: Uint8Array[][] // add modified keys ( â,ê,î,ô,û) + ArrayOf_processed_RuleDataStr: String[][] // add modified keys ( â,ê,î,ô,û) }; @@ -218,6 +220,7 @@ export class KeylayoutToKmnConverter { const duplicate_layouts_array: string[] = [] // array holding the layouts e.g. ANSI or JIS // needed?? I think no const deadkeyedChars_all_Layers: string[][] = [] // array holding all DEADKEYS for each mod state â, ê, ,.... const kmn_Rules_AllLayers: Uint8Array[][] = [] + const kmn_Rules_AllLayersStr: string[][] = [] let dk_pairs_all_Layers: string[][] = [] // add dk-mapping ( dk1 <-> '^' ) @@ -414,7 +417,6 @@ export class KeylayoutToKmnConverter { }); } - //console.log("deadkeyables_all_Layers after", deadkeyables_all_Layers) //double not needed??? @@ -440,23 +442,19 @@ export class KeylayoutToKmnConverter { for (let j = 0; j < dk_pairs_all_Layers.length; j++) { - //console.log("bis hier j", j) const deadkeys_One_dk: string[] = [] // find in action e.g. for (let k = 0; k < keys_action_all_Layers[j].length; k++) { - //console.log("bis hier k", k) const action_from_keys_prargraph = new TextDecoder().decode(keys_action_all_Layers[j][k]) if (action_from_keys_prargraph !== "") { // find the same id (e.g. ) in the actions-paragraph for (let l = 0; l < jsonObj.keyboard.actions.action.length; l++) { - //console.log("bis hier l", l) if (jsonObj.keyboard.actions.action[l]['@_id'] === action_from_keys_prargraph) { // loop through when until dk name (e.g. dk s0) for (let m = 0; m < jsonObj.keyboard.actions.action[l].when.length; m++) { - // console.log("bis hier m", m) // and get their @_output if (jsonObj.keyboard.actions.action[l].when[m]['@_state'] === dk_pairs_all_Layers[j][0]) { // todo push only if @output is found. if next is found: get value from terminators @@ -478,7 +476,6 @@ export class KeylayoutToKmnConverter { const vk: (string | number)[][] = [] - // TODO remove unneccassary elements const DataObject: convert_object = { name: "Ukelele-kmn", // needed?? remove @@ -493,7 +490,8 @@ export class KeylayoutToKmnConverter { ArrayOf_processed_deadkeyables: deadkeyables_all_Layers, // add char that can be modified with dk ( a,e,i,o,u) ArrayOf_processed_deadkeyedChar: deadkeyedChars_all_Layers, // add modified keys ( â,ê,î,ô,û) - ArrayOf_processed_RuleData: kmn_Rules_AllLayers + ArrayOf_processed_RuleData: kmn_Rules_AllLayers, + ArrayOf_processed_RuleDataStr: kmn_Rules_AllLayersStr }; // TODO review condition @@ -531,6 +529,7 @@ export class KeylayoutToKmnConverter { const duplicate_layouts_array: string[] = [] // array holding the layouts e.g. ANSI or JIS // needed?? I think no const deadkeyedChars_all_Layers: string[][] = [] // array holding all DEADKEYS for each mod state â, ê, ,.... const kmn_Rules_AllLayers: Uint8Array[][] = [] + const kmn_Rules_AllLayersStr: string[][] = [] let dk_pairs_all_Layers: string[][] = [] // add dk-mapping ( dk1 <-> '^' ) boxArrays_S(jsonObj.keyboard); @@ -692,7 +691,6 @@ export class KeylayoutToKmnConverter { } } } - // fills correct entries into modifier 1-3 then false ( because of no action any more) //const resulting_character = new TextDecoder().decode(keys_action_all_Layers[j][i]) @@ -701,7 +699,6 @@ export class KeylayoutToKmnConverter { if (resulting_character !== "") deadkeyables_one.push(resulting_character) } - for (let k = 0; k < dk_pairs_all_Layers.length; k++) { dk.push(dk_pairs_all_Layers[k][1]) } @@ -742,26 +739,23 @@ export class KeylayoutToKmnConverter { // in their 'when' find output for dk // for all 'action' at keys paragraph + // ToDo URTGENT duplicate dk ????? for (let j = 0; j < dk_pairs_all_Layers.length; j++) { - - //console.log("bis hier j", j) + //for (let j = 0; j < keys_action_all_Layers.length; j++) { const deadkeys_One_dk: string[] = [] // find in action e.g. for (let k = 0; k < keys_action_all_Layers[j].length; k++) { - //console.log("bis hier k", k) const action_from_keys_prargraph = new TextDecoder().decode(keys_action_all_Layers[j][k]) if (action_from_keys_prargraph !== "") { // find the same id (e.g. ) in the actions-paragraph for (let l = 0; l < jsonObj.keyboard.actions.action.length; l++) { - //console.log("bis hier l", l) if (jsonObj.keyboard.actions.action[l]['@_id'] === action_from_keys_prargraph) { // loop through when until dk name (e.g. dk s0) for (let m = 0; m < jsonObj.keyboard.actions.action[l].when.length; m++) { - // console.log("bis hier m", m) // and get their @_output if (jsonObj.keyboard.actions.action[l].when[m]['@_state'] === dk_pairs_all_Layers[j][0]) { // todo push only if @output is found. if next is found: get value from terminators @@ -774,7 +768,9 @@ export class KeylayoutToKmnConverter { } } } + } + // console.log("deadkeys_One_dk", deadkeys_One_dk) deadkeyedChars_all_Layers.push(deadkeys_One_dk) @@ -798,11 +794,15 @@ export class KeylayoutToKmnConverter { ArrayOf_processed_deadkeyables: deadkeyables_all_Layers, // add char that can be modified with dk ( a,e,i,o,u) ArrayOf_processed_deadkeyedChar: deadkeyedChars_all_Layers, // add modified keys ( â,ê,î,ô,û) - ArrayOf_processed_RuleData: kmn_Rules_AllLayers + ArrayOf_processed_RuleData: kmn_Rules_AllLayers, + ArrayOf_processed_RuleDataStr: kmn_Rules_AllLayersStr }; const filled_Data = this.collect_Data_From_File(DataObject, jsonObj) + console.log("filled_Data-len", filled_Data.length) + console.log("filled_Data", filled_Data) + // TODO review condition return filled_Data return DataObject @@ -840,6 +840,7 @@ export class KeylayoutToKmnConverter { const duplicate_layouts_array: string[] = [] // array holding the layouts e.g. ANSI or JIS // needed?? I think no const deadkeyedChars_all_Layers: string[][] = [] // array holding all DEADKEYS for each mod state â, ê, ,.... const kmn_Rules_AllLayers: Uint8Array[][] = [] + const kmn_Rules_AllLayersStr: string[][] = [] let dk_pairs_all_Layers: string[][] = [] // add dk-mapping ( dk1 <-> '^' ) boxArrays_S(jsonObj.keyboard); @@ -1054,23 +1055,19 @@ export class KeylayoutToKmnConverter { for (let j = 0; j < dk_pairs_all_Layers.length; j++) { - //console.log("bis hier j", j) const deadkeys_One_dk: string[] = [] // find in action e.g. for (let k = 0; k < keys_action_all_Layers[j].length; k++) { - //console.log("bis hier k", k) const action_from_keys_prargraph = new TextDecoder().decode(keys_action_all_Layers[j][k]) if (action_from_keys_prargraph !== "") { // find the same id (e.g. ) in the actions-paragraph for (let l = 0; l < jsonObj.keyboard.actions.action.length; l++) { - //console.log("bis hier l", l) if (jsonObj.keyboard.actions.action[l]['@_id'] === action_from_keys_prargraph) { // loop through when until dk name (e.g. dk s0) for (let m = 0; m < jsonObj.keyboard.actions.action[l].when.length; m++) { - // console.log("bis hier m", m) // and get their @_output if (jsonObj.keyboard.actions.action[l].when[m]['@_state'] === dk_pairs_all_Layers[j][0]) { // todo push only if @output is found. if next is found: get value from terminators @@ -1107,7 +1104,8 @@ export class KeylayoutToKmnConverter { ArrayOf_processed_deadkeyables: deadkeyables_all_Layers, // add char that can be modified with dk ( a,e,i,o,u) ArrayOf_processed_deadkeyedChar: deadkeyedChars_all_Layers, // add modified keys ( â,ê,î,ô,û) - ArrayOf_processed_RuleData: kmn_Rules_AllLayers + ArrayOf_processed_RuleData: kmn_Rules_AllLayers, + ArrayOf_processed_RuleDataStr: kmn_Rules_AllLayersStr }; // TODO review condition @@ -1335,32 +1333,48 @@ export class KeylayoutToKmnConverter { //... helpers ............................................................................................. // TODO move outside of class? + // TODO use UInt8 instead of string - public collect_Data_From_File(data_ukelele: convert_object, jsonObj: any): convert_object { + //public collect_Data_From_File(data_ukelele: convert_object, jsonObj: any): convert_object { + public collect_Data_From_File(data_ukelele: convert_object, jsonObj: any): any { - //Testarray - const UintArray: Uint8Array[] = []; - const stringArray: Uint8Array[][] = []; + /*const DataArray: string[][] = [] + const DataArrayU8: Uint8Array[][] = [] - UintArray.push(new TextEncoder().encode("K_A")) - UintArray.push(new TextEncoder().encode("K_B")) - UintArray.push(new TextEncoder().encode(">")) - UintArray.push(new TextEncoder().encode("ሴ")) - stringArray.push(UintArray) - console.log("UintArray", UintArray[0], UintArray[3]) - console.log("stringArray", stringArray) - // end - - console.log("json", jsonObj.keyboard.terminators) - console.log("jsonObj.keyboard.keyMapSet.le", jsonObj.keyboard.keyMapSet[0].keyMap.length) - let action_id + const testUI8 = "a" + const testUI8_1 = new TextEncoder().encode(testUI8); + + const testUI82 = "ẞ" + const testUI8_12 = new TextEncoder().encode(testUI82); + + const testUI83 = "ሴ" + const testUI8_13 = new TextEncoder().encode(testUI83); + + const arrayString: string[]=[] + const Ui8String: Uint8Array[]=[] + + + Ui8String.push(testUI8_1) + arrayString.push(testUI8,testUI8_1) + + + + console.log("arrayString",arrayString, + "Ui8String",Ui8String + )*/ + + + let action_id + let output_id const isCapsused = this.checkIfCapsUsed(data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect) + // loop keys //for (let j = 0; j < jsonObj.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { for (let j = 0; j < 52; j++) { + // loop behaviors for (let i = 0; i < jsonObj.keyboard.keyMapSet[0].keyMap.length; i++) { let output_count = 0 let action_count = 0 @@ -1381,36 +1395,42 @@ export class KeylayoutToKmnConverter { // in keys at top for code 1 (K_S) take output ("s") [italian copy] // get modifiers [modifer of Keymap index 0] // write [modifer of Keymap index 0] + K_S > s + // ...................................................................................................... output_count++ + output_id = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] + // loop modifiers for (let l = 0; l < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i].length; l++) { - const modifier_C0 = this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i][l], isCapsused) - if (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] !== "") + + const DataArraySingleStateC0: string[] = [] + + if (output_id !== "") { + const first_modifier_C0 = this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i][l], isCapsused) + const result_C0 = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] + const first_key_C0 = this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])) console.log("### Key Nr ", jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], - "[ + C0 modifiers->", i, modifier_C0.padEnd(25, " "), "] ", + "[ + C0 modifiers->", i, first_modifier_C0.padEnd(25, " "), "] ", this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])).padEnd(8, " "), "> ", jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output']) - - DataArraySingleState.push(modifier_C0) - DataArraySingleState.push(this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']))) - DataArraySingleState.push(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output']) + DataArraySingleStateC0.push("first_modifier_C0") + DataArraySingleStateC0.push(first_modifier_C0) + DataArraySingleStateC0.push(first_key_C0) + DataArraySingleStateC0.push(result_C0) + } + + if (DataArraySingleStateC0.length > 0) + DataArray.push(DataArraySingleStateC0) } - DataArray.push(DataArraySingleState) } - // ...................................................................................................... // actions ............................................................................... // ...................................................................................................... else if (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] !== undefined) { - action_count++ - /* console.log("_action is ",i,j, jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'], - "--",action_count, "of ", action_count+output_count, all_count)*/ - // ...................................................................................................... // case C1: action + state none + output .......................................................DONE .. // a key is mapped to an action and then to an output ................................................... @@ -1423,22 +1443,38 @@ export class KeylayoutToKmnConverter { // in action id a9 find "none" // get output "a" // write [modifer of Keymap index 0] + K_A > a + // ...................................................................................................... + + action_count++ + action_id = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] - const resultC1 = this.lookup_6_ActionNone__To__ActionOutput(jsonObj, action_id) + const result_C1 = this.lookup_6_ActionNone__To__ActionOutput(jsonObj, action_id) + + // modifiers for (let l = 0; l < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i].length; l++) { - const modifier_C1 = this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i][l], isCapsused) + const DataArraySingleStateC1: any[] = [] + + if (result_C1 !== undefined) { + const first_modifier_C1 = this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i][l], isCapsused) + const first_key_C1 = this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])) - if (resultC1 !== undefined) console.log( "### Key Nr ", jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], - "[ + C1 modifiers->", i, modifier_C1.padEnd(25, " "), "] ", + "[ + C1 modifiers->", i, first_modifier_C1.padEnd(25, " "), "] ", this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])).padEnd(8, " "), "> ", - resultC1) - } - //Todo write into array + result_C1) + DataArraySingleStateC1.push("first_modifier_C1") + DataArraySingleStateC1.push(first_modifier_C1) + DataArraySingleStateC1.push(first_key_C1) + DataArraySingleStateC1.push(result_C1) + } + + if (DataArraySingleStateC1.length > 0) + DataArray.push(DataArraySingleStateC1) + } // ...................................................................................................... // case C2: action + state Nr + output .........................................................DONE .... // a key is mapped to an action, then to an output+state ................................................ @@ -1454,122 +1490,165 @@ export class KeylayoutToKmnConverter { // get modifiers [modifer of Keymap index 3] (=anyOption) // [modifer of Keymap index 3] + K_A + K_9 > à // write anyOption + K_A + K_9 > à + // ...................................................................................................... - - let outputval + let result_C2 let nextvalArray: string[] = [] - // a16 + + // get action id: e.g. id a16 ->id nr 8 action_id = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] - //°° id a16 ->id nr 8 const indexInActions = this.lookup_10_ActionId__To__ActioIndex(jsonObj, action_id) - // loop through all actionh/when find state and get action id - // - // - // - // + // loop through all actionh/when find state and get action id ( 8-> state 3) for (let jj = 0; jj < jsonObj.keyboard.actions.action[indexInActions].when.length; jj++) { - // °°get state 3 <- - const stateVal = jsonObj.keyboard.actions.action[indexInActions].when[jj]['@_state'] // a09 ->3 + const stateVal = jsonObj.keyboard.actions.action[indexInActions].when[jj]['@_state'] + + // if there is a state defined, collect all cases which result in that state ( e.g. which case has next = 3) if (stateVal !== undefined) { - // get output  needed here?? CAse none-next (C3) - outputval = jsonObj.keyboard.actions.action[indexInActions].when[jj]['@_output'] - // get all that result in state 3 + // get output + result_C2 = jsonObj.keyboard.actions.action[indexInActions].when[jj]['@_output'] + // get all cases which result in state 3 nextvalArray = this.lookup_5_ActionState__To__ActionNext_none(jsonObj, stateVal) - } - for (let l = 0; l < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i].length; l++) { - const modifier_C2 = this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i][l], isCapsused) - - for (let k = 0; k < nextvalArray.length; k++) { - if (outputval !== undefined) { - console.log( - " ### Key Nr", - "nextvalArray.length",nextvalArray.length, - j, - "[ + C2 modifiers->", i, modifier_C2.padEnd(25, " "), "] ", - this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])).padEnd(8, " "), - "> ", - outputval, - "\t stateV ->", stateVal, - jsonObj.keyboard.keyMapSet[0].keyMap[i].key[jj]['@_code'], - nextvalArray[k], - - "-", - nextvalArray, - "-----", - "### Key Nr", - "+modixx2 +key nr", - this.lookup_11_KeyMapAction__To__KeyMapCode(jsonObj, nextvalArray[k]), - " +keymapindex of this", - this.lookup_11_KeyMapAction__To__KeyIndex(jsonObj, nextvalArray[k]) - ) + + // for all modifier combinations + for (let l = 0; l < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i].length; l++) { + + const DataArraySingleStateC2: string[] = [] + + for (let k = 0; k < nextvalArray.length; k++) { + if (result_C2 !== undefined) { + + const first_modifier_C2 = this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i][l], isCapsused) + const first_Key_C2 = this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])) + const second_Key_C2 = this.map_UkeleleKC_To_VK(Number(this.lookup_11_KeyMapAction__To__KeyMapCode(jsonObj, nextvalArray[k]))) + + console.log( + " ### Key Nr", + "nextvalArray.length", nextvalArray.length, + j, + "[ + C2 modifiers->", i, first_modifier_C2.padEnd(25, " "), "] ", + //this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])).padEnd(8, " "), + first_Key_C2.padEnd(8, " "), + "> ", + result_C2, + "\t stateV ->", stateVal, + jsonObj.keyboard.keyMapSet[0].keyMap[i].key[jj]['@_code'], + nextvalArray[k], + + "-", + nextvalArray, + "-----", + "### Key Nr", + "+modixx2 +key nr", + this.lookup_11_KeyMapAction__To__KeyMapCode(jsonObj, nextvalArray[k]), + " +keymapindex of this", + this.lookup_11_KeyMapAction__To__KeyIndex(jsonObj, nextvalArray[k]) + ) + + DataArraySingleStateC2.push("modifier_C2") + DataArraySingleStateC2.push(first_modifier_C2) + DataArraySingleStateC2.push(first_Key_C2) + DataArraySingleStateC2.push(second_Key_C2)// state = none -> no modifier + DataArraySingleStateC2.push(result_C2) + } + if (DataArraySingleStateC2.length > 0) + DataArray.push(DataArraySingleStateC2) } } } } // ...................................................................................................... - // case C3: action + state Nr + Next ........................4............................................ + // case C3: action + state Nr + Next .................................................................... // ...............e. g. ..................................................... // a key is mapped to an action and then to a terminator ................................................ - // code->action->action(state)->action(next)->terminator(output) ....................................... + // code->action->action(state)->action(next)->terminator(output) ........................................ + // ...................................................................................................... + {// in keys at top for code 10 (=K_BACKQUOTE) take actions id (a57) [German standard copy] + // code 10 = K_BACKQUOTE (or another key 93) + // get modifiers [modifer of Keymap index 0] + // goto action id a57 + // goto when 14 + + // loop through all actions to find next="14" ( might find several) + // get actionsId and output (a80 ) + // get modifiers [modifer of Keymap index 3] + // look at top for a80 => code 40 (= K_K) ( this is how we could get to state 14) + // take 20 and look for state = 20 in terminators ( because of "next") + // get output ("̭") + // [modifer of Keymap index 0] + a57 + +[modifer of Keymap index 3] state14 -> next 20 + // <=>[modifer of Keymap index 0] + K_BACKQUOTE +[modifer of Keymap index 3] K_K -> "̭" + } // ...................................................................................................... - // in keys at top for code 10 (=K_BACKQUOTE) take actions id (a57) [German standard copy] - // code 10 = K_BACKQUOTE (or another key 93) - // get modifiers [modifer of Keymap index 0] - // goto action id a57 - // goto when 14 - - // loop through all actions to find next="14" ( might find several) - // get actionsId and output (a80 ) - // get modifiers [modifer of Keymap index 3] - // look at top for a80 => code 40 (= K_K) ( this is how we could get to state 14) - // take 20 and look for state = 20 in terminators ( because of "next") - // get output ("̭") - // [modifer of Keymap index 0] + a57 + +[modifer of Keymap index 3] state14 -> next 20 - // <=>[modifer of Keymap index 0] + K_BACKQUOTE +[modifer of Keymap index 3] K_K -> "̭" - // get a57 + // get a9 in behavior/key action_id = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] const actionIdIndex = this.lookup_10_ActionId__To__ActioIndex(jsonObj, action_id) + const DataArraySingleStateC3: string[] = [] - //loop through action a57 and get all states e.g state 14 - // what if mor linese xisted?? - let thatstate - let thatnext + let value_state + let value_next let the_ContextKeyNr + let first_key_C3 + let keymapIndexForactionID_2: any[][] + + // loop all action-when and find state-next-pair for (let l = 0; l < jsonObj.keyboard.actions.action[actionIdIndex].when.length; l++) { - if ((jsonObj.keyboard.actions.action[actionIdIndex].when[l]['@_state'] !== "none") && (jsonObj.keyboard.actions.action[actionIdIndex].when[l]['@_next'] !== undefined)) { - thatstate = jsonObj.keyboard.actions.action[actionIdIndex].when[l]['@_state'] - thatnext = jsonObj.keyboard.actions.action[actionIdIndex].when[l]['@_next'] + // state_next data + if ((jsonObj.keyboard.actions.action[actionIdIndex].when[l]['@_state'] !== "none") + && (jsonObj.keyboard.actions.action[actionIdIndex].when[l]['@_next'] !== undefined)) { + + value_state = jsonObj.keyboard.actions.action[actionIdIndex].when[l]['@_state'] // e.g. 3 + value_next = jsonObj.keyboard.actions.action[actionIdIndex].when[l]['@_next'] // e.g. 1 - const theContextID = this.lookup_13_ActionNext__To__ActionID(jsonObj, thatstate) + // get actionId of that state/next pair (3,1) e.g. actionId a17 + const theContextID = this.lookup_13_ActionNext__To__ActionID(jsonObj, value_state) + // find keyNr of that actionID a17-> code=28 the_ContextKeyNr = this.lookup_11_KeyMapAction__To__KeyMapCode(jsonObj, theContextID) + // find all occurences of a17 e.g. key 28/3 [ [ '28', 3 ] ] + keymapIndexForactionID_2 = this.lookup_14_ActionName__To__MapIndex(jsonObj, String(theContextID)) + // get keyname e.g. 28-> K_8 + first_key_C3 = this.map_UkeleleKC_To_VK(Number(the_ContextKeyNr)) } - } - const resultC3 = this.lookup_9_TerminatorState__To__TerminatorOutput_str(jsonObj, thatnext) - for (let l = 0; l < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i].length; l++) { - const modifier_C3 = this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i][l], isCapsused) - if (the_ContextKeyNr !== undefined) - console.log( - " ### Key Nr", - jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], - "[ + C3 modifiers->", i, modifier_C3.padEnd(25, " "), "] ", - this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])).padEnd(8, " "), - "\t ", - "(key Code", jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], - ") + ", - this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), - "\t\t(keyCode", - the_ContextKeyNr, - ")", - "> ", - resultC3, - ) + const result_C3 = this.lookup_9_TerminatorState__To__TerminatorOutput_str(jsonObj, value_next) + + for (let l = 0; l < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i].length; l++) { + const second_modifier_C3 = this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i][l], isCapsused) + + if (the_ContextKeyNr !== undefined) { + + const second_key_Nr = Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']) + const second_key_C3 = this.map_UkeleleKC_To_VK(second_key_Nr) + + for (let kk = 0; kk < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[keymapIndexForactionID_2[0][1]].length; kk++) { + + const first_modifier_text_C3 = data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[keymapIndexForactionID_2[0][1]][kk] + const first_modifier_C3 = this.create_kmn_modifier(first_modifier_text_C3, isCapsused) + + console.log(" ### Key Nr", jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], + "[ + C3 modifiers->", i, l, + "[", first_modifier_C3, first_key_C3, "]", + "> dk(dk1) ######### ", " dk(dk1) + [", + second_modifier_C3, second_key_C3, "] > ", result_C3, + the_ContextKeyNr, + keymapIndexForactionID_2, first_key_C3) + + DataArraySingleStateC3.push("first_modifier_C3") + DataArraySingleStateC3.push(first_modifier_C3) + DataArraySingleStateC3.push(first_key_C3) + DataArraySingleStateC3.push(second_modifier_C3) + DataArraySingleStateC3.push(second_key_C3) + DataArraySingleStateC3.push(result_C3) + } + + if (DataArraySingleStateC3.length > 0) + DataArray.push(DataArraySingleStateC3) + } + } } // ...................................................................................................... // case C4: action + state none + Next ............................................................DONE . @@ -1587,22 +1666,35 @@ export class KeylayoutToKmnConverter { action_id = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] const next_id = this.lookup_3_ActionNone__To__ActionNext(jsonObj, action_id) - const resultC4 = this.lookup_9_TerminatorState__To__TerminatorOutput_str(jsonObj, next_id) + const result_C4 = this.lookup_9_TerminatorState__To__TerminatorOutput_str(jsonObj, next_id) + // all for (let l = 0; l < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i].length; l++) { - const modifier_C4 = this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i][l], isCapsused) - if (resultC4 !== "") + const DataArraySingleStateC4: string[] = [] + + const first_modifier_C4 = this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i][l], isCapsused) + const first_key_C4 = this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])) + + if (result_C4 !== "") { console.log( "### Key Nr ", jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], - "[ + C4 modifiers->", i, modifier_C4.padEnd(25, " "), "] ", + "[ + C4 modifiers->", i, first_modifier_C4.padEnd(25, " "), "] ", this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])).padEnd(8, " "), "> ", - resultC4, + result_C4, " [", action_id, next_id, "]") + + DataArraySingleStateC4.push("first_modifier_C4") + DataArraySingleStateC4.push(first_modifier_C4) + DataArraySingleStateC4.push(first_key_C4) + DataArraySingleStateC4.push(result_C4) + } + if (DataArraySingleStateC4.length > 0) + DataArray.push(DataArraySingleStateC4) } } @@ -1610,7 +1702,13 @@ export class KeylayoutToKmnConverter { console.log("ERROR : some entries are not available") } } - return data_ukelele + + // console.log("DataArray", DataArray) + + + data_ukelele.ArrayOf_processed_RuleDataStr = DataArray + + return data_ukelele.ArrayOf_processed_RuleDataStr } /*public lookup_1_KeymapCode__To__keyMapAction(data: any, search: string): string { @@ -1692,7 +1790,7 @@ export class KeylayoutToKmnConverter { } return new TextEncoder().encode("") } - public lookup_9_TerminatorState__To__TerminatorOutput_str(data: any, search: string): String { + public lookup_9_TerminatorState__To__TerminatorOutput_str(data: any, search: string): string { let OutputValue = "" for (let jj = 0; jj < data.keyboard.terminators.when.length; jj++) { if (data.keyboard.terminators.when[jj]['@_state'] === search) { @@ -1757,7 +1855,22 @@ export class KeylayoutToKmnConverter { } return "" } + public lookup_14_ActionName__To__MapIndex(data: any, search: string): number[][] { + const mapIndexArray_max: number[][] = [] + for (let kk = 0; kk < data.keyboard.keyMapSet[0].keyMap.length; kk++) { + for (let jj = 0; jj < data.keyboard.keyMapSet[0].keyMap[kk].key.length; jj++) { + const mapIndexArrayperKey: number[] = [] + if (data.keyboard.keyMapSet[0].keyMap[kk].key[jj]['@_action'] === search) { + mapIndexArrayperKey.push(data.keyboard.keyMapSet[0].keyMap[kk].key[jj]['@_code']) + mapIndexArrayperKey.push(kk) + } + if (mapIndexArrayperKey.length > 0) + mapIndexArray_max.push(mapIndexArrayperKey) + } + } + return mapIndexArray_max + } //___________________ /* ?? check:*/ public get_Terminator_Output_from_Next(data: any, valSearch: any, at_In: any, at_Out: any): any { const returnvalue = "XX" @@ -2111,7 +2224,6 @@ export class KeylayoutToKmnConverter { // TODO finish all entries public map_UkeleleKC_To_VK(pos: number): string { // ukelele KC --> // VK_US - if (pos === 0x0A) return "K_BKQUOTE" /* ^ */ if (pos === 0x12) return "K_1" /* 1 */ if (pos === 0x13) return "K_2" /* 2 */ From 0ae6314f6b7cf5fc180d544da1304262a86bca61 Mon Sep 17 00:00:00 2001 From: Sabine Date: Fri, 13 Dec 2024 15:06:31 +0100 Subject: [PATCH 030/251] feat(developer): kmc-convert tidy up --- .../keylayout-to-kmn-converter.ts | 1413 ++++------------- 1 file changed, 268 insertions(+), 1145 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 551d14c246b..87288b93af4 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -8,47 +8,47 @@ import { ConverterToKmnArtifacts } from "../converter-artifacts.js"; /*import { util } from '@keymanapp/common-types'; //_S2 import boxXmlArray = util.boxXmlArray;*/ +{ + // TODO keylayout->kmn + // OK modifiers: The identifier of the element to use for this range of hardware keyboard types. + // OK defaultIndex: The table number to use for modifier key combinations which are not explicitly specified by any element within the . + // write read, convert, write + // tests for 3 functions read write convert + // add data to object + // Use filter functions + // action/output:use filter etc to shorten func + // deadkeyables:use filter etc to shorten func + // dk-> for all action:use filter etc to shorten func + // remove unneccessary data from dataObject + // rename symbols + // OK remove part using kmn_key_Name1 + // OK remove unnecceaasry map_UkeleleKC_To_kmn_Key_Name_Array_Position_n etc + // OK loop throught ANSI, JIS- at moment only use [keyMapSet_count] (keyMapSet_count=0) + // OK remove funcs at teh end + // import { makePathToFixture } from '../../test/helpers/index.js'; + // OK Mapping 0->30 or 0->K_A-> missing entries in mapping + // OK Replace any-types + // Several steps action-> action-> action->character ( not only action->character) + // TODO waht about using actions twice in a row??? + // Usable for all keylayout files + // Return conditions + // Use callbacks as for writeFileSync + // Tests throws + // Conditions NCAPS,OPT;... + // TODO move func outside of class + // Functions as object methods? + // objects contain only used stuff READ in: -- out: only read arrays / CONVERT in: only read arrays out: return only to write arrays + // Use catch blocks for file read + // read: answer : + [K_A] > 'a' is OK / TODO which format to use in output ? + [K_A] > 'a' (character code) or + [K_A] > U+0061 (virt Keycode) + // read TODO which stores? + // one entry vs several entry in tags + // false arrangement of tags + // no added NCAPS when first modifier in modifierMap does not contain "caps" or"caps?" + // use length to clear array instead of defining evetry time new (modifierMap_ONE_InKeymapSelect.length=0 + // naming of for-loop var i,j,k?... + // warning if contrADICTING RULES E:G: [ 'modifier_C0', 'SHIFT NCAPS', 'K_C', 'c', '0', '1' ], vs [ 'modifier_C0', 'SHIFT NCAPS', 'K_C', 'C', '1', '0' ], -// TODO keylayout->kmn -// OK modifiers: The identifier of the element to use for this range of hardware keyboard types. -// OK defaultIndex: The table number to use for modifier key combinations which are not explicitly specified by any element within the . -// write read, convert, write -// tests for 3 functions read write convert -// add data to object -// Use filter functions -// action/output:use filter etc to shorten func -// deadkeyables:use filter etc to shorten func -// dk-> for all action:use filter etc to shorten func -// remove unneccessary data from dataObject -// rename symbols -// OK remove part using kmn_key_Name1 -// OK remove unnecceaasry map_UkeleleKC_To_kmn_Key_Name_Array_Position_n etc -// OK loop throught ANSI, JIS- at moment only use [keyMapSet_count] (keyMapSet_count=0) -// OK remove funcs at teh end -// import { makePathToFixture } from '../../test/helpers/index.js'; -// OK Mapping 0->30 or 0->K_A-> missing entries in mapping -// OK Replace any-types -// Several steps action-> action-> action->character ( not only action->character) -// TODO waht about using actions twice in a row??? -// Usable for all keylayout files -// Return conditions -// Use callbacks as for writeFileSync -// Tests throws -// Conditions NCAPS,OPT;... -// TODO move func outside of class -// Functions as object methods? -// objects contain only used stuff READ in: -- out: only read arrays / CONVERT in: only read arrays out: return only to write arrays -// Use catch blocks for file read -// read: answer : + [K_A] > 'a' is OK / TODO which format to use in output ? + [K_A] > 'a' (character code) or + [K_A] > U+0061 (virt Keycode) -// read TODO which stores? -// one entry vs several entry in tags -// false arrangement of tags -// no added NCAPS when first modifier in modifierMap does not contain "caps" or"caps?" -// use length to clear array instead of defining evetry time new (modifierMap_ONE_InKeymapSelect.length=0 -// naming of for-loop var i,j,k?... -// warning if contrADICTING RULES E:G: [ 'modifier_C0', 'SHIFT NCAPS', 'K_C', 'c', '0', '1' ], vs [ 'modifier_C0', 'SHIFT NCAPS', 'K_C', 'C', '1', '0' ], - - +} import { XMLParser } from 'fast-xml-parser'; // for reading a file import { readFileSync } from 'fs'; @@ -56,7 +56,7 @@ import { readFileSync } from 'fs'; //import * as fs from 'fs'; // what is this/do I need it? - either import all or seperately like above - +// todo use from elsewhere function boxXmlArray_S(o: any, x: string): void { if (typeof o == 'object' && !Array.isArray(o[x])) { if (o[x] === null || o[x] === undefined) { @@ -122,695 +122,73 @@ export interface convert_object { ArrayOf_Element_Layouts: string[], // needed?? I think no ArrayOf_Element_KeyOutput: Uint8Array[][], ArrayOf_Element_KeyAction: Uint8Array[][], - ArrayOf_Element_ALL_ModifierMaps: string[], - ArrayOf_Element_ModifierMaps_ALLKeyMapSelect: string[][], - ArrayOf_Element_Terminators: Uint8Array[] // add terminators ( ^,´,`) - ArrayOf_processed_VK_from_keylayout: (string | number)[][], - ArrayOf_processed_dk: string[][], // add dk-mapping ( dk1 <-> '^' ) - ArrayOf_processed_deadkeyables: string[][], // add char that can be modified with dk ( a,e,i,o,u) - ArrayOf_processed_deadkeyedChar: string[][], // add modified keys ( â,ê,î,ô,û) - ArrayOf_processed_RuleData: Uint8Array[][] // add modified keys ( â,ê,î,ô,û) - ArrayOf_processed_RuleDataStr: String[][] // add modified keys ( â,ê,î,ô,û) -}; - - -export class KeylayoutToKmnConverter { - static readonly INPUT_FILE_EXTENSION = '.keylayout'; - static readonly OUTPUT_FILE_EXTENSION = '.kmn'; - - // TODO use callbacks - //constructor(/*private*/ _callbacks: CompilerCallbacks, /*private*/ _options: CompilerOptions) { - constructor(private callbacks: CompilerCallbacks, options: CompilerOptions) { - // TODO: if these are needed, uncomment /*private*/ and remove _, and they will then - // be available as class properties - } - - /** - * @brief member function to run read/convert/write - * @param inputFilename the ukelele .keylayout-file to be converted - * @param outputFilename the resulting keyman .kmn-file - * @return - */ - async run(inputFilename: string, outputFilename: string): Promise { - - if (!inputFilename || !outputFilename) { - throw new Error('Invalid parameters'); - } - - console.log(' _S2 first READ file ........................................in:', inputFilename); - const inArray: convert_object = this.read_old(inputFilename) - - if (!inArray) { - return null; - } - - console.log(' _S2 then CONVERT ........................................'); - const outArray: convert_object = await this.convert(inArray); - - if (!outArray) { - return null; - } - - console.log(' _S2 then WRITE to kmn .....................................'); - - const out = this.write(outArray) - if (!out) { - return null; - } - - // TODO throws - console.log(';;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; FINISHED OK ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;'); - throw new Error('Not finished yet'); - } - - /** - * @brief take filename, open and read data from .keylayout-file and store in several arrays of the data object - * member function to read filename ( a .keylayout-file) and write contents into Uint8Array keys_all_Layers - * @param filename the ukelele .keylayout-file to be converted - * @return in case of success Uint8Array keys_all_Layers; else null - */ - public read(filename: string): convert_object { - - console.log("inputFilename read", filename) - const options = { - ignoreAttributes: false, - attributeNamePrefix: '@_' // to access the attribute - }; - - - console.log("xmlFile_name", (process.cwd() + "\\data" + filename.substring(filename.lastIndexOf("\\"))).replace(" ", "")) - //const xmlFile = readFileSync(`${process.cwd()}/data/MySample.keylayout`, 'utf8') - const xmlFile = readFileSync((process.cwd() + "\\data" + filename.substring(filename.lastIndexOf("\\"))).replace(" ", ""), 'utf8'); - - // we don`t need file-read with uint8array return - /*const fullPath = (process.cwd() + "\\data" + filename.substring(filename.lastIndexOf("\\"))).replace(" ", "") - const xmlFile1 = this.callbacks.loadFile(fullPath) - console.log("xmlFile1",xmlFile1)*/ - - console.log("layouts_array read ") - const parser = new XMLParser(options); - const jsonObj = parser.parse(xmlFile); // get plain Object - boxArrays_S(jsonObj.keyboard); - - const modifierMap_ALL_KeyMapSelects: string[][] = [] // modifier for each keymapselect - const modifierMap_all_Layers: string[] = [] // array holding all MODIFIER strings e.g. "anyShift caps anyOption" -why not put modifiers into Uint8Array along with values of keys of layer - const keys_output_all_Layers: Uint8Array[][] = [] - const keys_action_all_Layers: Uint8Array[][] = [] // array holding all values with ACTION attribute (needed for finding deadkeys) - const terminators_all_Layers: Uint8Array[] = [] // array holding all DEADKEYS for each mod state â, ê, ,.... - const duplicate_layouts_array: string[] = [] // array holding the layouts e.g. ANSI or JIS // needed?? I think no - const deadkeyedChars_all_Layers: string[][] = [] // array holding all DEADKEYS for each mod state â, ê, ,.... - const kmn_Rules_AllLayers: Uint8Array[][] = [] - const kmn_Rules_AllLayersStr: string[][] = [] - let dk_pairs_all_Layers: string[][] = [] // add dk-mapping ( dk1 <-> '^' ) - - - // fill arrays - // TODO call: get only ANSI - // Do I need to care or is there always ANSI which is always keyMapSet[0] - // if so code can be shortened - // ......................................................... - // LAYOUTS: get all groups like ANSI JIS, remove JIS - // ......................................................... - - // in case we need to find ANSI - for (let i = 0; i < jsonObj.keyboard.layouts.layout.length; i++) { - duplicate_layouts_array[i] = jsonObj.keyboard.layouts.layout[i]['@_mapSet'] - } - - // remove duplicates from array - const layouts_array_both: any[] = duplicate_layouts_array.filter(function (item, pos, self) { - return self.indexOf(item) == pos; - }) - - // use only ANSI - the first element - const layouts_array: any[] = layouts_array_both.filter(function (item, pos, self) { - return self.indexOf(item) == 0; - }) - - // in case there always ANSI which is always keyMapSet[0] - //const layouts_array: string[] = duplicate_layouts_array - const keyMapSet_count = 0 - - //#### end layouts ############################################################################################################################################### - - for (let j = 0; j < jsonObj.keyboard.modifierMap.keyMapSelect.length; j++) { - const modifierMap_ONE_InKeymapSelect: string[] = [] - - for (let k = 0; k < jsonObj.keyboard.modifierMap.keyMapSelect[j].modifier.length; k++) { - modifierMap_all_Layers.push(jsonObj.keyboard.modifierMap.keyMapSelect[j].modifier[k]['@_keys']) - modifierMap_ONE_InKeymapSelect.push(jsonObj.keyboard.modifierMap.keyMapSelect[j].modifier[k]['@_keys']) - } - modifierMap_ALL_KeyMapSelects.push(modifierMap_ONE_InKeymapSelect) - - // create a new array of keys_in_Layer (type Uint8tarray) - const keys_output_One_Layer: Uint8Array[] = [] - const keys_action_One_Layer: Uint8Array[] = [] - - //#### end modifierMap ############################################################################################################################################### - - // ......................................................... - // KEYMAP: get all keys for attribute "output" ( y,c,b,...) - // output type Uint8Array -> string - // ......................................................... - for (let i = 0; i < jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap[j].key.length; i++) { - if (jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap[j].key[i]['@_output'] !== "\0") { - // textencoder converts string -> bytes ( 'A' -> [ 65 ], '☺' -> [ 226, 152, 186 ]) - // textencoder is of Uint8Array(1) for A and Uint8Array(3) for ☺ - keys_output_One_Layer[i] = new TextEncoder().encode(jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap[j].key[i]['@_output']); - } - // ToDo do I need empty fields in keys_output_all_Layers, keys_action_all_Layers - // ......................................................... - // KEYMAP: get all keys for attribute "action" ( ^,a,e,i,...) - // action type Uint8Array -> string - // ......................................................... - if (jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap[j].key[i]['@_action'] !== "\0") { - keys_action_One_Layer[i] = new TextEncoder().encode(jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap[j].key[i]['@_action']); - } - } - - // ......................................................... - // create array of "action" and array of "output" - keys_output_all_Layers.push(keys_output_One_Layer) // save all @output data ( will be used for conversion, write...) - keys_action_all_Layers.push(keys_action_One_Layer) // save all @action data ( will be used for deadkeys) - //#### end output+action ############################################################################################################################################### - } - - // ......................................................... - // ACTION: create array of "deadkey" / "deadkey names" - // action type string[] -> string[][] - // ......................................................... - const dk_pairs_all_Layers_max: string[][] = [] - // here replace with function to find - // C3 state none + next Nr => deadkeys - console.log("--------------------------------") - - // loop through actions and get the value of attribute "next" (which indicates this is a deadkey) - for (let jj = 0; jj < jsonObj.keyboard.actions.action.length; jj++) { - for (let kk = 0; kk < jsonObj.keyboard.actions.action[jj].when.length; kk++) { - - if (jsonObj.keyboard.actions.action[jj].when[kk]['@_next'] !== undefined) { - const vec1d: string[] = [] - let dk_to_print - - const text_attribute_next = jsonObj.keyboard.actions.action[jj].when[kk]['@_next'] - - // loop through terminators and get output of that next state - for (let n = 0; n < jsonObj.keyboard.terminators.when.length; n++) { - if (jsonObj.keyboard.terminators.when[n]['@_state'] === text_attribute_next) - dk_to_print = jsonObj.keyboard.terminators.when[n]['@_output'] - } - - vec1d.push(text_attribute_next) - vec1d.push(dk_to_print) - vec1d.push(jsonObj.keyboard.actions.action[jj]['@_id']) // todo remove later - dk_pairs_all_Layers_max.push(vec1d) - } - } - } - dk_pairs_all_Layers = dk_pairs_all_Layers_max.filter(function (item, pos, self) { - return self.indexOf(item) == pos; - }) - console.log("dk_pairs_all_Layers", dk_pairs_all_Layers) - const dk: string[] = []; - - // ......................................................... - // ACTION: create array of "deadkeyables_all_Layers" - TODO can i use shorter function? - // deadkeyables_one type Uint8Array -> string[][] - // ......................................................... - const deadkeyables_all_Layers: string[][] = [] - const action_name = "" - // needed? we just want ANSI = the first one - for (let j = 0; j < jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap.length; j++) { - const deadkeyables_one: string[] = [] - // loop through all keys of ANSI 109 - /*for (let i = 0; i < jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap[0].key.length; i++) { - - let dk_char - // find output in action id 20 - for (let jj = 0; jj < jsonObj.keyboard.actions.action.length; jj++) { - - // find the action ID which was specified in keymap->key->action e.g. a19 - action_name = new TextDecoder().decode(keys_action_all_Layers[j][i]) - - if (action_name !== "") { - // find action id in actions->action e.g. a19 - if (jsonObj.keyboard.actions.action[jj]['@_id'] === action_name) { - - //a85 - - // 4 cases: - // C1 state none + output => - // C2 state Nr + output => - // OK C3 state none + next Nr => deadkeys see above - // C4 state Nr + next Nr => loop deadkeyables - - - const mytestVar = this.get_Terminator_Output_from_Next(jsonObj.keyboard, "a16", '@_state', '@_output') - console.log("mytestVar", mytestVar) - - if (jsonObj.keyboard.actions.action[jj].when[0]['@_state'] === "none") { - dk_char = jsonObj.keyboard.actions.action[jj].when[0]['@_output'] - console.log("++++++++++++++++++++++dk_char", j, i, jj, "action_name", action_name, - jsonObj.keyboard.actions.action[jj].when[0], "===>", dk_char, "mytestVar", mytestVar) - - // if @_next instead of @_output - // loop again - // and again... again...( -> recursive func!!) - } - } - } - } - - // fills correct entries into modifier 1-3 then false ( because of no action any more) - - //const resulting_character = new TextDecoder().decode(keys_action_all_Layers[j][i]) - const resulting_character = dk_char - - if (resulting_character !== "") - deadkeyables_one.push(resulting_character) - } -*/ - - - - - - - - for (let k = 0; k < dk_pairs_all_Layers.length; k++) { - dk.push(dk_pairs_all_Layers[k][1]) - } - - if (deadkeyables_one.length !== 0) { - deadkeyables_all_Layers.push(deadkeyables_one) - } - } - - - console.log("ction_name", action_name) - //console.log("deadkeyables_all_Layers before",deadkeyables_all_Layers) - for (let j = 0; j < deadkeyables_all_Layers.length; j++) { - // filter out dk -> plain deadkeyables_all_Layers ( a,^, e,i,´,u => a,e,i,u) - // return all that don`t find ^,´, ` - deadkeyables_all_Layers[j] = deadkeyables_all_Layers[j].filter(function (el) { - return dk.indexOf(el) < 0; - }); - - } - //console.log("deadkeyables_all_Layers after", deadkeyables_all_Layers) - - //double not needed??? - // ......................................................... - // TERMINATOR: create array of "terminators" - TODO can i use shorter function? what element of terminators do i need - // terminators when state type Uint8Array[] - // ......................................................... - for (let i = 0; i < jsonObj.keyboard.terminators.when.length; i++) { - terminators_all_Layers[i] = jsonObj.keyboard.terminators.when[i] - } - - // ......................................................... - // TODO can i use shorter function? -> yes use terminators, filter, map or reduce - - // this addresses state+output and none+output - // but not state+next or none+next - - // loop through all dk, key-actions and find @_action - // find this value in - // in their 'when' find output for dk - // for all 'action' at keys paragraph - - - for (let j = 0; j < dk_pairs_all_Layers.length; j++) { - - const deadkeys_One_dk: string[] = [] - // find in action e.g. - for (let k = 0; k < keys_action_all_Layers[j].length; k++) { - - const action_from_keys_prargraph = new TextDecoder().decode(keys_action_all_Layers[j][k]) - if (action_from_keys_prargraph !== "") { - // find the same id (e.g. ) in the actions-paragraph - for (let l = 0; l < jsonObj.keyboard.actions.action.length; l++) { - - if (jsonObj.keyboard.actions.action[l]['@_id'] === action_from_keys_prargraph) { - // loop through when until dk name (e.g. dk s0) - for (let m = 0; m < jsonObj.keyboard.actions.action[l].when.length; m++) { - - // and get their @_output - if (jsonObj.keyboard.actions.action[l].when[m]['@_state'] === dk_pairs_all_Layers[j][0]) { - // todo push only if @output is found. if next is found: get value from terminators - //if (typeof jsonObj.keyboard.actions.action[l].when[m]['@_output'].property !== 'undefined') - deadkeys_One_dk.push(jsonObj.keyboard.actions.action[l].when[m]['@_output']) - //else - //console.log(deadkeys_One_dk, "§§§§§§ PROP UNDEFINED", j, "-", k, "-", l, "-", m, "-", dk_pairs_all_Layers[j][0], jsonObj.keyboard.actions.action[l].when[m].property) - } - } - } - } - } - } - // console.log("deadkeys_One_dk", deadkeys_One_dk) - deadkeyedChars_all_Layers.push(deadkeys_One_dk) - - //console.log("deadkeyedChars_all_Layers", deadkeyedChars_all_Layers) - } - - - const vk: (string | number)[][] = [] - // TODO remove unneccassary elements - const DataObject: convert_object = { - name: "Ukelele-kmn", // needed?? remove - ArrayOf_Element_Layouts: layouts_array, // needed?? I think no - ArrayOf_Element_KeyOutput: keys_output_all_Layers, - ArrayOf_Element_KeyAction: keys_action_all_Layers, - ArrayOf_Element_ALL_ModifierMaps: modifierMap_all_Layers, // all 18 modifiers in 1 array - ArrayOf_Element_ModifierMaps_ALLKeyMapSelect: modifierMap_ALL_KeyMapSelects, // 18 modifiers in 8 KeyMapSelect(behaviors) - ArrayOf_Element_Terminators: terminators_all_Layers, // add terminators ( ^,´,`) - ArrayOf_processed_VK_from_keylayout: vk, - ArrayOf_processed_dk: dk_pairs_all_Layers, // add dk-mapping ( dk1 <-> '^' ) - - ArrayOf_processed_deadkeyables: deadkeyables_all_Layers, // add char that can be modified with dk ( a,e,i,o,u) - ArrayOf_processed_deadkeyedChar: deadkeyedChars_all_Layers, // add modified keys ( â,ê,î,ô,û) - ArrayOf_processed_RuleData: kmn_Rules_AllLayers, - ArrayOf_processed_RuleDataStr: kmn_Rules_AllLayersStr - }; - - // TODO review condition - return DataObject - //return ((keys_output_all_Layers.length === nrOfStates + 5) && keys_output_all_Layers[0].length === nrOfKeys_inLayer) ? keys_output_all_Layers : null; - } - - public read_old(filename: string): convert_object { - - console.log("inputFilename read", filename) - const options = { - ignoreAttributes: false, - attributeNamePrefix: '@_' // to access the attribute - }; - - - console.log("xmlFile_name", (process.cwd() + "\\data" + filename.substring(filename.lastIndexOf("\\"))).replace(" ", "")) - //const xmlFile = readFileSync(`${process.cwd()}/data/MySample.keylayout`, 'utf8') - const xmlFile = readFileSync((process.cwd() + "\\data" + filename.substring(filename.lastIndexOf("\\"))).replace(" ", ""), 'utf8'); - - // we don`t need file-read with uint8array return - /*const fullPath = (process.cwd() + "\\data" + filename.substring(filename.lastIndexOf("\\"))).replace(" ", "") - const xmlFile1 = this.callbacks.loadFile(fullPath) - console.log("xmlFile1",xmlFile1)*/ - - - console.log("layouts_array read ") - const parser = new XMLParser(options); - const jsonObj = parser.parse(xmlFile); // get plain Object - const modifierMap_ALL_KeyMapSelects: string[][] = [] // modifier for each keymapselect - const modifierMap_all_Layers: string[] = [] // array holding all MODIFIER strings e.g. "anyShift caps anyOption" -why not put modifiers into Uint8Array along with values of keys of layer - const keys_output_all_Layers: Uint8Array[][] = [] - const keys_action_all_Layers: Uint8Array[][] = [] // array holding all values with ACTION attribute (needed for finding deadkeys) - const terminators_all_Layers: Uint8Array[] = [] // array holding all DEADKEYS for each mod state â, ê, ,.... - const duplicate_layouts_array: string[] = [] // array holding the layouts e.g. ANSI or JIS // needed?? I think no - const deadkeyedChars_all_Layers: string[][] = [] // array holding all DEADKEYS for each mod state â, ê, ,.... - const kmn_Rules_AllLayers: Uint8Array[][] = [] - const kmn_Rules_AllLayersStr: string[][] = [] - let dk_pairs_all_Layers: string[][] = [] // add dk-mapping ( dk1 <-> '^' ) - - boxArrays_S(jsonObj.keyboard); - - // fill arrays - // TODO call: get only ANSI - // Do I need to care or is there always ANSI which is always keyMapSet[0] - // if so code can be shortened - // ......................................................... - // LAYOUTS: get all groups like ANSI JIS, remove JIS - // ......................................................... - - // in case we need to find ANSI - for (let i = 0; i < jsonObj.keyboard.layouts.layout.length; i++) { - duplicate_layouts_array[i] = jsonObj.keyboard.layouts.layout[i]['@_mapSet'] - } - - // remove duplicates - const layouts_array: any[] = duplicate_layouts_array.filter(function (item, pos, self) { - return self.indexOf(item) == pos; - }) - // remove JIS (if keyMap contains baseMapSet it`s JIS) - for (let i = 0; i < layouts_array.length; i++) { - if (jsonObj.keyboard.keyMapSet[i].keyMap[0]['@_baseMapSet']) - layouts_array.splice(i, 1); - } - // in case there always ANSI which is always keyMapSet[0] - //const layouts_array: string[] = duplicate_layouts_array - const keyMapSet_count = 0 - - //#### end layouts ############################################################################################################################################### - - for (let j = 0; j < jsonObj.keyboard.modifierMap.keyMapSelect.length; j++) { - const modifierMap_ONE_InKeymapSelect: string[] = [] - - for (let k = 0; k < jsonObj.keyboard.modifierMap.keyMapSelect[j].modifier.length; k++) { - modifierMap_all_Layers.push(jsonObj.keyboard.modifierMap.keyMapSelect[j].modifier[k]['@_keys']) - modifierMap_ONE_InKeymapSelect.push(jsonObj.keyboard.modifierMap.keyMapSelect[j].modifier[k]['@_keys']) - } - modifierMap_ALL_KeyMapSelects.push(modifierMap_ONE_InKeymapSelect) - - // create a new array of keys_in_Layer (type Uint8tarray) - const keys_output_One_Layer: Uint8Array[] = [] - const keys_action_One_Layer: Uint8Array[] = [] - - //#### end modifierMap ############################################################################################################################################### - - // ......................................................... - // KEYMAP: get all keys for attribute "output" ( y,c,b,...) - TODO can i use shorter function? - // output type Uint8Array -> string - // ......................................................... - for (let i = 0; i < jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap[j].key.length; i++) { - if (jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap[j].key[i]['@_output'] !== "\0") { - // textencoder converts string -> bytes ( 'A' -> [ 65 ], '☺' -> [ 226, 152, 186 ]) - // textencoder is of Uint8Array(1) for A and Uint8Array(3) for ☺ - keys_output_One_Layer[i] = new TextEncoder().encode(jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap[j].key[i]['@_output']); - } - // ToDo do I need empty fields in keys_output_all_Layers, keys_action_all_Layers - // ......................................................... - // KEYMAP: get all keys for attribute "action" ( ^,a,e,i,...) - TODO can i use shorter function? - // action type Uint8Array -> string - // ......................................................... - if (jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap[j].key[i]['@_action'] !== "\0") { - keys_action_One_Layer[i] = new TextEncoder().encode(jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap[j].key[i]['@_action']); - } - } - - // ......................................................... - // create array of "action" and array of "output" - keys_output_all_Layers.push(keys_output_One_Layer) // save all @output data ( will be used for conversion, write...) - keys_action_all_Layers.push(keys_action_One_Layer) // save all @action data ( will be used for deadkeys) - - - //#### end output+action ############################################################################################################################################### - } - - // ......................................................... - // ACTION: create array of "deadkey" / "deadkey names" - TODO can i use shorter function? - // action type string[] -> string[][] - // ......................................................... - const dk_pairs_all_Layers_max: string[][] = [] - // here replace with function to find - // C3 state none + next Nr => deadkeys - console.log("--------------------------------") - - // loop through actions and get the value of attribute "next" (which indicates this is a deadkey) - for (let jj = 0; jj < jsonObj.keyboard.actions.action.length; jj++) { - for (let kk = 0; kk < jsonObj.keyboard.actions.action[jj].when.length; kk++) { - - if (jsonObj.keyboard.actions.action[jj].when[kk]['@_next'] !== undefined) { - const vec1d: string[] = [] - let dk_to_print - - const text_attribute_next = jsonObj.keyboard.actions.action[jj].when[kk]['@_next'] - - // loop through terminators and get output of that next state - for (let n = 0; n < jsonObj.keyboard.terminators.when.length; n++) { - if (jsonObj.keyboard.terminators.when[n]['@_state'] === text_attribute_next) - dk_to_print = jsonObj.keyboard.terminators.when[n]['@_output'] - } - - vec1d.push(text_attribute_next) - vec1d.push(dk_to_print) - vec1d.push(jsonObj.keyboard.actions.action[jj]['@_id']) // todo remove later - dk_pairs_all_Layers_max.push(vec1d) - } - } - } - dk_pairs_all_Layers = dk_pairs_all_Layers_max.filter(function (item, pos, self) { - return self.indexOf(item) == pos; - }) - console.log("dk_pairs_all_Layers", dk_pairs_all_Layers) - const dk: string[] = []; - - // ......................................................... - // ACTION: create array of "deadkeyables_all_Layers" - TODO can i use shorter function? - // deadkeyables_one type Uint8Array -> string[][] - // ......................................................... - const deadkeyables_all_Layers: string[][] = [] - // needed? we just want ANSI = the first one - for (let j = 0; j < jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap.length; j++) { - const deadkeyables_one: string[] = [] - // loop through all keys of ANSI - for (let i = 0; i < jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap[0].key.length; i++) { - - let dk_char - // find output in action id - for (let jj = 0; jj < jsonObj.keyboard.actions.action.length; jj++) { - - // find the action ID which was specified in keymap->key->action e.g. a19 - const action_name = new TextDecoder().decode(keys_action_all_Layers[j][i]) - - if (action_name !== "") { - //console.log("ction_name",action_name) - // find action id in actions->action e.g. a19 - if (jsonObj.keyboard.actions.action[jj]['@_id'] === action_name) { - - //a85 - - // 4 cases: - // C1 state none + output => - // C2 state Nr + output => - // OK C3 state none + next Nr => deadkeys see above - // C4 state Nr + next Nr => loop deadkeyables - - - /*const mytestVar = this.get_Terminator_Output_from_Next(jsonObj.keyboard, "a16", '@_state', '@_output') - console.log("mytestVar", mytestVar)*/ - - if (jsonObj.keyboard.actions.action[jj].when[0]['@_state'] === "none") { - dk_char = jsonObj.keyboard.actions.action[jj].when[0]['@_output'] - /* console.log("++++++++++++++++++++++dk_char", j, i, jj, "action_name", action_name, - jsonObj.keyboard.actions.action[jj].when[0], "===>", dk_char, "mytestVar", mytestVar)*/ - - // if @_next instead of @_output - // loop again - // and again... again...( -> recursive func!!) - } - } - } - } - // fills correct entries into modifier 1-3 then false ( because of no action any more) - - //const resulting_character = new TextDecoder().decode(keys_action_all_Layers[j][i]) - const resulting_character = dk_char - - if (resulting_character !== "") - deadkeyables_one.push(resulting_character) - } - for (let k = 0; k < dk_pairs_all_Layers.length; k++) { - dk.push(dk_pairs_all_Layers[k][1]) - } - - if (deadkeyables_one.length !== 0) { - deadkeyables_all_Layers.push(deadkeyables_one) - } - } - //console.log("deadkeyables_all_Layers before",deadkeyables_all_Layers) - for (let j = 0; j < deadkeyables_all_Layers.length; j++) { - // filter out dk -> plain deadkeyables_all_Layers ( a,^, e,i,´,u => a,e,i,u) - // return all that don`t find ^,´, ` - deadkeyables_all_Layers[j] = deadkeyables_all_Layers[j].filter(function (el) { - return dk.indexOf(el) < 0; - }); - - } - - //console.log("deadkeyables_all_Layers after", deadkeyables_all_Layers) - - //double??? - // ......................................................... - // TERMINATOR: create array of "terminators" - TODO can i use shorter function? what element of terminators do i need - // terminators when state type Uint8Array[] - // ......................................................... - for (let i = 0; i < jsonObj.keyboard.terminators.when.length; i++) { - terminators_all_Layers[i] = jsonObj.keyboard.terminators.when[i] - } - - // ......................................................... - // TODO can i use shorter function? -> yes use terminators, filter, map or reduce - - // this addresses state+output and none+output - // but not state+next or none+next - - // loop through all dk, key-actions and find @_action - // find this value in - // in their 'when' find output for dk - // for all 'action' at keys paragraph - - // ToDo URTGENT duplicate dk ????? - - for (let j = 0; j < dk_pairs_all_Layers.length; j++) { - //for (let j = 0; j < keys_action_all_Layers.length; j++) { - const deadkeys_One_dk: string[] = [] - // find in action e.g. - for (let k = 0; k < keys_action_all_Layers[j].length; k++) { - - const action_from_keys_prargraph = new TextDecoder().decode(keys_action_all_Layers[j][k]) - if (action_from_keys_prargraph !== "") { - // find the same id (e.g. ) in the actions-paragraph - for (let l = 0; l < jsonObj.keyboard.actions.action.length; l++) { + ArrayOf_Element_ALL_ModifierMaps: string[], + ArrayOf_Element_ModifierMaps_ALLKeyMapSelect: string[][], + ArrayOf_Element_Terminators: Uint8Array[] // add terminators ( ^,´,`) + ArrayOf_processed_VK_from_keylayout: (string | number)[][], + ArrayOf_processed_dk: string[][], // add dk-mapping ( dk1 <-> '^' ) + ArrayOf_processed_deadkeyables: string[][], // add char that can be modified with dk ( a,e,i,o,u) + ArrayOf_processed_deadkeyedChar: string[][], // add modified keys ( â,ê,î,ô,û) + ArrayOf_processed_RuleData: Uint8Array[][] // add modified keys ( â,ê,î,ô,û) +}; - if (jsonObj.keyboard.actions.action[l]['@_id'] === action_from_keys_prargraph) { - // loop through when until dk name (e.g. dk s0) - for (let m = 0; m < jsonObj.keyboard.actions.action[l].when.length; m++) { - // and get their @_output - if (jsonObj.keyboard.actions.action[l].when[m]['@_state'] === dk_pairs_all_Layers[j][0]) { - // todo push only if @output is found. if next is found: get value from terminators - //if (typeof jsonObj.keyboard.actions.action[l].when[m]['@_output'].property !== 'undefined') - deadkeys_One_dk.push(jsonObj.keyboard.actions.action[l].when[m]['@_output']) - //else - //console.log(deadkeys_One_dk, "§§§§§§ PROP UNDEFINED", j, "-", k, "-", l, "-", m, "-", dk_pairs_all_Layers[j][0], jsonObj.keyboard.actions.action[l].when[m].property) - } - } - } - } - } +export class KeylayoutToKmnConverter { + static readonly INPUT_FILE_EXTENSION = '.keylayout'; + static readonly OUTPUT_FILE_EXTENSION = '.kmn'; - } + // TODO use callbacks + //constructor(/*private*/ _callbacks: CompilerCallbacks, /*private*/ _options: CompilerOptions) { + constructor(private callbacks: CompilerCallbacks, options: CompilerOptions) { + // TODO: if these are needed, uncomment /*private*/ and remove _, and they will then + // be available as class properties + } - // console.log("deadkeys_One_dk", deadkeys_One_dk) - deadkeyedChars_all_Layers.push(deadkeys_One_dk) + /** + * @brief member function to run read/convert/write + * @param inputFilename the ukelele .keylayout-file to be converted + * @param outputFilename the resulting keyman .kmn-file + * @return + */ + async run(inputFilename: string, outputFilename: string): Promise { - //console.log("deadkeyedChars_all_Layers", deadkeyedChars_all_Layers) + if (!inputFilename || !outputFilename) { + throw new Error('Invalid parameters'); } + console.log(' _S2 first READ file ........................................in:', inputFilename); + const inArray: convert_object = this.read(inputFilename) - const vk: (string | number)[][] = [] + if (!inArray) { + return null; + } - // TODO remove unneccassary elements - const DataObject: convert_object = { - name: "Ukelele-kmn", // needed?? remove - ArrayOf_Element_Layouts: layouts_array, // needed?? I think no - ArrayOf_Element_KeyOutput: keys_output_all_Layers, - ArrayOf_Element_KeyAction: keys_action_all_Layers, - ArrayOf_Element_ALL_ModifierMaps: modifierMap_all_Layers, // all 18 modifiers in 1 array - ArrayOf_Element_ModifierMaps_ALLKeyMapSelect: modifierMap_ALL_KeyMapSelects, // 18 modifiers in 8 KeyMapSelect(behaviors) - ArrayOf_Element_Terminators: terminators_all_Layers, // add terminators ( ^,´,`) - ArrayOf_processed_VK_from_keylayout: vk, - ArrayOf_processed_dk: dk_pairs_all_Layers, // add dk-mapping ( dk1 <-> '^' ) + console.log(' _S2 then CONVERT ........................................'); + const outArray: convert_object = await this.convert(inArray); - ArrayOf_processed_deadkeyables: deadkeyables_all_Layers, // add char that can be modified with dk ( a,e,i,o,u) - ArrayOf_processed_deadkeyedChar: deadkeyedChars_all_Layers, // add modified keys ( â,ê,î,ô,û) - ArrayOf_processed_RuleData: kmn_Rules_AllLayers, - ArrayOf_processed_RuleDataStr: kmn_Rules_AllLayersStr - }; + if (!outArray) { + return null; + } - const filled_Data = this.collect_Data_From_File(DataObject, jsonObj) + console.log(' _S2 then WRITE to kmn .....................................'); - console.log("filled_Data-len", filled_Data.length) - console.log("filled_Data", filled_Data) + const out = this.write(outArray) + if (!out) { + return null; + } - // TODO review condition - return filled_Data - return DataObject - //return ((keys_output_all_Layers.length === nrOfStates + 5) && keys_output_all_Layers[0].length === nrOfKeys_inLayer) ? keys_output_all_Layers : null; + // TODO throws + console.log(';;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; FINISHED OK ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;'); + throw new Error('Not finished yet'); } - - public read_backup_runableMinimalVersion(filename: string): convert_object { + /** + * @brief take filename, open and read data from .keylayout-file and store in several arrays of the data object + * member function to read filename ( a .keylayout-file) and write contents into Uint8Array keys_all_Layers + * @param filename the ukelele .keylayout-file to be converted + * @return in case of success Uint8Array keys_all_Layers; else null + */ + public read(filename: string): convert_object { console.log("inputFilename read", filename) const options = { @@ -840,7 +218,6 @@ export class KeylayoutToKmnConverter { const duplicate_layouts_array: string[] = [] // array holding the layouts e.g. ANSI or JIS // needed?? I think no const deadkeyedChars_all_Layers: string[][] = [] // array holding all DEADKEYS for each mod state â, ê, ,.... const kmn_Rules_AllLayers: Uint8Array[][] = [] - const kmn_Rules_AllLayersStr: string[][] = [] let dk_pairs_all_Layers: string[][] = [] // add dk-mapping ( dk1 <-> '^' ) boxArrays_S(jsonObj.keyboard); @@ -873,6 +250,9 @@ export class KeylayoutToKmnConverter { //#### end layouts ############################################################################################################################################### + // ......................................................... + // MODIFIER MAP: get behaviours(=MapIndex) and modifiers (shift? leftShift caps? ) + // ......................................................... for (let j = 0; j < jsonObj.keyboard.modifierMap.keyMapSelect.length; j++) { const modifierMap_ONE_InKeymapSelect: string[] = [] @@ -881,17 +261,20 @@ export class KeylayoutToKmnConverter { modifierMap_ONE_InKeymapSelect.push(jsonObj.keyboard.modifierMap.keyMapSelect[j].modifier[k]['@_keys']) } modifierMap_ALL_KeyMapSelects.push(modifierMap_ONE_InKeymapSelect) + } + //#### end modifierMap ############################################################################################################################################### + + for (let j = 0; j < jsonObj.keyboard.modifierMap.keyMapSelect.length; j++) { // create a new array of keys_in_Layer (type Uint8tarray) const keys_output_One_Layer: Uint8Array[] = [] const keys_action_One_Layer: Uint8Array[] = [] - //#### end modifierMap ############################################################################################################################################### - // ......................................................... - // KEYMAP: get all keys for attribute "output" ( y,c,b,...) - TODO can i use shorter function? + // KEYMAP - OUTPUT : get all keys for attribute "output" ( y,c,b,...) - TODO can i use shorter function? // output type Uint8Array -> string // ......................................................... + // loop keys for (let i = 0; i < jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap[j].key.length; i++) { if (jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap[j].key[i]['@_output'] !== "\0") { // textencoder converts string -> bytes ( 'A' -> [ 65 ], '☺' -> [ 226, 152, 186 ]) @@ -900,10 +283,10 @@ export class KeylayoutToKmnConverter { } // ToDo do I need empty fields in keys_output_all_Layers, keys_action_all_Layers // ......................................................... - // KEYMAP: get all keys for attribute "action" ( ^,a,e,i,...) - TODO can i use shorter function? + // KEYMAP - ACTION: get all keys for attribute "action" ( ^,a,e,i,...) - TODO can i use shorter function? // action type Uint8Array -> string // ......................................................... - if (jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap[j].key[i]['@_action'] !== "\0") { + else if (jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap[j].key[i]['@_action'] !== "\0") { keys_action_One_Layer[i] = new TextEncoder().encode(jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap[j].key[i]['@_action']); } } @@ -987,13 +370,10 @@ export class KeylayoutToKmnConverter { // C4 state Nr + next Nr => loop deadkeyables - const mytestVar = this.get_Terminator_Output_from_Next(jsonObj.keyboard, "a16", '@_state', '@_output') - console.log("mytestVar", mytestVar) - if (jsonObj.keyboard.actions.action[jj].when[0]['@_state'] === "none") { dk_char = jsonObj.keyboard.actions.action[jj].when[0]['@_output'] - console.log("++++++++++++++++++++++dk_char", j, i, jj, "action_name", action_name, - jsonObj.keyboard.actions.action[jj].when[0], "===>", dk_char, "mytestVar", mytestVar) + /* console.log("++++++++++++++++++++++dk_char", j, i, jj, "action_name", action_name, + jsonObj.keyboard.actions.action[jj].when[0], "===>", dk_char, "mytestVar", mytestVar)*/ // if @_next instead of @_output // loop again @@ -1002,7 +382,6 @@ export class KeylayoutToKmnConverter { } } } - // fills correct entries into modifier 1-3 then false ( because of no action any more) //const resulting_character = new TextDecoder().decode(keys_action_all_Layers[j][i]) @@ -1011,7 +390,6 @@ export class KeylayoutToKmnConverter { if (resulting_character !== "") deadkeyables_one.push(resulting_character) } - for (let k = 0; k < dk_pairs_all_Layers.length; k++) { dk.push(dk_pairs_all_Layers[k][1]) } @@ -1030,7 +408,7 @@ export class KeylayoutToKmnConverter { } - console.log("deadkeyables_all_Layers after", deadkeyables_all_Layers) + //console.log("deadkeyables_all_Layers after", deadkeyables_all_Layers) //double??? // ......................................................... @@ -1052,9 +430,10 @@ export class KeylayoutToKmnConverter { // in their 'when' find output for dk // for all 'action' at keys paragraph - + // ToDo URTGENT duplicate dk ????? + // todo use lookup functions for (let j = 0; j < dk_pairs_all_Layers.length; j++) { - + //for (let j = 0; j < keys_action_all_Layers.length; j++) { const deadkeys_One_dk: string[] = [] // find in action e.g. for (let k = 0; k < keys_action_all_Layers[j].length; k++) { @@ -1080,11 +459,13 @@ export class KeylayoutToKmnConverter { } } } + } + // console.log("deadkeys_One_dk", deadkeys_One_dk) deadkeyedChars_all_Layers.push(deadkeys_One_dk) - console.log("deadkeyedChars_all_Layers", deadkeyedChars_all_Layers) + //console.log("deadkeyedChars_all_Layers", deadkeyedChars_all_Layers) } @@ -1101,18 +482,25 @@ export class KeylayoutToKmnConverter { ArrayOf_Element_Terminators: terminators_all_Layers, // add terminators ( ^,´,`) ArrayOf_processed_VK_from_keylayout: vk, ArrayOf_processed_dk: dk_pairs_all_Layers, // add dk-mapping ( dk1 <-> '^' ) - ArrayOf_processed_deadkeyables: deadkeyables_all_Layers, // add char that can be modified with dk ( a,e,i,o,u) ArrayOf_processed_deadkeyedChar: deadkeyedChars_all_Layers, // add modified keys ( â,ê,î,ô,û) - ArrayOf_processed_RuleData: kmn_Rules_AllLayers, - ArrayOf_processed_RuleDataStr: kmn_Rules_AllLayersStr + ArrayOf_processed_RuleData: kmn_Rules_AllLayers }; + // Todo ? move to convert? + // move up instead of action/output? + // do i need to return a value? + const rule_Data = this.createRuleData(DataObject, jsonObj) + + console.log("rule_Data-lenU8", rule_Data.ArrayOf_processed_RuleData.length) + console.log("rule_Data_U8", rule_Data.ArrayOf_processed_RuleData) + // TODO review condition - return DataObject + return rule_Data //return ((keys_output_all_Layers.length === nrOfStates + 5) && keys_output_all_Layers[0].length === nrOfKeys_inLayer) ? keys_output_all_Layers : null; } + /** * @brief member function to convert data of .keylayout-file to kmn-file This will convert/rename modifiers, position of Keys and deadkeys and save into an array * @param take data_ukelele and create a mapping from mac Keycodes to key-names and save to data_ukelele object @@ -1120,6 +508,10 @@ export class KeylayoutToKmnConverter { * @return outArray Uint8Array keys_all_Layers, the converted data for kmn-files if all layers have been converted; else null */ public convert(data_ukelele: convert_object): convert_object { + + + + const data_VK_from_keylayout: (string | number)[][] = []; for (let i = 0; i < data_ukelele.ArrayOf_Element_KeyOutput[0].length; i++) { @@ -1183,7 +575,7 @@ export class KeylayoutToKmnConverter { // ************************************************************* // **** write rules ******************************************** // *************************************************************^ - + // todo replace write rules with reading out of rule-array console.log("start write 1") // if caps is used in .keylayout-file we need to add NCAPS in kmn-file let isCAPSused = false @@ -1318,6 +710,18 @@ export class KeylayoutToKmnConverter { } } + + //TODO remove + data += 'NOW MY RULES ********************************\n' + for (let kkk = 0; kkk < data_ukelele.ArrayOf_processed_RuleData.length; kkk++) { + let line: string = "" + for (let lll = 0; lll < data_ukelele.ArrayOf_processed_RuleData[kkk].length; lll++) { + const entry = new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][lll]) + line += " " + entry + " " + } + data += line + '\n' + } + data += '\n' // console.log("start write 5") /*writeFileSync("data/MyResult.kmn", data, { flag: "w" })*/ const data_encoded = new TextEncoder().encode(data) @@ -1333,96 +737,61 @@ export class KeylayoutToKmnConverter { //... helpers ............................................................................................. // TODO move outside of class? - // TODO use UInt8 instead of string - - //public collect_Data_From_File(data_ukelele: convert_object, jsonObj: any): convert_object { - public collect_Data_From_File(data_ukelele: convert_object, jsonObj: any): any { - - /*const DataArray: string[][] = [] - const DataArrayU8: Uint8Array[][] = [] - - - - const testUI8 = "a" - const testUI8_1 = new TextEncoder().encode(testUI8); - - const testUI82 = "ẞ" - const testUI8_12 = new TextEncoder().encode(testUI82); - - const testUI83 = "ሴ" - const testUI8_13 = new TextEncoder().encode(testUI83); - - const arrayString: string[]=[] - const Ui8String: Uint8Array[]=[] - - - Ui8String.push(testUI8_1) - arrayString.push(testUI8,testUI8_1) - - - - console.log("arrayString",arrayString, - "Ui8String",Ui8String - )*/ + // ToDo keep only uint8array-version + // for more info about mapping and cases C0-C4 + // see https://docs.google.com/document/d/1ISjACTA9aUBueTo1AoKnOsI6QR5kXeeD_maI0XUyXqg/edit?tab=t.0 + public createRuleData(data_ukelele: convert_object, jsonObj: any): convert_object { + const DataArray_U8: Uint8Array[][] = [] let action_id let output_id const isCapsused = this.checkIfCapsUsed(data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect) - // loop keys //for (let j = 0; j < jsonObj.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { for (let j = 0; j < 52; j++) { + // loop behaviors for (let i = 0; i < jsonObj.keyboard.keyMapSet[0].keyMap.length; i++) { - let output_count = 0 - let action_count = 0 - let all_count = 0 // ...................................................................................................... - // case C0: code + output ............................................................................... + // case C0: output ...................................................................................... + // a key is mapped to a character ( code-> output) ...................................................... + // ...............e. g. ...................................................... + // ...................................................................................................... + // in keys at top for code 1 (K_S) take output ("s") [italian copy] + // get modifiers [modifer of Keymap index 0] + // write [modifer of Keymap index 0] + K_S > s // ...................................................................................................... - all_count++ if (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] !== undefined) { - - // ...................................................................................................... - // case C0: output .............................................................................DONE .... - // a key is mapped to a character ( code-> output) ...................................................... - // ...............e. g. ...................................................... - // ...................................................................................................... - // in keys at top for code 1 (K_S) take output ("s") [italian copy] - // get modifiers [modifer of Keymap index 0] - // write [modifer of Keymap index 0] + K_S > s - // ...................................................................................................... - output_count++ output_id = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] + // loop modifiers for (let l = 0; l < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i].length; l++) { - const DataArraySingleStateC0: string[] = [] + const DataArraySingleStateC0_U8: Uint8Array[] = [] if (output_id !== "") { - const first_modifier_C0 = this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i][l], isCapsused) - const result_C0 = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] - const first_key_C0 = this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])) - - console.log("### Key Nr ", - jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], - "[ + C0 modifiers->", i, first_modifier_C0.padEnd(25, " "), "] ", - this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])).padEnd(8, " "), - "> ", - jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output']) - - DataArraySingleStateC0.push("first_modifier_C0") - DataArraySingleStateC0.push(first_modifier_C0) - DataArraySingleStateC0.push(first_key_C0) - DataArraySingleStateC0.push(result_C0) + const first_modifier_C0_U8 = new TextEncoder().encode(this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i][l], isCapsused)); + const result_C0_U8 = new TextEncoder().encode(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output']); + const first_key_C0_U8 = new TextEncoder().encode(this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']))); + + /* console.log("### Key Nr ", + jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], + "[ + C0 modifiers->", i, first_modifier_C0.padEnd(25, " "), "] ", + this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])).padEnd(8, " "), + "> ", + jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'])*/ + + DataArraySingleStateC0_U8.push(new TextEncoder().encode("first_modifier_C0")) + DataArraySingleStateC0_U8.push(first_modifier_C0_U8) + DataArraySingleStateC0_U8.push(first_key_C0_U8) + DataArraySingleStateC0_U8.push(result_C0_U8) } - - if (DataArraySingleStateC0.length > 0) - DataArray.push(DataArraySingleStateC0) + if (DataArraySingleStateC0_U8.length > 0) + DataArray_U8.push(DataArraySingleStateC0_U8) } } @@ -1432,9 +801,9 @@ export class KeylayoutToKmnConverter { else if (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] !== undefined) { // ...................................................................................................... - // case C1: action + state none + output .......................................................DONE .. + // case C1: action + state none + output .............................................................. // a key is mapped to an action and then to an output ................................................... - // code->action->action(none)->action(output) .......................................................... + // code->action->action(none)->action(output) ........................................................... // ...............e. g. a + // write [modifer of Keymap index 0] + K_A > a // ...................................................................................................... - action_count++ - action_id = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] const result_C1 = this.lookup_6_ActionNone__To__ActionOutput(jsonObj, action_id) + const result_C1_U8 = new TextEncoder().encode(this.lookup_6_ActionNone__To__ActionOutput(jsonObj, action_id)) // modifiers for (let l = 0; l < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i].length; l++) { - const DataArraySingleStateC1: any[] = [] + const DataArraySingleStateC1_U8: Uint8Array[] = [] if (result_C1 !== undefined) { - const first_modifier_C1 = this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i][l], isCapsused) - const first_key_C1 = this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])) + const first_modifier_C1_U8 = new TextEncoder().encode(this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i][l], isCapsused)) + const first_key_C1_U8 = new TextEncoder().encode(this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']))) - console.log( + /*console.log( "### Key Nr ", jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], "[ + C1 modifiers->", i, first_modifier_C1.padEnd(25, " "), "] ", this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])).padEnd(8, " "), "> ", - result_C1) + result_C1)*/ - DataArraySingleStateC1.push("first_modifier_C1") - DataArraySingleStateC1.push(first_modifier_C1) - DataArraySingleStateC1.push(first_key_C1) - DataArraySingleStateC1.push(result_C1) + DataArraySingleStateC1_U8.push(new TextEncoder().encode("first_modifier_C1")) + DataArraySingleStateC1_U8.push(first_modifier_C1_U8) + DataArraySingleStateC1_U8.push(first_key_C1_U8) + DataArraySingleStateC1_U8.push(result_C1_U8) } - if (DataArraySingleStateC1.length > 0) - DataArray.push(DataArraySingleStateC1) + if (DataArraySingleStateC1_U8.length > 0) + DataArray_U8.push(DataArraySingleStateC1_U8) } // ...................................................................................................... - // case C2: action + state Nr + output .........................................................DONE .... - // a key is mapped to an action, then to an output+state ................................................ - // code->action->action(none) + state->action(output) ................................................... + // case C2: action + state Nr + output .................................................................. + // a key is mapped to an action, then to an state+output ................................................ + // replace state x with all rules that result in x (action->action(none) + state-> output) ......................................................... // ...............e. g. .................................................... // ...................................................................................................... // in keys at top for code 0 (K_A) take actions id (a9) [italian copy] // get modifiers [modifer of Keymap index 0] - // loop all actions and look for next="2" (state="2" => next="2") (=>a8) + // loop all actions and look for next="2" (state="none" => next="2") (=>action id = a8) // get action id of this row (id = a8) - // look for a8 in keymap-keys action at top - // take code = 25 = K_9 - // get modifiers [modifer of Keymap index 3] (=anyOption) + // look for a8 in keymap-keys action at the top + // take code = 25 and map keycode to VK (VK= K_9) + // get second modifiers [modifer of Keymap index 3] (=anyOption) // [modifer of Keymap index 3] + K_A + K_9 > à - // write anyOption + K_A + K_9 > à + // write: [anyOption + K_A] > dk(dk1) ; dk(dk1) + [second modifiers K_9] > à // ...................................................................................................... let result_C2 + let result_C2_U8 let nextvalArray: string[] = [] // get action id: e.g. id a16 ->id nr 8 @@ -1508,22 +878,28 @@ export class KeylayoutToKmnConverter { if (stateVal !== undefined) { // get output result_C2 = jsonObj.keyboard.actions.action[indexInActions].when[jj]['@_output'] + result_C2_U8 = new TextEncoder().encode(jsonObj.keyboard.actions.action[indexInActions].when[jj]['@_output']) // get all cases which result in state 3 nextvalArray = this.lookup_5_ActionState__To__ActionNext_none(jsonObj, stateVal) // for all modifier combinations for (let l = 0; l < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i].length; l++) { - const DataArraySingleStateC2: string[] = [] + // const DataArraySingleStateC2: string[] = [] + const DataArraySingleStateC2_U8: Uint8Array[] = [] for (let k = 0; k < nextvalArray.length; k++) { if (result_C2 !== undefined) { - const first_modifier_C2 = this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i][l], isCapsused) - const first_Key_C2 = this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])) - const second_Key_C2 = this.map_UkeleleKC_To_VK(Number(this.lookup_11_KeyMapAction__To__KeyMapCode(jsonObj, nextvalArray[k]))) + /* const first_modifier_C2 = this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i][l], isCapsused) + const first_Key_C2 = this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])) + const second_Key_C2 = this.map_UkeleleKC_To_VK(Number(this.lookup_11_KeyMapAction__To__KeyMapCode(jsonObj, nextvalArray[k]))) + */ + const first_modifier_C2_U8 = new TextEncoder().encode(this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i][l], isCapsused)) + const first_Key_C2_U8 = new TextEncoder().encode(this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']))) + const second_Key_C2_U8 = new TextEncoder().encode(this.map_UkeleleKC_To_VK(Number(this.lookup_11_KeyMapAction__To__KeyMapCode(jsonObj, nextvalArray[k])))) - console.log( + /*console.log( " ### Key Nr", "nextvalArray.length", nextvalArray.length, j, @@ -1544,16 +920,17 @@ export class KeylayoutToKmnConverter { this.lookup_11_KeyMapAction__To__KeyMapCode(jsonObj, nextvalArray[k]), " +keymapindex of this", this.lookup_11_KeyMapAction__To__KeyIndex(jsonObj, nextvalArray[k]) - ) + )*/ - DataArraySingleStateC2.push("modifier_C2") - DataArraySingleStateC2.push(first_modifier_C2) - DataArraySingleStateC2.push(first_Key_C2) - DataArraySingleStateC2.push(second_Key_C2)// state = none -> no modifier - DataArraySingleStateC2.push(result_C2) + DataArraySingleStateC2_U8.push(new TextEncoder().encode("first modifier_C2")) + DataArraySingleStateC2_U8.push(first_modifier_C2_U8) + DataArraySingleStateC2_U8.push(first_Key_C2_U8) + DataArraySingleStateC2_U8.push(second_Key_C2_U8)// state = none -> no modifier + DataArraySingleStateC2_U8.push(result_C2_U8) } - if (DataArraySingleStateC2.length > 0) - DataArray.push(DataArraySingleStateC2) + + if (DataArraySingleStateC2_U8.length > 0) + DataArray_U8.push(DataArraySingleStateC2_U8) } } } @@ -1562,35 +939,34 @@ export class KeylayoutToKmnConverter { // ...................................................................................................... // case C3: action + state Nr + Next .................................................................... // ...............e. g. ..................................................... + // replace state x with all rules that result in 14 (action->action(state)->action(next)->terminator(output) ........................................ // ...................................................................................................... {// in keys at top for code 10 (=K_BACKQUOTE) take actions id (a57) [German standard copy] // code 10 = K_BACKQUOTE (or another key 93) // get modifiers [modifer of Keymap index 0] - // goto action id a57 - // goto when 14 - - // loop through all actions to find next="14" ( might find several) - // get actionsId and output (a80 ) - // get modifiers [modifer of Keymap index 3] - // look at top for a80 => code 40 (= K_K) ( this is how we could get to state 14) - // take 20 and look for state = 20 in terminators ( because of "next") + // goto action id a57 and find 14 in + // find all rules that result in 14 (next="14" - there might be several) + // get actionsId and of that rule (a80 ) + // look at top for a80 and find key Code (code 40 = K_K) + // get modifiers Index of that key (code 40) [modifer of Keymap index 3] + // lookup modifier names from modifiers Index + // take 20 ( of next="20") and look for state = 20 in terminators ("next" points to terminators) // get output ("̭") - // [modifer of Keymap index 0] + a57 + +[modifer of Keymap index 3] state14 -> next 20 - // <=>[modifer of Keymap index 0] + K_BACKQUOTE +[modifer of Keymap index 3] K_K -> "̭" + // [first modifier + K_K] > dk(dk1) ; dk(dk1) + [second modifier K_BKQUOTE] > "̭" } // ...................................................................................................... // get a9 in behavior/key action_id = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] const actionIdIndex = this.lookup_10_ActionId__To__ActioIndex(jsonObj, action_id) - const DataArraySingleStateC3: string[] = [] + const DataArraySingleStateC3_U8: Uint8Array[] = [] let value_state let value_next let the_ContextKeyNr - let first_key_C3 + let first_key_C3_U8 let keymapIndexForactionID_2: any[][] // loop all action-when and find state-next-pair @@ -1611,42 +987,47 @@ export class KeylayoutToKmnConverter { // find all occurences of a17 e.g. key 28/3 [ [ '28', 3 ] ] keymapIndexForactionID_2 = this.lookup_14_ActionName__To__MapIndex(jsonObj, String(theContextID)) // get keyname e.g. 28-> K_8 - first_key_C3 = this.map_UkeleleKC_To_VK(Number(the_ContextKeyNr)) + first_key_C3_U8 = new TextEncoder().encode(this.map_UkeleleKC_To_VK(Number(the_ContextKeyNr))) } - const result_C3 = this.lookup_9_TerminatorState__To__TerminatorOutput_str(jsonObj, value_next) + // const result_C3 = this.lookup_9_TerminatorState__To__TerminatorOutput_str(jsonObj, value_next) + const result_C3_U8 = new TextEncoder().encode(this.lookup_9_TerminatorState__To__TerminatorOutput_str(jsonObj, value_next)) for (let l = 0; l < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i].length; l++) { - const second_modifier_C3 = this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i][l], isCapsused) + // const second_modifier_C3 = this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i][l], isCapsused) + const second_modifier_C3_U8 = new TextEncoder().encode(this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i][l], isCapsused)) if (the_ContextKeyNr !== undefined) { const second_key_Nr = Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']) - const second_key_C3 = this.map_UkeleleKC_To_VK(second_key_Nr) + // const second_key_C3 = this.map_UkeleleKC_To_VK(second_key_Nr) + + const second_key_C3_U8 = new TextEncoder().encode(this.map_UkeleleKC_To_VK(second_key_Nr)) for (let kk = 0; kk < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[keymapIndexForactionID_2[0][1]].length; kk++) { - const first_modifier_text_C3 = data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[keymapIndexForactionID_2[0][1]][kk] - const first_modifier_C3 = this.create_kmn_modifier(first_modifier_text_C3, isCapsused) + const first_modifier_text_C3_U8 = data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[keymapIndexForactionID_2[0][1]][kk] + const first_modifier_C3_U8 = new TextEncoder().encode(this.create_kmn_modifier(first_modifier_text_C3_U8, isCapsused)) - console.log(" ### Key Nr", jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], + /*console.log(" ### Key Nr", jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], "[ + C3 modifiers->", i, l, "[", first_modifier_C3, first_key_C3, "]", "> dk(dk1) ######### ", " dk(dk1) + [", second_modifier_C3, second_key_C3, "] > ", result_C3, the_ContextKeyNr, - keymapIndexForactionID_2, first_key_C3) - - DataArraySingleStateC3.push("first_modifier_C3") - DataArraySingleStateC3.push(first_modifier_C3) - DataArraySingleStateC3.push(first_key_C3) - DataArraySingleStateC3.push(second_modifier_C3) - DataArraySingleStateC3.push(second_key_C3) - DataArraySingleStateC3.push(result_C3) + keymapIndexForactionID_2, first_key_C3)*/ + + DataArraySingleStateC3_U8.push(new TextEncoder().encode("first_modifier_C3")) + DataArraySingleStateC3_U8.push(first_modifier_C3_U8) + DataArraySingleStateC3_U8.push(first_key_C3_U8) + DataArraySingleStateC3_U8.push(second_modifier_C3_U8) + DataArraySingleStateC3_U8.push(second_key_C3_U8) + DataArraySingleStateC3_U8.push(result_C3_U8) } - if (DataArraySingleStateC3.length > 0) - DataArray.push(DataArraySingleStateC3) + + if (DataArraySingleStateC3_U8.length > 0) + DataArray_U8.push(DataArraySingleStateC3_U8) } } } @@ -1658,25 +1039,25 @@ export class KeylayoutToKmnConverter { // ...................................................................................................... // in keys for code 32 (K_U) at top find actions id a16 [italian copy] // get modifiers [modifer of Keymap index 3] - // in actions a16 find state "none" and get next (=4) - // in terminators find the state (=4) - // take output ("¨") + // in actions a16 () find state "none" and get next (=4) + // in terminators ( ) find the state (=4) and get output ("¨") // write [modifer of Keymap index 3] + K_U -> "¨" action_id = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] const next_id = this.lookup_3_ActionNone__To__ActionNext(jsonObj, action_id) const result_C4 = this.lookup_9_TerminatorState__To__TerminatorOutput_str(jsonObj, next_id) - // all + const result_C4_U8 = new TextEncoder().encode(this.lookup_9_TerminatorState__To__TerminatorOutput_str(jsonObj, next_id)) + for (let l = 0; l < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i].length; l++) { - const DataArraySingleStateC4: string[] = [] + const DataArraySingleStateC4_U8: Uint8Array[] = [] - const first_modifier_C4 = this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i][l], isCapsused) - const first_key_C4 = this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])) + const first_modifier_C4_U8 = new TextEncoder().encode(this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i][l], isCapsused)) + const first_key_C4_U8 = new TextEncoder().encode(this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']))) if (result_C4 !== "") { - console.log( + /*console.log( "### Key Nr ", jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], "[ + C4 modifiers->", i, first_modifier_C4.padEnd(25, " "), "] ", @@ -1686,15 +1067,15 @@ export class KeylayoutToKmnConverter { " [", action_id, next_id, - "]") + "]")*/ - DataArraySingleStateC4.push("first_modifier_C4") - DataArraySingleStateC4.push(first_modifier_C4) - DataArraySingleStateC4.push(first_key_C4) - DataArraySingleStateC4.push(result_C4) + DataArraySingleStateC4_U8.push(new TextEncoder().encode("first_modifier_C4")) + DataArraySingleStateC4_U8.push(first_modifier_C4_U8) + DataArraySingleStateC4_U8.push(first_key_C4_U8) + DataArraySingleStateC4_U8.push(result_C4_U8) } - if (DataArraySingleStateC4.length > 0) - DataArray.push(DataArraySingleStateC4) + if (DataArraySingleStateC4_U8.length > 0) + DataArray_U8.push(DataArraySingleStateC4_U8) } } @@ -1703,12 +1084,8 @@ export class KeylayoutToKmnConverter { } } - // console.log("DataArray", DataArray) - - - data_ukelele.ArrayOf_processed_RuleDataStr = DataArray - - return data_ukelele.ArrayOf_processed_RuleDataStr + data_ukelele.ArrayOf_processed_RuleData = DataArray_U8 + return data_ukelele } /*public lookup_1_KeymapCode__To__keyMapAction(data: any, search: string): string { @@ -1871,262 +1248,8 @@ export class KeylayoutToKmnConverter { } return mapIndexArray_max } - //___________________ - /* ?? check:*/ public get_Terminator_Output_from_Next(data: any, valSearch: any, at_In: any, at_Out: any): any { - const returnvalue = "XX" - // take jsonObj(data), valSearch, valReturn, at_In, at_Out // valSearch =18 from next=18 - // return valReturn - // do: - // loop (i) through jsonObj-terminator until VAlSearch is found in when-@state - // get i - // return jsonObj-termin[i][@_out] - - // a16: state = "none -> next =3" - - //console.log(" in:", valSearch, "->") - //const found_outputValue = this.get_Next_Output_from_None_and_id(data, valSearch, "none", at_In, at_Out) - - // console.log(" in:", valSearch, "->", found_outputValue) - //const returnvalue = this.get_Terminator_Output_from_Next(data, found_outputValue, at_In, at_Out) - - //console.log("§§§§§§§§§§§ in:", valSearch, "->", found_outputValue, "->", returnvalue) - return returnvalue - } - /* public get_all_next_from_state(data: any, action_idName: string): string[] { - const returnarray: string[] = [] - // e.g. action_idName = 3 - if (action_idName !== "none") { - // loop all action/when - for (let k = 0; k < data.keyboard.actions.action.length; k++) { - for (let j = 0; j < data.keyboard.actions.action[k].when.length; j++) { - // find attribute next === 3 - if (data.keyboard.actions.action[k].when[j]['@_next'] === action_idName) { - returnarray.push(data.keyboard.actions.action[k]['@_id']) - } - } - } - } - return returnarray - } */ - /* public get_Output_Output_from_None_and_id(data: any, actionId: any, valSearch: any): any { - // a16-> id ==a16 ->4 - //todo what if douplicate value?? - let OutputValue = "" - for (let jj = 0; jj < data.keyboard.actions.action.length; jj++) { - if (data.keyboard.actions.action[jj]['@_id'] === actionId) { - for (let kk = 0; kk < data.keyboard.actions.action[jj].when.length; kk++) { - if (data.keyboard.actions.action[jj].when[kk]['@_state'] === "none") { - OutputValue = data.keyboard.actions.action[jj].when[kk]['@_output'] - } - } - } - } - return OutputValue - } */ - /* public get_Output_Next_from_None_and_id(data: any, actionId: any, valSearch: any): any { - // a16-> id ==a16 ->4 - //todo what if douplicate value?? - let OutputValue = "" - - for (let jj = 0; jj < data.keyboard.actions.action.length; jj++) { - if (data.keyboard.actions.action[jj]['@_id'] === actionId) { - for (let kk = 0; kk < data.keyboard.actions.action[jj].when.length; kk++) { - if (data.keyboard.actions.action[jj].when[kk]['@_state'] === "none") - OutputValue = data.keyboard.actions.action[jj].when[kk]['@_next'] - } - } - } - return OutputValue - }*/ - /* public loop_Action_ToFind_index_from_ID_name(data: any, action_idName: string): number { - - for (let k = 0; k < data.keyboard.actions.action.length; k++) { - if (data.keyboard.actions.action[k]['@_id'] === action_idName) - - // console.log("data.actions.action[0]['@_id'] 2",data.keyboard.actions.action[0]['@_id'], k) - return k - } - return 0 - }*/ - /*public get_Next_Output_from_None(data: any, valSearch: any, at_In: any, at_Out: any): any { - - valSearch = "none" - - for (let k = 0; k < data.actions.action.length; k++) { - for (let j = 0; j < data.actions.action[k].when.length; j++) { - if ((data.actions.action[k].when[j]['@_state'] === valSearch && data.actions.action[k].when[j]['@_next'] !== "undefined")) { - const nextValue = data.actions.action[k].when[j]['@_next'] - // console.log("found pair: ", k, j, data.actions.action[k]['@_id'], data.actions.action[k].when[j]['@_state'], "nextValue",nextValue) - return nextValue - } - } - } - return "" - }*/ - /*public get_Next_Output_from_None_and_id(data: any, actionId: any, valSearch: any, at_In: any, at_Out: any): any { - // a16-> id ==a16 ->4 - valSearch = "none" - - let nextValue = "" - for (let jj = 0; jj < data.actions.action.length; jj++) { - if (data.actions.action[jj]['@_id'] === actionId) { - for (let kk = 0; kk < data.actions.action[jj].when.length; kk++) { - nextValue = data.actions.action[jj].when[kk]['@_next'] - } - } - } - return nextValue - }*/ - /*public get_Output_From_Terminator(data: any, actionId: any, valSearch: any): any { - // a16-> id ==a16 ->4 - //todo what if douplicate value?? - let OutputValue = "" - for (let jj = 0; jj < data.keyboard.terminators.when.length; jj++) { - if (data.keyboard.terminators.when[jj]['@_state'] === actionId) { - OutputValue = data.keyboard.terminators.when[jj]['@_output'] - } - } - return OutputValue - }*/ - /*public get_Attribut_follow(data: any, parent: any, child: any, actionId: any, findtag: any, returntag: any, findtagContents: any): any { - - console.log("Input:", - "\nchild", child, - "\nactionId", actionId, - "\nfindtag", findtag, - "\nreturntag", returntag, - "\nfindtagContents", findtagContents, - "\nfdata.child.length", parent + "." + child + ".length", - "\nparent.child[jj]['@_id'] ", parent + "." + child + ".[0]['@_id']", - "\nparent.child[jj].when.length ", parent + "." + child + ".[0].when.length", - "\nparent.child[jj].when[kk][findtag] ", parent + "." + child + ".d[0].when[0]["+findtag+"]" - ) - console.log("Input:" - ) - const parent_child= (parent + "." + child) - // a16-> id ==a16 ->4 - //todo what if douplicate value?? - let OutputValue = "" - for (let jj = 0; jj < parent_child.length; jj++) { - if (parent_child[jj]['@_id'] === actionId) { - for (let kk = 0; kk < parent.child[jj].when.length; kk++) { - if (parent.child[jj].when[kk][findtag] === findtagContents) { - OutputValue = parent.child[jj].when[kk][returntag] - } - } - } - } - return OutputValue - }*/ - /*public get_Terminator_Output_from_Next(data: any, valSearch: any, at_In: any, at_Out: any): any { - - const valReturn = 0 - // take jsonObj(data), valSearch, valReturn, at_In, at_Out // valSearch =18 from next=18 - // return valReturn - // do: - // loop (i) through jsonObj-terminator until VAlSearch is found in when-@state - // get i - // return jsonObj-termin[i][@_out] - - - let nextValue = 0 - let returnvalue =0 - - //for (let k = 0; k < data.actions.length; k++) { - for (let k = 0; k < data.actions.action.length; k++) { - for (let j = 0; j < data.actions.action[k].when.length; j++) { - if ((data.actions.action[k].when[j]['@_state'] === "none" && data.actions.action[k].when[j]['@_next'] !== "undefined")) { - // if ((data.actions.action[k].when[j]['@_state'] === "none" )) { - nextValue = data.actions.action[k].when[j]['@_next'] - // console.log("found pair: ", k, j, data.actions.action[k]['@_id'], data.actions.action[k].when[j]['@_state'], "nextValue",nextValue) - for (let i = 0; i < data.terminators.when.length; i++) { - if (data.terminators.when[i]['@_state'] === nextValue) { - - returnvalue= data.terminators.when[i]['@_output'] - // console.log("terminators pair: ", i, nextValue, data.terminators.when[i]['@_output'], returnvalue) - } - } - } - } - } - return valReturn - }*/ - /* public get_Next_Output_from_Any(data: any, valSearch: any, at_In: any, at_Out: any): any { - - for (let k = 0; k < data.actions.action.length; k++) { - for (let j = 0; j < data.actions.action[k].when.length; j++) { - if ((data.actions.action[k].when[j]['@_state'] === valSearch && data.actions.action[k].when[j]['@_next'] !== "undefined")) { - const nextValue = data.actions.action[k].when[j]['@_next'] - // console.log("found pair: ", k, j, data.actions.action[k]['@_id'], data.actions.action[k].when[j]['@_state'], "nextValue",nextValue) - return nextValue - } - } - } - return "" - } - */ - /* public find_ID_for_Next(data: any, state: string): string { - // a16-> id ==a16 ->4 - //todo what if douplicate value?? - for (let jj = 0; jj < data.keyboard.actions.length; jj++) { - for (let k = 0; k < data.keyboard.actions.action[jj].length; k++) { - if (data.keyboard.actions.action[jj].when[k]['@_next'] !== undefined) - return data.keyboard.actions.action[jj]['@_id'] - } - } - return "" - }*/ - /* public get_Next_Output_from_Any_and_id(data: any, actionId: any, valSearch: any, at_In: any, at_Out: any): any { - - for (let j = 0; j < data.actions.action[actionId].when.length; j++) { - if ((data.actions.action[actionId].when[j]['@_state'] === valSearch && data.actions.action[actionId].when[j]['@_next'] !== "undefined")) { - const nextValue = data.actions.action[actionId].when[j]['@_next'] - // console.log("found pair: ", k, j, data.actions.action[k]['@_id'], data.actions.action[k].when[j]['@_state'], "nextValue",nextValue) - return nextValue - } - } - return "" - } - */ - /* public get_Terminator_Output_from_State(data: any, actionId: any, valSearch: any, at_In: any, at_Out: any): any { - - for (let j = 0; j < data.terminators.when.length; j++) { - if (data.terminators.when[j]['@_state'] === valSearch) { - return data.terminators.when[j]['@_output'] - } - } - return "" - }*/ - /*public getCharacterFromActionName(data_ukelele: convert_object, ArrayOf_Element_KeyActionElement: Uint8Array): any { - //get character from ~ <- 4 <- a9 - //in: [ 97, 49 ] (a9) - // out: ~ - - //[ 97, 49 ]-> (a9) - console.log("ArrayOf_Element_KeyActionElement", ArrayOf_Element_KeyActionElement) - const ArrayOf_Element_KeyActionElement_string = new TextDecoder().decode(ArrayOf_Element_KeyActionElement) - - - if (ArrayOf_Element_KeyActionElement_string !== "") { - console.log("ArrayOf_Element_KeyActionElement_string in func", ArrayOf_Element_KeyActionElement_string) - - for (let jj = 0; jj < data_ukelele.ArrayOf_processed_dk.length; jj++) { - console.log(data_ukelele.ArrayOf_processed_dk[jj][2], "===?", ArrayOf_Element_KeyActionElement_string) - if (data_ukelele.ArrayOf_processed_dk[jj][2] === ArrayOf_Element_KeyActionElement_string) { - console.log("FOUND", data_ukelele.ArrayOf_processed_dk[jj][2]) - return data_ukelele.ArrayOf_processed_dk[jj][1] - } - - } - - return "" - } - - } -*/ - /** * @brief member function to return the unicode value of a character * @param character the value that will converted From a12f5113db62a1c9848847bb12e37870000e3b0e Mon Sep 17 00:00:00 2001 From: Sabine Date: Mon, 16 Dec 2024 14:13:23 +0100 Subject: [PATCH 031/251] feat(developer): kmc-convert pstart rint deadkeyed and deadkeyables --- .../keylayout-to-kmn-converter.ts | 491 +++++++++++++++++- .../test/test-keylayout-to-kmn-converter.ts | 5 +- 2 files changed, 466 insertions(+), 30 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 87288b93af4..c2034cf3bc3 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -47,7 +47,7 @@ import boxXmlArray = util.boxXmlArray;*/ // use length to clear array instead of defining evetry time new (modifierMap_ONE_InKeymapSelect.length=0 // naming of for-loop var i,j,k?... // warning if contrADICTING RULES E:G: [ 'modifier_C0', 'SHIFT NCAPS', 'K_C', 'c', '0', '1' ], vs [ 'modifier_C0', 'SHIFT NCAPS', 'K_C', 'C', '1', '0' ], - + // print NCAPS as the first of the modifiers in create_kmn_modifier } import { XMLParser } from 'fast-xml-parser'; // for reading a file @@ -129,7 +129,8 @@ export interface convert_object { ArrayOf_processed_dk: string[][], // add dk-mapping ( dk1 <-> '^' ) ArrayOf_processed_deadkeyables: string[][], // add char that can be modified with dk ( a,e,i,o,u) ArrayOf_processed_deadkeyedChar: string[][], // add modified keys ( â,ê,î,ô,û) - ArrayOf_processed_RuleData: Uint8Array[][] // add modified keys ( â,ê,î,ô,û) + ArrayOf_processed_RuleData: Uint8Array[][], // add modified keys ( â,ê,î,ô,û) + ArrayOf_processed_dk_U8: Uint8Array[][] }; @@ -219,6 +220,7 @@ export class KeylayoutToKmnConverter { const deadkeyedChars_all_Layers: string[][] = [] // array holding all DEADKEYS for each mod state â, ê, ,.... const kmn_Rules_AllLayers: Uint8Array[][] = [] let dk_pairs_all_Layers: string[][] = [] // add dk-mapping ( dk1 <-> '^' ) + const dk_pairs_all_Layers_U8: Uint8Array[][] = [] // add dk-mapping ( dk1 <-> '^' ) boxArrays_S(jsonObj.keyboard); @@ -484,7 +486,8 @@ export class KeylayoutToKmnConverter { ArrayOf_processed_dk: dk_pairs_all_Layers, // add dk-mapping ( dk1 <-> '^' ) ArrayOf_processed_deadkeyables: deadkeyables_all_Layers, // add char that can be modified with dk ( a,e,i,o,u) ArrayOf_processed_deadkeyedChar: deadkeyedChars_all_Layers, // add modified keys ( â,ê,î,ô,û) - ArrayOf_processed_RuleData: kmn_Rules_AllLayers + ArrayOf_processed_RuleData: kmn_Rules_AllLayers, + ArrayOf_processed_dk_U8: dk_pairs_all_Layers_U8 }; // Todo ? move to convert? @@ -493,7 +496,7 @@ export class KeylayoutToKmnConverter { const rule_Data = this.createRuleData(DataObject, jsonObj) console.log("rule_Data-lenU8", rule_Data.ArrayOf_processed_RuleData.length) - console.log("rule_Data_U8", rule_Data.ArrayOf_processed_RuleData) + //console.log("rule_Data_U8", rule_Data.ArrayOf_processed_RuleData) // TODO review condition return rule_Data @@ -637,8 +640,26 @@ export class KeylayoutToKmnConverter { // ************************************************************* + data += 'NOW MY DEADKEYS : \n' + + /* console.log("start write 3: ", + data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect.length, + data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[1].length, + data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[1][1].length, + data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect + ) + for (let i = 0; i < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect.length; i++) { + for (let j = 0; j < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i].length; j++) { + console.log("Element: ", i, j, + data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i][j], + this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i][j], isCAPSused) + ) + } + }*/ + // old + // all 109 keys with action a9 - for (let i = 0; i < data_ukelele.ArrayOf_Element_KeyAction[0].length; i++) { + for (let i = 0; i < data_ukelele.ArrayOf_Element_KeyAction.length; i++) { // loop through keyMapSelect (8) for (let ii = 0; ii < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect.length; ii++) { //for (let ii = 0; ii < 8; ii++) { @@ -646,7 +667,7 @@ export class KeylayoutToKmnConverter { //for (let j = 0; j < data_ukelele.ArrayOf_Element_KeyAction.length; j++) { // 8 behaviors for (let j = 0; j < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect.length; j++) { - //console.log("start write 3A") + //console.log("start write 3A", i, ii, j) // get the modifier for the layer //const label_modifier = this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ALL_ModifierMaps[j], isCAPSused) @@ -665,7 +686,7 @@ export class KeylayoutToKmnConverter { // realChar) if (resulting_character !== "") { - // console.log("start write 3B+3C", i, ii, j, label_modifier, "---", resulting_character) + console.log("start write 3B+3C", i, ii, j, label_modifier, "---", resulting_character) const VK: (string | number)[][] = data_ukelele.ArrayOf_processed_VK_from_keylayout const vk_label = VK.filter(item => item[0] === data_ukelele.ArrayOf_processed_VK_from_keylayout[i][0]) @@ -673,12 +694,14 @@ export class KeylayoutToKmnConverter { // console.log("start write 3D,data_ukelele.ArrayOf_processed_dk", data_ukelele.ArrayOf_processed_dk) for (let k = 0; k < data_ukelele.ArrayOf_processed_dk.length; k++) { - /* console.log("start write 3E") - console.log("resulting_character", resulting_character, "data_ukelele.ArrayOf_processed_dk[k][1]", data_ukelele.ArrayOf_processed_dk[k][1]) - console.log("data_ukelele.ArrayOf_processed_dk is",data_ukelele.ArrayOf_processed_dk) - console.log("resulting_characte, data_ukelele.ArrayOf_processed_dk is",resulting_character, data_ukelele.ArrayOf_processed_dk[k][2])*/ + console.log("start write 3E") + console.log("resulting_character", resulting_character, "data_ukelele.ArrayOf_processed_dk[k][1]", data_ukelele.ArrayOf_processed_dk[k][1]) + console.log("data_ukelele.ArrayOf_processed_dk is", data_ukelele.ArrayOf_processed_dk) + console.log("resulting_characte, data_ukelele.ArrayOf_processed_dk is", resulting_character, data_ukelele.ArrayOf_processed_dk[k][2]) if ((resulting_character !== "") && (resulting_character === data_ukelele.ArrayOf_processed_dk[k][2])) { data += '[' + (label_modifier + ' ' + vk_label[0][1]).trim() + '] ' + "> dk(" + this.getHexFromChar(data_ukelele.ArrayOf_processed_dk[k][1]) + ") " + '\n' + console.log("start write 3D", data) + } } } @@ -687,6 +710,117 @@ export class KeylayoutToKmnConverter { } } + + // all 109 keys with action a9 + /* for (let i = 0; i < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect.length; i++) { + // loop through keyMapSelect (8) + for (let ii = 0; ii < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i].length; ii++) { + //for (let ii = 0; ii < 8; ii++) { + // loop through modifiers + //for (let j = 0; j < data_ukelele.ArrayOf_Element_KeyAction.length; j++) { + // 8 behaviors + // for (let j = 0; j < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i][ii].length; j++) { + if (data_ukelele.ArrayOf_Element_ALL_ModifierMaps[i][ii] !== "") { + + console.log("start write 3A", i,ii,data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i][ii] ) + + const label_modifier = this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ALL_ModifierMaps[i][ii], isCAPSused) + console.log("label_modifier", label_modifier ) + // get the modifier for the layer + //const label_modifier = this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ALL_ModifierMaps[j], isCAPSused) + const label_modifier = this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ALL_ModifierMaps[i][ii], isCAPSused) + + // get the character from keymap-section of .keylayout-file that will be written as result in kmn-file + //const resulting_character = new TextDecoder().decode(data_ukelele.ArrayOf_Element_KeyAction[j][i]) + // wrong since it attempts to convert a9 and not 4 ( the termínator id ) + const resulting_character = new TextDecoder().decode(data_ukelele.ArrayOf_Element_KeyAction[i][ii]) + + // therefore get character from ~ <- 4 <- a9 + //const realChar = this.getCharacterFromActionName(data_ukelele, data_ukelele.ArrayOf_Element_KeyAction[ii][i]) + //console.log("realChar", realChar,i,ii,j ) + // console.log("data_ukelele.ArrayOf_Element_KeyAction[ii][i],", + // data_ukelele.ArrayOf_Element_KeyAction[ii][i], + // realChar) + + if (resulting_character !== "") { + console.log("start write 3B+3C", i, ii, label_modifier, "---", resulting_character) + + const VK: (string | number)[][] = data_ukelele.ArrayOf_processed_VK_from_keylayout + const vk_label = VK.filter(item => item[0] === data_ukelele.ArrayOf_processed_VK_from_keylayout[i][0]) + // console.log("VK", VK, "vk_label", vk_label) + + // console.log("start write 3D,data_ukelele.ArrayOf_processed_dk", data_ukelele.ArrayOf_processed_dk) + for (let k = 0; k < data_ukelele.ArrayOf_processed_dk.length; k++) { + // console.log("start write 3E") + // console.log("resulting_character", resulting_character, "data_ukelele.ArrayOf_processed_dk[k][1]", data_ukelele.ArrayOf_processed_dk[k][1]) + // console.log("data_ukelele.ArrayOf_processed_dk is",data_ukelele.ArrayOf_processed_dk) + // console.log("resulting_characte, data_ukelele.ArrayOf_processed_dk is",resulting_character, data_ukelele.ArrayOf_processed_dk[k][2]) + if ((resulting_character !== "") && (resulting_character === data_ukelele.ArrayOf_processed_dk[k][2])) { + data += '[' + (label_modifier + ' ' + vk_label[0][1]).trim() + '] ' + "> dk(" + this.getHexFromChar(data_ukelele.ArrayOf_processed_dk[k][1]) + ") " + '\n' + console.log("start write 3D", data) + + } + } + // } + + } + + } + }}*/ + + /* old + // all 109 keys with action a9 + for (let i = 0; i < data_ukelele.ArrayOf_Element_KeyAction[0].length; i++) { + // loop through keyMapSelect (8) + for (let ii = 0; ii < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect.length; ii++) { + //for (let ii = 0; ii < 8; ii++) { + // loop through modifiers + //for (let j = 0; j < data_ukelele.ArrayOf_Element_KeyAction.length; j++) { + // 8 behaviors + for (let j = 0; j < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect.length; j++) { + console.log("start write 3A", i,ii,j) + + // get the modifier for the layer + //const label_modifier = this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ALL_ModifierMaps[j], isCAPSused) + const label_modifier = this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ALL_ModifierMaps[j], isCAPSused) + + // get the character from keymap-section of .keylayout-file that will be written as result in kmn-file + //const resulting_character = new TextDecoder().decode(data_ukelele.ArrayOf_Element_KeyAction[j][i]) + // wrong since it attempts to convert a9 and not 4 ( the termínator id ) + const resulting_character = new TextDecoder().decode(data_ukelele.ArrayOf_Element_KeyAction[ii][i]) + + // therefore get character from ~ <- 4 <- a9 + //const realChar = this.getCharacterFromActionName(data_ukelele, data_ukelele.ArrayOf_Element_KeyAction[ii][i]) + //console.log("realChar", realChar,i,ii,j ) + // console.log("data_ukelele.ArrayOf_Element_KeyAction[ii][i],", + // data_ukelele.ArrayOf_Element_KeyAction[ii][i], + // realChar) + + if (resulting_character !== "") { + console.log("start write 3B+3C", i, ii, j, label_modifier, "---", resulting_character) + + const VK: (string | number)[][] = data_ukelele.ArrayOf_processed_VK_from_keylayout + const vk_label = VK.filter(item => item[0] === data_ukelele.ArrayOf_processed_VK_from_keylayout[i][0]) + // console.log("VK", VK, "vk_label", vk_label) + + // console.log("start write 3D,data_ukelele.ArrayOf_processed_dk", data_ukelele.ArrayOf_processed_dk) + for (let k = 0; k < data_ukelele.ArrayOf_processed_dk.length; k++) { + /* console.log("start write 3E") + console.log("resulting_character", resulting_character, "data_ukelele.ArrayOf_processed_dk[k][1]", data_ukelele.ArrayOf_processed_dk[k][1]) + console.log("data_ukelele.ArrayOf_processed_dk is",data_ukelele.ArrayOf_processed_dk) + console.log("resulting_characte, data_ukelele.ArrayOf_processed_dk is",resulting_character, data_ukelele.ArrayOf_processed_dk[k][2])*/ + /* if ((resulting_character !== "") && (resulting_character === data_ukelele.ArrayOf_processed_dk[k][2])) { + data += '[' + (label_modifier + ' ' + vk_label[0][1]).trim() + '] ' + "> dk(" + this.getHexFromChar(data_ukelele.ArrayOf_processed_dk[k][1]) + ") " + '\n' + console.log("start write 3D", data) + + } + } + } + } + + } + } +*/ // console.log("start write 4") data += "\n" data += "match > use(deadkeys)\n\n" @@ -704,6 +838,9 @@ export class KeylayoutToKmnConverter { for (let i = 0; i < data_ukelele.ArrayOf_processed_deadkeyables.length; i++) { if (data_ukelele.ArrayOf_processed_deadkeyedChar[i] !== undefined) { + data += "store(dkf" + this.getHexFromChar(data_ukelele.ArrayOf_processed_dk[i][1]) + ") " + ("\'" + String(data_ukelele.ArrayOf_processed_deadkeyables[i])).replace(/\,+/g, "' '").slice(0, -1).trim() + "\n" + data += "store(dkt" + this.getHexFromChar(data_ukelele.ArrayOf_processed_dk[i][1]) + ") " + ("\'" + String(data_ukelele.ArrayOf_processed_deadkeyedChar[i])).replace(/\,+/g, "' '") + "'\n" + data += "store(dkf" + this.getHexFromChar(data_ukelele.ArrayOf_processed_dk[i][1]) + ") " + ("\'" + String(data_ukelele.ArrayOf_processed_deadkeyables[i])).replace(/\,+/g, "' '").slice(0, -1).trim() + "\n" data += "store(dkt" + this.getHexFromChar(data_ukelele.ArrayOf_processed_dk[i][1]) + ") " + ("\'" + String(data_ukelele.ArrayOf_processed_deadkeyedChar[i])).replace(/\,+/g, "' '") + "'\n" data += '\n' @@ -711,17 +848,303 @@ export class KeylayoutToKmnConverter { } - //TODO remove + //TODO better distinction!!! data += 'NOW MY RULES ********************************\n' for (let kkk = 0; kkk < data_ukelele.ArrayOf_processed_RuleData.length; kkk++) { - let line: string = "" - for (let lll = 0; lll < data_ukelele.ArrayOf_processed_RuleData[kkk].length; lll++) { - const entry = new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][lll]) - line += " " + entry + " " + if (data_ukelele.ArrayOf_processed_RuleData[kkk].length <= 6) { + let line: string = "" + for (let lll = 0; lll < data_ukelele.ArrayOf_processed_RuleData[kkk].length; lll++) { + const entry = new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][lll]) + line += " " + entry + " " + } + data += line + '\n' } - data += line + '\n' } - data += '\n' + + data += '\nNOW MY C4 RULES *********** (only to get 02C6 ect) *********************\n\n' + for (let kkk = 0; kkk < data_ukelele.ArrayOf_processed_RuleData.length; kkk++) { + if (new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][4]) === "isTerminator") { + let line: string = "" + for (let lll = 0; lll < data_ukelele.ArrayOf_processed_RuleData[kkk].length; lll++) { + const entry = new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][lll]) + line += " " + entry + " " + } + data += line + '\n' + } + } + + data += '......................................................\n' + for (let kkk = 0; kkk < data_ukelele.ArrayOf_processed_RuleData.length; kkk++) { + if (new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][4]) === "isTerminator") { + let line: string = "" + const entry = new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][6]) + line += " Hex dk: " + entry + " " + data += line + '\n' + } + } + + // array ony of dk (array_dk_char [ '¨', 'ˆ', '´', '˜', '`' ]) + const array_dk_char = [...new Set(data_ukelele.ArrayOf_processed_dk.map(a => a[1]))]; + console.log("array_dk_char", array_dk_char); + + + data += '\nNOW DEADKEYABLES ********************************\n\n' + + + const deadkeyables_array = [] + // loop al data rules + for (let kkk = 0; kkk < data_ukelele.ArrayOf_processed_RuleData.length; kkk++) { + + // find dk rules + if ((new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][0]) === ("first_modifier_C2")) + && (data_ukelele.ArrayOf_processed_RuleData[kkk].length === 5)) { + + // if char of pos4 is in array_dk_char [ '¨', 'ˆ', '´', '˜', '`' ]) + if (!array_dk_char.includes(new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][4]))) { + deadkeyables_array.push(new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][2])) + } + } + } + + // remove duplicates -> array_deadkeyables_unique1 [ 'K_A', 'K_E', 'K_Y', 'K_O', 'K_U', 'K_I', 'K_N' ] + const array_deadkeyables_unique = deadkeyables_array.filter(function (item, pos, self) { + return self.indexOf(item) == pos; + }) + + + data += " store dk... : " + console.log("array_deadkeyables_unique", array_deadkeyables_unique) + + for (let i = 0; i < array_deadkeyables_unique.length; i++) { + data += '\'' + array_deadkeyables_unique[i] + '\' ' + } + + data += '\nNOW DEADKEYED ********************************\n\n' + let counter = 0 + const deadkeyed_array = [] + // loop al data rules + for (let kkk = 0; kkk < data_ukelele.ArrayOf_processed_RuleData.length; kkk++) { + + // find dk rules + if ((new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][0]) === ("first_modifier_C2")) + && (data_ukelele.ArrayOf_processed_RuleData[kkk].length === 5)) { + + const deadkeyed_array_1D = [] + if (!array_dk_char.includes(new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][4]))) { + deadkeyed_array_1D.push(new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][1])) + deadkeyed_array_1D.push(new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][2])) + deadkeyed_array_1D.push(new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][3])) + deadkeyed_array_1D.push(new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][4])) + } + deadkeyed_array.push(deadkeyed_array_1D) + counter++ + } + } + + /*// remove duplicates -> array_deadkeyables_unique1 [ 'K_A', 'K_E', 'K_Y', 'K_O', 'K_U', 'K_I', 'K_N' ] + const array_deadkeyed_unique = deadkeyed_array.filter(function (item, pos, self) { + return self.indexOf(item) == pos; + })*/ + + // remove empty + const array_deadkeyed_unique = deadkeyed_array.filter(function (arr) { + return arr.length > 0 + }); + + data += " store dk... : " + // console.log("array_deadkeyed_unique", counter, array_deadkeyed_unique) + + for (let i = 0; i < array_deadkeyed_unique.length; i++) { + if (array_deadkeyed_unique[i].length !== 0) + data += '\n\'' + array_deadkeyed_unique[i] + '\' ' + // console.log("array_deadkeyed_unique[i][1]", array_deadkeyed_unique[i][1]) + } + + // find all â + const modiArray = array_deadkeyed_unique.filter(function ([A, B, C, D]) { + /* + 'SHIFT LEFTSHIFT CAPS,K_N,K_N,Ñ' + console.log("A", A) + console.log("B", B) + console.log("B[1]", B[1]) + console.log("B[2]", B[2]) + console.log("A[1]", A[1]) + console.log("A[2]", A[2]) + return B == "K_A"*/ + return D == "â" + }); + + + console.log("modiArray", modiArray) + data += '\'\n' + data += '\nNOW DEADKEYS ********************************\n\n' + + + //############################################################################################## + //######################all##################################################################### + + const All_array: any[] = [] + // loop al data rules + for (let kkk = 0; kkk < data_ukelele.ArrayOf_processed_RuleData.length; kkk++) { + + // find dk rules + // if ((new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][0]) === ("first_modifier_C2")) + // && (data_ukelele.ArrayOf_processed_RuleData[kkk].length === 5)) { + + const deadkeyed_array_1D = [] + // if (!array_dk_char.includes(new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][4]))) { + deadkeyed_array_1D.push(new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][0])) + deadkeyed_array_1D.push(new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][1])) + deadkeyed_array_1D.push(new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][2])) + deadkeyed_array_1D.push(new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][3])) + deadkeyed_array_1D.push(new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][4])) + if (data_ukelele.ArrayOf_processed_RuleData[kkk].length === 5) + deadkeyed_array_1D.push(new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][5])) + else + deadkeyed_array_1D.push("") + if (data_ukelele.ArrayOf_processed_RuleData[kkk].length === 5) + deadkeyed_array_1D.push(new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][6])) + else + deadkeyed_array_1D.push("") + // } + All_array.push(deadkeyed_array_1D) + counter++ + // } + } + + // remove empty + const All_array_unique = All_array.filter(function (arr) { + return arr.length > 0 + }); + + data += " store dk... : " + + // all data ; no duplicates [ 'first_modifier_C1', 'NCAPS', 'K_A', 'a', '', '', '' ], + // console.log("All_array_unique", counter, All_array_unique) + + //[ 'NCAPS', 'K_A', 'K_EQUAL', 'â' ], + // console.log("deadkeyed_array", deadkeyed_array) + + // find all K_A [ 'first_modifier_C2', 'NCAPS', 'K_A', 'K_EQUAL', 'â', '', '' ], + /* const All_C2 = All_array_unique.filter(function ([A, B, C, D, E, F, G]) { + return ((A === "first_modifier_C2") && (C === "K_A")) + }); + // console.log("All_C2", All_C2.length, All_C2)*/ + + + + + + + // find all deadkeys + const dk_all = All_array_unique.filter(function ([A, B, C, D, E, F, G]) { + return ((A === "first_modifier_C2")) + }); + // console.log("dk_all", dk_all.length, dk_all) + // console.log("array_dk_char", array_dk_char.length, array_dk_char) + const dk_Array: any[][] = [] + + + for (let ii = 0; ii < dk_all.length; ii++) { + for (let kk = 0; kk < array_dk_char.length; kk++) { + + // console.log("nochmakl dk_all[ii]", dk_all[ii][0], dk_all[ii][1], dk_all[ii][2], dk_all[ii][3]) + if (dk_all[ii].length > 4) { + if (array_dk_char[kk] === (dk_all[ii][4])) { + const dk_Array_1D: any[] = [] + if (dk_all[ii].length > 4) { + + + dk_Array_1D.push(dk_all[ii][2]) + dk_Array_1D.push(array_dk_char[kk]) + // console.log("dk_all[ii]", dk_all[ii], dk_Array_1D) + } + if (dk_Array_1D.length > 0) + dk_Array.push(dk_Array_1D) + } + } + } + } + // console.log("dk_Array", dk_Array.length, dk_Array) + + // find all deadkeyed [ 'first_modifier_C2', 'CAPS', 'K_A', 'K_EQUAL', 'Â', '', '' ], + const modiCaps = All_array_unique.filter(function ([A, B, C, D, E, F, G]) { + return ((A === "first_modifier_C2") && (B === "CAPS") && (C === "K_A")) + }); + console.log("modiCaps", modiCaps.length, modiCaps) + + // find deadkeyable [ 'first_modifier_C1', 'CAPS', 'K_A', 'A', '', '', '' ] + const modiDeadkeyable = All_array_unique.filter(function ([A, B, C, D, E, F, G]) { + return ((A === "first_modifier_C1") && (B === "CAPS") && (C === "K_A")) + }); + + console.log("modiDeadkeyable", modiDeadkeyable.length, modiDeadkeyable) + + const nname = this.map_UkeleleKC_To_VK(0) + const modiDeadkeyable2 = All_array_unique.filter(function ([A, B, C, D, E, F, G]) { + return ((A === "first_modifier_C1") && (B === "CAPS") && (C === nname)) + }); + console.log("modiDeadkeyable2", data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect.length, data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[1].length, modiDeadkeyable2) + + + let modiDeadkeyable1 + let Shift:any + const modiDeadkeyable1_all: any[][] = [] + const modiDeadkeyable1_all_lines: any[][] = [] + //loop through all keys + console.log("lenns",data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect.length, + data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[1].length + ) + // 8 behaviours + for (let j = 0; j < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect.length; j++) { + // for (let j = 0; j < 1; j++) { + const modiDeadkeyable1_arr1: any[] = [] + let allDKables_name_char: any[] = [] + // 4 modifiers for beha 1 + for (let k = 0; k < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[j].length; k++) { + const deadkeyables_line: any[] = [] + const modiDeadkeyable1_arr: any[] = [] + for (let i = 0; i < 50; i++) { + const Keyname = this.map_UkeleleKC_To_VK(i) + Shift = this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[j][k], isCAPSused) + // const Shift = "CAPS" + // console.log("Keyname", Keyname, "xxShift", Shift) + + + // find deadkeyable [ 'first_modifier_C1', 'CAPS', 'K_A', 'A', '', '', '' ] + modiDeadkeyable1 = All_array_unique.filter(function ([A, B, C, D, E, F, G]) { + return ((A === "first_modifier_C1") && (B === Shift) && (C === Keyname)) + }); + + // console.log("modiDeadkeyable1[0]", modiDeadkeyable1[0]) + modiDeadkeyable1_arr.push(modiDeadkeyable1[0]) + } + modiDeadkeyable1_all.push(modiDeadkeyable1_arr1) + + console.log("modiDeadkeyable1_arr", modiDeadkeyable1_arr.length, modiDeadkeyable1_arr, modiDeadkeyable1_arr[0]) + + + allDKables_name_char = modiDeadkeyable1_arr.filter(function (mod) { + //console.log("mod", mod) + return ((mod !== undefined) && (mod[2] !== "K_SPACE")) + }); + + + console.log("allDKables_name_char", allDKables_name_char.length, allDKables_name_char) + + for (let i = 0; i < allDKables_name_char.length; i++) { + deadkeyables_line.push(allDKables_name_char[i][3]) + } + + console.log("deadkeyables_line with ss ",Shift, deadkeyables_line.length,deadkeyables_line) + if(deadkeyables_line.length !=0) + modiDeadkeyable1_all_lines.push(deadkeyables_line) + + } + + console.log("modiDeadkeyable1_all_lines", modiDeadkeyable1_all_lines.length,modiDeadkeyable1_all_lines) + } data += '\n' + // console.log("start write 5") /*writeFileSync("data/MyResult.kmn", data, { flag: "w" })*/ const data_encoded = new TextEncoder().encode(data) @@ -922,7 +1345,7 @@ export class KeylayoutToKmnConverter { this.lookup_11_KeyMapAction__To__KeyIndex(jsonObj, nextvalArray[k]) )*/ - DataArraySingleStateC2_U8.push(new TextEncoder().encode("first modifier_C2")) + DataArraySingleStateC2_U8.push(new TextEncoder().encode("first_modifier_C2")) DataArraySingleStateC2_U8.push(first_modifier_C2_U8) DataArraySingleStateC2_U8.push(first_Key_C2_U8) DataArraySingleStateC2_U8.push(second_Key_C2_U8)// state = none -> no modifier @@ -1056,23 +1479,34 @@ export class KeylayoutToKmnConverter { const first_modifier_C4_U8 = new TextEncoder().encode(this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i][l], isCapsused)) const first_key_C4_U8 = new TextEncoder().encode(this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']))) + const str_UTF8 = new TextDecoder().decode(result_C4_U8) + + DataArraySingleStateC4_U8.push(new TextEncoder().encode("first_modifier_C4")) + DataArraySingleStateC4_U8.push(first_modifier_C4_U8) + DataArraySingleStateC4_U8.push(first_key_C4_U8) + DataArraySingleStateC4_U8.push(result_C4_U8) + + if (result_C4_U8.length !== 0) { + DataArraySingleStateC4_U8.push(new TextEncoder().encode("isTerminator")) + DataArraySingleStateC4_U8.push(result_C4_U8) + DataArraySingleStateC4_U8.push(new TextEncoder().encode(this.getHexFromChar(str_UTF8))) + } + if (result_C4 !== "") { - /*console.log( + console.log( "### Key Nr ", jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], - "[ + C4 modifiers->", i, first_modifier_C4.padEnd(25, " "), "] ", + "[ + C4 modifiers->", i, "] ", this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])).padEnd(8, " "), "> ", result_C4, " [", action_id, next_id, - "]")*/ - - DataArraySingleStateC4_U8.push(new TextEncoder().encode("first_modifier_C4")) - DataArraySingleStateC4_U8.push(first_modifier_C4_U8) - DataArraySingleStateC4_U8.push(first_key_C4_U8) - DataArraySingleStateC4_U8.push(result_C4_U8) + "]", + result_C4_U8, this.getHexFromChar(str_UTF8), + this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i][l], isCapsused) + ) } if (DataArraySingleStateC4_U8.length > 0) DataArray_U8.push(DataArraySingleStateC4_U8) @@ -1085,6 +1519,7 @@ export class KeylayoutToKmnConverter { } data_ukelele.ArrayOf_processed_RuleData = DataArray_U8 + //console.log("DataArray_U8", DataArray_U8) return data_ukelele } @@ -1256,7 +1691,7 @@ export class KeylayoutToKmnConverter { * @return headecimal value of a character */ public getHexFromChar(character: string): string { - return '00' + character.charCodeAt(0).toString(16).slice(-4).toLowerCase() + return character.charCodeAt(0).toString(16).slice(-4).toUpperCase().padStart(4, "0") } // TODO if the first in the list does not contain caps but later entries do contain caps-> no NCAPS is added(Todo check if caps/NCAPS are there after all entries are completed) diff --git a/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts index 20bea0925cc..d8c24467ae2 100644 --- a/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts @@ -20,7 +20,7 @@ describe('KeylayoutToKmnConverter', function() { }); // _S2 first test - it('should throw on null inputs', async function () { + /* it('should throw on null inputs', async function () { // const inputFilename = makePathToFixture('file.keylayout'); const converter = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); // note, could use 'chai as promised' library to make this more fluent: @@ -31,7 +31,7 @@ describe('KeylayoutToKmnConverter', function() { threw = true; } assert.isTrue(threw); - }); + });*/ // _S2 My tests... // later throws on NOT all elements loaded @@ -42,6 +42,7 @@ describe('KeylayoutToKmnConverter', function() { // all keys, some deadkeys //const inputFilename = makePathToFixture('../data/US_complete.keylayout'); + //const inputFilename = makePathToFixture('../data/German_complete.keylayout'); const inputFilename = makePathToFixture('../data/Italian_copy.keylayout'); //const inputFilename = makePathToFixture('../data/My_dk_Keyboard.keylayout'); From 3bdcee94880abb60c0c8f3c37e8697e3865b88bc Mon Sep 17 00:00:00 2001 From: Sabine Date: Thu, 19 Dec 2024 17:31:44 +0100 Subject: [PATCH 032/251] feat(developer): kmc-convert write out all data to kmn --- .../keylayout-to-kmn-converter.ts | 577 +++++++++--------- 1 file changed, 295 insertions(+), 282 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index c2034cf3bc3..09793a9da01 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -512,9 +512,6 @@ export class KeylayoutToKmnConverter { */ public convert(data_ukelele: convert_object): convert_object { - - - const data_VK_from_keylayout: (string | number)[][] = []; for (let i = 0; i < data_ukelele.ArrayOf_Element_KeyOutput[0].length; i++) { @@ -538,21 +535,7 @@ export class KeylayoutToKmnConverter { */ //TODO need to use export const USVirtualKeyCodes here public write(data_ukelele: convert_object): boolean { - console.log("start write") - console.log("SizeOf elements: " - , "\n ArrayOf_Element_Layouts", data_ukelele.ArrayOf_Element_Layouts.length - , "\n ArrayOf_ALL_Element_ModifierMaps", data_ukelele.ArrayOf_Element_ALL_ModifierMaps.length - , "\n ArrayOf_Element_KeyAction", data_ukelele.ArrayOf_Element_KeyAction.length - , "\n ArrayOf_Element_KeyOutput", data_ukelele.ArrayOf_Element_KeyOutput.length - , "\n ArrayOf_Element_Terminators", data_ukelele.ArrayOf_Element_Terminators.length - , "\n ArrayOf_Element_ModifierMaps_ALLKeyMapSelect", data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect.length - , "\n ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[1]", data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[1].length - - , "\n ArrayOf_processed_VK_from_keylayout", data_ukelele.ArrayOf_processed_VK_from_keylayout.length - , "\n ArrayOf_processed_deadkeyables", data_ukelele.ArrayOf_processed_deadkeyables.length - , "\n ArrayOf_processed_deadkeyedChar", data_ukelele.ArrayOf_processed_deadkeyedChar.length - , "\n ArrayOf_processed_dk", data_ukelele.ArrayOf_processed_dk.length - ) + console.log("start write") // ************************************************************* // **** write stores ******************************************* @@ -711,116 +694,7 @@ export class KeylayoutToKmnConverter { } - // all 109 keys with action a9 - /* for (let i = 0; i < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect.length; i++) { - // loop through keyMapSelect (8) - for (let ii = 0; ii < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i].length; ii++) { - //for (let ii = 0; ii < 8; ii++) { - // loop through modifiers - //for (let j = 0; j < data_ukelele.ArrayOf_Element_KeyAction.length; j++) { - // 8 behaviors - // for (let j = 0; j < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i][ii].length; j++) { - if (data_ukelele.ArrayOf_Element_ALL_ModifierMaps[i][ii] !== "") { - - console.log("start write 3A", i,ii,data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i][ii] ) - - const label_modifier = this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ALL_ModifierMaps[i][ii], isCAPSused) - console.log("label_modifier", label_modifier ) - // get the modifier for the layer - //const label_modifier = this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ALL_ModifierMaps[j], isCAPSused) - const label_modifier = this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ALL_ModifierMaps[i][ii], isCAPSused) - - // get the character from keymap-section of .keylayout-file that will be written as result in kmn-file - //const resulting_character = new TextDecoder().decode(data_ukelele.ArrayOf_Element_KeyAction[j][i]) - // wrong since it attempts to convert a9 and not 4 ( the termínator id ) - const resulting_character = new TextDecoder().decode(data_ukelele.ArrayOf_Element_KeyAction[i][ii]) - - // therefore get character from ~ <- 4 <- a9 - //const realChar = this.getCharacterFromActionName(data_ukelele, data_ukelele.ArrayOf_Element_KeyAction[ii][i]) - //console.log("realChar", realChar,i,ii,j ) - // console.log("data_ukelele.ArrayOf_Element_KeyAction[ii][i],", - // data_ukelele.ArrayOf_Element_KeyAction[ii][i], - // realChar) - - if (resulting_character !== "") { - console.log("start write 3B+3C", i, ii, label_modifier, "---", resulting_character) - - const VK: (string | number)[][] = data_ukelele.ArrayOf_processed_VK_from_keylayout - const vk_label = VK.filter(item => item[0] === data_ukelele.ArrayOf_processed_VK_from_keylayout[i][0]) - // console.log("VK", VK, "vk_label", vk_label) - - // console.log("start write 3D,data_ukelele.ArrayOf_processed_dk", data_ukelele.ArrayOf_processed_dk) - for (let k = 0; k < data_ukelele.ArrayOf_processed_dk.length; k++) { - // console.log("start write 3E") - // console.log("resulting_character", resulting_character, "data_ukelele.ArrayOf_processed_dk[k][1]", data_ukelele.ArrayOf_processed_dk[k][1]) - // console.log("data_ukelele.ArrayOf_processed_dk is",data_ukelele.ArrayOf_processed_dk) - // console.log("resulting_characte, data_ukelele.ArrayOf_processed_dk is",resulting_character, data_ukelele.ArrayOf_processed_dk[k][2]) - if ((resulting_character !== "") && (resulting_character === data_ukelele.ArrayOf_processed_dk[k][2])) { - data += '[' + (label_modifier + ' ' + vk_label[0][1]).trim() + '] ' + "> dk(" + this.getHexFromChar(data_ukelele.ArrayOf_processed_dk[k][1]) + ") " + '\n' - console.log("start write 3D", data) - - } - } - // } - - } - - } - }}*/ - - /* old - // all 109 keys with action a9 - for (let i = 0; i < data_ukelele.ArrayOf_Element_KeyAction[0].length; i++) { - // loop through keyMapSelect (8) - for (let ii = 0; ii < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect.length; ii++) { - //for (let ii = 0; ii < 8; ii++) { - // loop through modifiers - //for (let j = 0; j < data_ukelele.ArrayOf_Element_KeyAction.length; j++) { - // 8 behaviors - for (let j = 0; j < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect.length; j++) { - console.log("start write 3A", i,ii,j) - - // get the modifier for the layer - //const label_modifier = this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ALL_ModifierMaps[j], isCAPSused) - const label_modifier = this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ALL_ModifierMaps[j], isCAPSused) - - // get the character from keymap-section of .keylayout-file that will be written as result in kmn-file - //const resulting_character = new TextDecoder().decode(data_ukelele.ArrayOf_Element_KeyAction[j][i]) - // wrong since it attempts to convert a9 and not 4 ( the termínator id ) - const resulting_character = new TextDecoder().decode(data_ukelele.ArrayOf_Element_KeyAction[ii][i]) - - // therefore get character from ~ <- 4 <- a9 - //const realChar = this.getCharacterFromActionName(data_ukelele, data_ukelele.ArrayOf_Element_KeyAction[ii][i]) - //console.log("realChar", realChar,i,ii,j ) - // console.log("data_ukelele.ArrayOf_Element_KeyAction[ii][i],", - // data_ukelele.ArrayOf_Element_KeyAction[ii][i], - // realChar) - - if (resulting_character !== "") { - console.log("start write 3B+3C", i, ii, j, label_modifier, "---", resulting_character) - - const VK: (string | number)[][] = data_ukelele.ArrayOf_processed_VK_from_keylayout - const vk_label = VK.filter(item => item[0] === data_ukelele.ArrayOf_processed_VK_from_keylayout[i][0]) - // console.log("VK", VK, "vk_label", vk_label) - - // console.log("start write 3D,data_ukelele.ArrayOf_processed_dk", data_ukelele.ArrayOf_processed_dk) - for (let k = 0; k < data_ukelele.ArrayOf_processed_dk.length; k++) { - /* console.log("start write 3E") - console.log("resulting_character", resulting_character, "data_ukelele.ArrayOf_processed_dk[k][1]", data_ukelele.ArrayOf_processed_dk[k][1]) - console.log("data_ukelele.ArrayOf_processed_dk is",data_ukelele.ArrayOf_processed_dk) - console.log("resulting_characte, data_ukelele.ArrayOf_processed_dk is",resulting_character, data_ukelele.ArrayOf_processed_dk[k][2])*/ - /* if ((resulting_character !== "") && (resulting_character === data_ukelele.ArrayOf_processed_dk[k][2])) { - data += '[' + (label_modifier + ' ' + vk_label[0][1]).trim() + '] ' + "> dk(" + this.getHexFromChar(data_ukelele.ArrayOf_processed_dk[k][1]) + ") " + '\n' - console.log("start write 3D", data) - - } - } - } - } - - } - } -*/ + // console.log("start write 4") data += "\n" data += "match > use(deadkeys)\n\n" @@ -873,6 +747,8 @@ export class KeylayoutToKmnConverter { } } + + data += '......................................................\n' for (let kkk = 0; kkk < data_ukelele.ArrayOf_processed_RuleData.length; kkk++) { if (new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][4]) === "isTerminator") { @@ -913,7 +789,7 @@ export class KeylayoutToKmnConverter { data += " store dk... : " - console.log("array_deadkeyables_unique", array_deadkeyables_unique) + //console.log("array_deadkeyables_unique", array_deadkeyables_unique) for (let i = 0; i < array_deadkeyables_unique.length; i++) { data += '\'' + array_deadkeyables_unique[i] + '\' ' @@ -941,41 +817,21 @@ export class KeylayoutToKmnConverter { } } - /*// remove duplicates -> array_deadkeyables_unique1 [ 'K_A', 'K_E', 'K_Y', 'K_O', 'K_U', 'K_I', 'K_N' ] - const array_deadkeyed_unique = deadkeyed_array.filter(function (item, pos, self) { - return self.indexOf(item) == pos; - })*/ - // remove empty const array_deadkeyed_unique = deadkeyed_array.filter(function (arr) { return arr.length > 0 }); data += " store dk... : " - // console.log("array_deadkeyed_unique", counter, array_deadkeyed_unique) + // console.log("array_deadkeyed_unique", counter, array_deadkeyed_unique) for (let i = 0; i < array_deadkeyed_unique.length; i++) { if (array_deadkeyed_unique[i].length !== 0) data += '\n\'' + array_deadkeyed_unique[i] + '\' ' - // console.log("array_deadkeyed_unique[i][1]", array_deadkeyed_unique[i][1]) - } - - // find all â - const modiArray = array_deadkeyed_unique.filter(function ([A, B, C, D]) { - /* - 'SHIFT LEFTSHIFT CAPS,K_N,K_N,Ñ' - console.log("A", A) - console.log("B", B) - console.log("B[1]", B[1]) - console.log("B[2]", B[2]) - console.log("A[1]", A[1]) - console.log("A[2]", A[2]) - return B == "K_A"*/ - return D == "â" - }); - + // console.log("array_deadkeyed_unique[i][1]", array_deadkeyed_unique[i][1]) + } - console.log("modiArray", modiArray) + // console.log("modiArray", modiArray) data += '\'\n' data += '\nNOW DEADKEYS ********************************\n\n' @@ -984,166 +840,122 @@ export class KeylayoutToKmnConverter { //######################all##################################################################### const All_array: any[] = [] - // loop al data rules + // loop al data rules and push dk rules to array for (let kkk = 0; kkk < data_ukelele.ArrayOf_processed_RuleData.length; kkk++) { - - // find dk rules - // if ((new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][0]) === ("first_modifier_C2")) - // && (data_ukelele.ArrayOf_processed_RuleData[kkk].length === 5)) { - const deadkeyed_array_1D = [] - // if (!array_dk_char.includes(new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][4]))) { - deadkeyed_array_1D.push(new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][0])) - deadkeyed_array_1D.push(new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][1])) - deadkeyed_array_1D.push(new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][2])) - deadkeyed_array_1D.push(new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][3])) - deadkeyed_array_1D.push(new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][4])) - if (data_ukelele.ArrayOf_processed_RuleData[kkk].length === 5) - deadkeyed_array_1D.push(new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][5])) + deadkeyed_array_1D.push(new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][0])) //modifier + deadkeyed_array_1D.push(new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][1])) //shiftstates + deadkeyed_array_1D.push(new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][2])) //keyname 1 + deadkeyed_array_1D.push(new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][3])) //output character/ keyname 2 / shiftstate 2 + if (data_ukelele.ArrayOf_processed_RuleData[kkk].length === 4) + deadkeyed_array_1D.push(new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][4])) // -- / keyname 2 else deadkeyed_array_1D.push("") if (data_ukelele.ArrayOf_processed_RuleData[kkk].length === 5) - deadkeyed_array_1D.push(new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][6])) + deadkeyed_array_1D.push(new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][5])) // -- / output character else deadkeyed_array_1D.push("") - // } - All_array.push(deadkeyed_array_1D) - counter++ - // } - } - - // remove empty - const All_array_unique = All_array.filter(function (arr) { - return arr.length > 0 - }); - - data += " store dk... : " - - // all data ; no duplicates [ 'first_modifier_C1', 'NCAPS', 'K_A', 'a', '', '', '' ], - // console.log("All_array_unique", counter, All_array_unique) - - //[ 'NCAPS', 'K_A', 'K_EQUAL', 'â' ], - // console.log("deadkeyed_array", deadkeyed_array) - - // find all K_A [ 'first_modifier_C2', 'NCAPS', 'K_A', 'K_EQUAL', 'â', '', '' ], - /* const All_C2 = All_array_unique.filter(function ([A, B, C, D, E, F, G]) { - return ((A === "first_modifier_C2") && (C === "K_A")) - }); - // console.log("All_C2", All_C2.length, All_C2)*/ - - - - - - // find all deadkeys - const dk_all = All_array_unique.filter(function ([A, B, C, D, E, F, G]) { - return ((A === "first_modifier_C2")) - }); - // console.log("dk_all", dk_all.length, dk_all) - // console.log("array_dk_char", array_dk_char.length, array_dk_char) - const dk_Array: any[][] = [] - - - for (let ii = 0; ii < dk_all.length; ii++) { - for (let kk = 0; kk < array_dk_char.length; kk++) { - - // console.log("nochmakl dk_all[ii]", dk_all[ii][0], dk_all[ii][1], dk_all[ii][2], dk_all[ii][3]) - if (dk_all[ii].length > 4) { - if (array_dk_char[kk] === (dk_all[ii][4])) { - const dk_Array_1D: any[] = [] - if (dk_all[ii].length > 4) { - - - dk_Array_1D.push(dk_all[ii][2]) - dk_Array_1D.push(array_dk_char[kk]) - // console.log("dk_all[ii]", dk_all[ii], dk_Array_1D) - } - if (dk_Array_1D.length > 0) - dk_Array.push(dk_Array_1D) - } - } - } + if (deadkeyed_array_1D.length > 0) + All_array.push(deadkeyed_array_1D) + counter++ } - // console.log("dk_Array", dk_Array.length, dk_Array) - // find all deadkeyed [ 'first_modifier_C2', 'CAPS', 'K_A', 'K_EQUAL', 'Â', '', '' ], - const modiCaps = All_array_unique.filter(function ([A, B, C, D, E, F, G]) { - return ((A === "first_modifier_C2") && (B === "CAPS") && (C === "K_A")) - }); - console.log("modiCaps", modiCaps.length, modiCaps) + // + // console.log("All_array", All_array) + data += " store dk... : \n" - // find deadkeyable [ 'first_modifier_C1', 'CAPS', 'K_A', 'A', '', '', '' ] - const modiDeadkeyable = All_array_unique.filter(function ([A, B, C, D, E, F, G]) { - return ((A === "first_modifier_C1") && (B === "CAPS") && (C === "K_A")) - }); - console.log("modiDeadkeyable", modiDeadkeyable.length, modiDeadkeyable) - - const nname = this.map_UkeleleKC_To_VK(0) - const modiDeadkeyable2 = All_array_unique.filter(function ([A, B, C, D, E, F, G]) { - return ((A === "first_modifier_C1") && (B === "CAPS") && (C === nname)) - }); - console.log("modiDeadkeyable2", data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect.length, data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[1].length, modiDeadkeyable2) - - - let modiDeadkeyable1 - let Shift:any - const modiDeadkeyable1_all: any[][] = [] + let All_C1_Shift_Keyname_all + let All_C1_Shift_Keyname + let Shift: any const modiDeadkeyable1_all_lines: any[][] = [] - //loop through all keys - console.log("lenns",data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect.length, - data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[1].length - ) - // 8 behaviours + const deadkeyables_combi: any[][] = [] + const deadkeyables_combiAndSS: any[][] = [] + + //loop through all behaviours (8) for (let j = 0; j < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect.length; j++) { + // for (let j = 0; j < 1; j++) { - const modiDeadkeyable1_arr1: any[] = [] - let allDKables_name_char: any[] = [] - // 4 modifiers for beha 1 + let deadkeyables_without_VKspace: any[] = [] + + //loop through all modifiers (4) for behaviour for (let k = 0; k < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[j].length; k++) { const deadkeyables_line: any[] = [] const modiDeadkeyable1_arr: any[] = [] + const deadkeyables_combi2: any[][] = [] + // loop all keys for (let i = 0; i < 50; i++) { const Keyname = this.map_UkeleleKC_To_VK(i) - Shift = this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[j][k], isCAPSused) + Shift = this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[j][k], isCAPSused) // const Shift = "CAPS" // console.log("Keyname", Keyname, "xxShift", Shift) // find deadkeyable [ 'first_modifier_C1', 'CAPS', 'K_A', 'A', '', '', '' ] - modiDeadkeyable1 = All_array_unique.filter(function ([A, B, C, D, E, F, G]) { + All_C1_Shift_Keyname_all = All_array.filter(function ([A, B, C, D, E, F, G]) { return ((A === "first_modifier_C1") && (B === Shift) && (C === Keyname)) }); + //console.log("All_C1_Shift_Keyname_all", All_C1_Shift_Keyname_all.length,All_C1_Shift_Keyname_all) + + + + + + All_C1_Shift_Keyname = All_C1_Shift_Keyname_all + + // console.log("All_C1_Shift_Keyname", All_C1_Shift_Keyname.length, All_C1_Shift_Keyname) + + // in case there are more rules-should not be the case + for (let xi = 0; xi < All_C1_Shift_Keyname.length; xi++) { + modiDeadkeyable1_arr.push(All_C1_Shift_Keyname[xi]) + } - // console.log("modiDeadkeyable1[0]", modiDeadkeyable1[0]) - modiDeadkeyable1_arr.push(modiDeadkeyable1[0]) } - modiDeadkeyable1_all.push(modiDeadkeyable1_arr1) - console.log("modiDeadkeyable1_arr", modiDeadkeyable1_arr.length, modiDeadkeyable1_arr, modiDeadkeyable1_arr[0]) + //console.log("modiDeadkeyable1_arr", modiDeadkeyable1_arr.length, modiDeadkeyable1_arr, modiDeadkeyable1_arr[0]) - allDKables_name_char = modiDeadkeyable1_arr.filter(function (mod) { - //console.log("mod", mod) + deadkeyables_without_VKspace = modiDeadkeyable1_arr.filter(function (mod) { return ((mod !== undefined) && (mod[2] !== "K_SPACE")) }); - - - console.log("allDKables_name_char", allDKables_name_char.length, allDKables_name_char) + console.log("deadkeyables_without_VKspace", deadkeyables_without_VKspace.length, deadkeyables_without_VKspace) + + for (let i = 0; i < deadkeyables_without_VKspace.length; i++) { + //deadkeyables_line.push(deadkeyables_without_VKspace[i][2]) + deadkeyables_line.push(deadkeyables_without_VKspace[i][3]) - for (let i = 0; i < allDKables_name_char.length; i++) { - deadkeyables_line.push(allDKables_name_char[i][3]) + const deadkeyables_line_forC: any[] = [] + for (let zz = 2; zz < 4; zz++) { + deadkeyables_line_forC.push(deadkeyables_without_VKspace[i][zz]) + } + deadkeyables_combi.push(deadkeyables_line_forC) + deadkeyables_combi2.push(deadkeyables_line_forC) } - console.log("deadkeyables_line with ss ",Shift, deadkeyables_line.length,deadkeyables_line) - if(deadkeyables_line.length !=0) + // console.log("deadkeyables_combi2[k][1]", deadkeyables_combi2[k], deadkeyables_combi2[j]) + + if (deadkeyables_line.length != 0) { modiDeadkeyable1_all_lines.push(deadkeyables_line) + data += "Deadkeyables: " + deadkeyables_line + "\n" + data += "dk : " + deadkeyables_combi2[k][j] + "\n" + } + deadkeyables_combiAndSS.push(deadkeyables_combi2) } - - console.log("modiDeadkeyable1_all_lines", modiDeadkeyable1_all_lines.length,modiDeadkeyable1_all_lines) - } data += '\n' + // THIS IS DEADKEYABLES OUTPUT + // console.log("modiDeadkeyable1_all_lines", modiDeadkeyable1_all_lines.length, modiDeadkeyable1_all_lines) + } + data += '\n' + + // console.log("deadkeyables_combiAndSS", deadkeyables_combiAndSS) + + + + + + const NEWDATA = this.writeLastPart(data_ukelele, isCAPSused) + data += NEWDATA + '\n' // console.log("start write 5") /*writeFileSync("data/MyResult.kmn", data, { flag: "w" })*/ @@ -1519,17 +1331,10 @@ export class KeylayoutToKmnConverter { } data_ukelele.ArrayOf_processed_RuleData = DataArray_U8 - //console.log("DataArray_U8", DataArray_U8) + console.log("DataArray_U8", DataArray_U8) return data_ukelele } - /*public lookup_1_KeymapCode__To__keyMapAction(data: any, search: string): string { - for (let kk = 0; kk < data.keyboard.keyMapSet[0].keyMap.length; kk++) { - for (let jj = 0; jj < data.keyboard.keyMapSet[0].keyMap[kk].key.length; jj++) { - if (data.keyboard.keyMapSet[0].keyMap[kk].key ) - } - } - }*/ // public lookup_2_KeyMapAction__To__ActionAction() { } public lookup_3_ActionNone__To__ActionNext(data: any, search: string): string { for (let jj = 0; jj < data.keyboard.actions.action.length; jj++) { @@ -1840,6 +1645,214 @@ export class KeylayoutToKmnConverter { if (pos === 49) return "K_SPACE" else return "" } -} + public useElementAsString(u18ArrayElemnent: Uint8Array): string { + return new TextDecoder().decode(u18ArrayElemnent) + } + public useAsString(u18ArrayElemnent: Uint8Array[]): string { + let str = "" + for (let i = 0; i < u18ArrayElemnent.length; i++) { + str = str + " " + new TextDecoder().decode(u18ArrayElemnent[i]) + } + return str + } + //---------------------------------------------------------------------------------------------------- + //---------------------------------------------------------------------------------------------------- + //---------------------------------------------------------------------------------------------------- + + public writeLastPart(data_ukelele: convert_object, isCAPSused: boolean): string { + + //°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° + // DEADKEYS °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° + //°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° + const dk_ss_array: string[][] = [] + + // ToDo get data from WorkArray + // filter for dk values + let data: string = "" + data += '\nNOW MY C4 RULES *********** (only to get 02C6 ect) *********************\n\n' + for (let kkk = 0; kkk < data_ukelele.ArrayOf_processed_RuleData.length; kkk++) { + if (new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][4]) === "isTerminator") { + let line: string = "" + for (let lll = 0; lll < data_ukelele.ArrayOf_processed_RuleData[kkk].length; lll++) { + const dk_ss_array1D: string[] = [] + const entry = new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][lll]) + dk_ss_array1D.push(new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][2])) + dk_ss_array1D.push(new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][3])) + dk_ss_array1D.push(new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][6])) + line += " " + entry + " " + dk_ss_array.push(dk_ss_array1D) + } + line += "\n" + data += line + '\n' + console.log((data += line), "\n") + } + } + + + // remove duplicates + const [uniqueDeadkeys] = dk_ss_array.reduce((acc, curr) => { + const [uniq, set] = acc; + if (!set.has(curr.join(','))) { + set.add(curr.join(',')); + uniq.push(curr); + } + return acc; + }, [[], new Set()], + ); + + // array ony of dk (array_dk_char [ '¨', 'ˆ', '´', '˜', '`' ]) + const array_dk_char = [...new Set(data_ukelele.ArrayOf_processed_dk.map(a => a[1]))]; + console.log("data_ukelele.ArrayOf_processed_RuleData", data_ukelele.ArrayOf_processed_RuleData); + console.log("dk_ss_array", dk_ss_array); + console.log("uniqueDeadkeys", uniqueDeadkeys); + + console.log("array_dk_charN", array_dk_char); + //console.log("data_ukelele.ArrayOf_processed_dk", data_ukelele.ArrayOf_processed_dk); + // let data = "\n" + + // create a string array ....................................................... + const workArray2D: string[][] = [] + for (let k = 0; k < data_ukelele.ArrayOf_processed_RuleData.length; k++) { + const array1D: string[] = [] + for (let l = 0; l < data_ukelele.ArrayOf_processed_RuleData[k].length; l++) { + const u8data = data_ukelele.ArrayOf_processed_RuleData[k][l] + array1D.push(this.useElementAsString(u8data)) + } + workArray2D.push(array1D) + } + console.log("workArray2D", workArray2D) + // we have 5 different types: + /* + C0: size: 4 [ 'first_modifier_C0', '33RIGHTSHIFT NCAPS', 'K_S', 'S' ] + C1: size: 4 [ 'first_modifier_C1', 'CAPS', 'K_N', 'N' ], + C2: size: 5 [ 'first_modifier_C2', 'CAPS', 'K_E', 'K_9', 'È' ], + use 2.(K_E) and 4.('È') to get Name and DEADKEYED + C3: size: 6 ['first_modifier_C3', 'NCAPS RALT', 'K_8', 'NCAPS RALT', 'K_U', 'ˆ' + C4: size: 4 ['first_modifier_C4', 'NCAPS 0', 'K_SPACE', '' ], + size: 7 ['first_modifier_C4', 'NCAPS RALT', 'K_N', '˜', 'isTerminator', '˜', '02DC' ], + use 2.(K_N) , 5. (isTerminator) and 6.('02DC') to get Name and DEADKEY in hex + + Find DEADKEYABLE + 1) first_modifier_C1 CAPS K_A A + 2) first_modifier_C2 CAPS K_A K_EQUAL  + 3) first_modifier_C2 CAPS K_A K_9 À + - Find C2 rule with Deadkeyed ( n= 5) + - get C1 rule with first n=3 entries -> (first_modifier_C1 CAPS K_A) + - get 4th entry == DEADKEYABLE + + Find DEADKEY + 1) look in modifier_C4 (n=7) + 2) get 7th entry (=02DC) + + Find DEADKEYED + 1)look in modifier_C2 + 2) get 5th entry (='È') + 2) get 3th entry (='K_E') + + + */ + + // create deadkeyables_raw, deadkeyed_raw array ....................................................... + let deadkeyables_raw: string[][] = [] + let deadkeyed_raw: string[][] = [] + + // find deadkeyable [ 'first_modifier_C1', 'CAPS', 'K_A', 'A', '', '', '' ] + deadkeyables_raw = workArray2D.filter(function ([A, B, C, D, E, F, G]) { + return ((A === "first_modifier_C1") /*&& (B === shiftstate) && (C === key_name)*/ + && ((C !== "K_SPACE") && (D !== "")) + ) + }); + //console.log("deadkeyables_raw", deadkeyables_raw) + + // find deadkeyed [ 'first_modifier_C2', 'CAPS', 'K_A', 'K_N', 'Ã' ] + deadkeyed_raw = workArray2D.filter(function ([A, B, C, D, E, F, G]) { + return ((A === "first_modifier_C2")/* && (B === shiftstate) && (C === key_name)*/ + && ((C !== "K_SPACE")) + + ) + }); + console.log("deadkeyables_raw", deadkeyables_raw.length, deadkeyables_raw) + console.log("deadkeyed_raw", deadkeyed_raw.length, deadkeyed_raw) + const dkable_dked_array2D: any[][] = [] + // loop dedkeyables, take first + for (let rr = 0; rr < deadkeyables_raw.length; rr++) { + // loop dedkeyed, take first + for (let ss = 0; ss < deadkeyed_raw.length; ss++) { + const dkable_dked_array: any[] = [] + //if available ( shifts the same, keyname the same) + if ((deadkeyables_raw[rr][1] === deadkeyed_raw[ss][1]) + && ((deadkeyables_raw[rr][2] === deadkeyed_raw[ss][2]))) { + //copy dedkeyables name, deadkeyable + //copy dedkeyed Secondname, deadkeyed + // dkable_dked_array.push(deadkeyables_raw[rr][1]) + dkable_dked_array.push(deadkeyables_raw[rr][3]) + dkable_dked_array.push(deadkeyed_raw[ss][3]) + dkable_dked_array.push(deadkeyed_raw[ss][4]) + } + // dkable_dked_array2D.push(dkable_dked_array) + if (dkable_dked_array.length > 0) + dkable_dked_array2D.push(dkable_dked_array) + } + } + + console.log("dkable_dked_array2D", dkable_dked_array2D.length, dkable_dked_array2D) + + // remove duplicates + const [uniqueDeadkeyables] = dkable_dked_array2D.reduce((acc, curr) => { + const [uniq, set] = acc; + if (!set.has(curr.join(','))) { + set.add(curr.join(',')); + uniq.push(curr); + } + return acc; + }, [[], new Set()], + ); + console.log("uniqueDeadkeyables", uniqueDeadkeyables.length, uniqueDeadkeyables); + + + const deadkeyedArray:string[][] = Array.from({ length: uniqueDeadkeys.length }, () => new Array(2).fill('')); + + console.log("deadkeyedArray", deadkeyedArray) + const deadkeyablesArray:string[][] = Array.from({ length: uniqueDeadkeys.length }, () => new Array(1).fill('')); + + for (let i = 0; i < uniqueDeadkeys.length; i++) { + for (let j = 0; j < uniqueDeadkeyables.length; j++) { + if (uniqueDeadkeys[i][0] === uniqueDeadkeyables[j][1]) { + deadkeyablesArray[i][0] = deadkeyablesArray[i][0] + "\'" + uniqueDeadkeyables[j][0] + "\' " + deadkeyedArray[i][0] = deadkeyedArray[i][0] + "\'" + uniqueDeadkeyables[j][2] + "\' " + } + } + deadkeyedArray[i][1]=(uniqueDeadkeys[i][2]) + } + + data += "\n" + for (let i = 0; i < deadkeyablesArray.length; i++) { + + data += "\n\ndk: "+ deadkeyedArray[i][1] + console.log("dk: ", deadkeyedArray[i][1]) + + data += "\ndeadkeyablesArray" + deadkeyablesArray[i][0] + console.log("deadkeyablesArray", deadkeyablesArray[i][0]) + + data += "\ndeadkeyedArray "+ deadkeyedArray[i][0] + console.log("deadkeyedArray ", deadkeyedArray[i][0]) + } + return data + } + + public writeLines(inArray: string[]): string { + let editedLine: string = "" + for (let i = 0; i < inArray.length; i++) { + if (inArray[i] !== " ") + editedLine = editedLine + "\'" + inArray[i] + "\' " + else + editedLine = editedLine + " " + } + return editedLine + } + + + +} From 6b75883c4816af3ebdbb2a5237ebff7bb5ee0a2b Mon Sep 17 00:00:00 2001 From: Sabine Date: Fri, 20 Dec 2024 09:50:23 +0100 Subject: [PATCH 033/251] eat(developer): kmc-convert write out sorted --- .../keylayout-to-kmn-converter.ts | 244 +++++++++++++----- 1 file changed, 183 insertions(+), 61 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 09793a9da01..f09cefac6d9 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -463,11 +463,13 @@ export class KeylayoutToKmnConverter { } } + // do e clear - // console.log("deadkeys_One_dk", deadkeys_One_dk) + // consoleconsole.log("deadkeys_One_dk", deadkeys_One_dk) deadkeyedChars_all_Layers.push(deadkeys_One_dk) - //console.log("deadkeyedChars_all_Layers", deadkeyedChars_all_Layers) + + //console.consolelog("deadkeyedChars_all_Layers", deadkeyedChars_all_Layers) } @@ -535,7 +537,7 @@ export class KeylayoutToKmnConverter { */ //TODO need to use export const USVirtualKeyCodes here public write(data_ukelele: convert_object): boolean { - console.log("start write") + console.log("start write") // ************************************************************* // **** write stores ******************************************* @@ -545,15 +547,20 @@ export class KeylayoutToKmnConverter { data += "c Keyman keyboard generated by kmn-convert\n" data += "c\n" data += "\n" + + data += '\########## OK #################################################################\n' data += "store(&VERSION) \'...\'\n" data += "store(&TARGETS) \'any\'\n" data += "store(&KEYBOARDVERSION) \'...\'\n" data += "store(©RIGHT) '© 2024 SIL International\n" // TODO what else ?? + data += '\########## OK #################################################################\n' + data += "\n" data += "begin Unicode > use(main)\n\n" data += "group(main) using keys\n\n" + data += '\########## OK #################################################################\n' data += "Tipp: if K_? is replaced by undefined-> no enry in kmn_Key_Name=> add K_? there and it will be shown here\n" data += "Tipp: keys that are marked with sction do not aoear in ukelele_Array_output->do not appear in kmn\n" data += "\n" @@ -615,6 +622,31 @@ export class KeylayoutToKmnConverter { //console.log("start write 2G") } + //......................................................................... + // end write out ........................................................ + //......................................................................... + //......................................................................... + + const NEWDATA = this.writeLastPart(data_ukelele, isCAPSused) + data += NEWDATA + '\n' + + // console.log("start write 5") + /*writeFileSync("data/MyResult.kmn", data, { flag: "w" })*/ + const data_encoded = new TextEncoder().encode(data) + this.callbacks.fs.writeFileSync("data/MyResult.kmn", data_encoded) // not usable here since it takes UInt8array data + + // ToDo conditions? + if (data.length > 0) + return true; + else + return false + + + //......................................................................... + // end write out ........................................................ + //......................................................................... + //......................................................................... + //console.log("start write 3") data += '\n' @@ -829,7 +861,7 @@ export class KeylayoutToKmnConverter { if (array_deadkeyed_unique[i].length !== 0) data += '\n\'' + array_deadkeyed_unique[i] + '\' ' // console.log("array_deadkeyed_unique[i][1]", array_deadkeyed_unique[i][1]) - } + } // console.log("modiArray", modiArray) data += '\'\n' @@ -954,19 +986,19 @@ export class KeylayoutToKmnConverter { - const NEWDATA = this.writeLastPart(data_ukelele, isCAPSused) - data += NEWDATA + '\n' - - // console.log("start write 5") - /*writeFileSync("data/MyResult.kmn", data, { flag: "w" })*/ - const data_encoded = new TextEncoder().encode(data) - this.callbacks.fs.writeFileSync("data/MyResult.kmn", data_encoded) // not usable here since it takes UInt8array data - - // ToDo conditions? - if (data.length > 0) - return true; - else - return false + //const NEWDATA = this.writeLastPart(data_ukelele, isCAPSused) + /* data += NEWDATA + '\n' + + // console.log("start write 5") + //writeFileSync("data/MyResult.kmn", data, { flag: "w" }) + const data_encoded = new TextEncoder().encode(data) + this.callbacks.fs.writeFileSync("data/MyResult.kmn", data_encoded) // not usable here since it takes UInt8array data + + // ToDo conditions? + if (data.length > 0) + return true; + else + return false*/ } //... helpers ............................................................................................. @@ -1661,37 +1693,125 @@ export class KeylayoutToKmnConverter { //---------------------------------------------------------------------------------------------------- public writeLastPart(data_ukelele: convert_object, isCAPSused: boolean): string { - + // create a string array ....................................................... + const workArray2D: string[][] = [] + for (let k = 0; k < data_ukelele.ArrayOf_processed_RuleData.length; k++) { + const array1D: string[] = [] + for (let l = 0; l < data_ukelele.ArrayOf_processed_RuleData[k].length; l++) { + const u8data = data_ukelele.ArrayOf_processed_RuleData[k][l] + array1D.push(this.useElementAsString(u8data)) + } + workArray2D.push(array1D) + } + console.log("workArray2D", workArray2D) //°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° // DEADKEYS °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° //°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° - const dk_ss_array: string[][] = [] + //const dk_ss_array: string[][] = [] // ToDo get data from WorkArray // filter for dk values let data: string = "" - data += '\nNOW MY C4 RULES *********** (only to get 02C6 ect) *********************\n\n' - for (let kkk = 0; kkk < data_ukelele.ArrayOf_processed_RuleData.length; kkk++) { - if (new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][4]) === "isTerminator") { - let line: string = "" - for (let lll = 0; lll < data_ukelele.ArrayOf_processed_RuleData[kkk].length; lll++) { - const dk_ss_array1D: string[] = [] - const entry = new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][lll]) - dk_ss_array1D.push(new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][2])) - dk_ss_array1D.push(new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][3])) - dk_ss_array1D.push(new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][6])) - line += " " + entry + " " - dk_ss_array.push(dk_ss_array1D) + + //data += '\n.. dk part here (+ [K_BKQUOTE] > dk(005e))\n\n' + + console.log("start dk-part ") + console.log("data_ukelele.ArrayOf_Element_KeyAction.length ", data_ukelele.ArrayOf_Element_KeyAction.length) + console.log(" data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect.length", data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect.length) + + + /* + // all 109 keys with action a9 + for (let i = 0; i < data_ukelele.ArrayOf_Element_KeyAction.length; i++) { + // loop through keyMapSelect (8) + for (let ii = 0; ii < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect.length; ii++) { + //for (let ii = 0; ii < 8; ii++) { + // loop through modifiers + //for (let j = 0; j < data_ukelele.ArrayOf_Element_KeyAction.length; j++) { + // 8 behaviors + for (let j = 0; j < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect.length; j++) { + //console.log("start write 3A", i, ii, j) + + // get the modifier for the layer + //const label_modifier = this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ALL_ModifierMaps[j], isCAPSused) + const label_modifier = this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ALL_ModifierMaps[j], isCAPSused) + console.log("label_modifier ", label_modifier) + + // get the character from keymap-section of .keylayout-file that will be written as result in kmn-file + //const resulting_character = new TextDecoder().decode(data_ukelele.ArrayOf_Element_KeyAction[j][i]) + // wrong since it attempts to convert a9 and not 4 ( the termínator id ) + const resulting_character = new TextDecoder().decode(data_ukelele.ArrayOf_Element_KeyAction[ii][i]) + console.log("resulting_character ",resulting_character ) + console.log("data_ukelele.ArrayOf_Element_KeyAction ",data_ukelele.ArrayOf_Element_KeyAction ) + + // therefore get character from ~ <- 4 <- a9 + //const realChar = this.getCharacterFromActionName(data_ukelele, data_ukelele.ArrayOf_Element_KeyAction[ii][i]) + //console.log("realChar", realChar,i,ii,j ) + // console.log("data_ukelele.ArrayOf_Element_KeyAction[ii][i],", + // data_ukelele.ArrayOf_Element_KeyAction[ii][i], + // realChar) + + if (resulting_character !== "") { + console.log("start write 3B+3C", i, ii, j, label_modifier, "---", resulting_character) + + const VK: (string | number)[][] = data_ukelele.ArrayOf_processed_VK_from_keylayout + const vk_label = VK.filter(item => item[0] === data_ukelele.ArrayOf_processed_VK_from_keylayout[i][0]) + // console.log("VK", VK, "vk_label", vk_label) + + // console.log("start write 3D,data_ukelele.ArrayOf_processed_dk", data_ukelele.ArrayOf_processed_dk) + for (let k = 0; k < data_ukelele.ArrayOf_processed_dk.length; k++) { + console.log("start write 3E") + console.log("resulting_character", resulting_character, "data_ukelele.ArrayOf_processed_dk[k][1]", data_ukelele.ArrayOf_processed_dk[k][1]) + console.log("data_ukelele.ArrayOf_processed_dk is", data_ukelele.ArrayOf_processed_dk) + console.log("resulting_characte, data_ukelele.ArrayOf_processed_dk is", resulting_character, data_ukelele.ArrayOf_processed_dk[k][2]) + if ((resulting_character !== "") && (resulting_character === data_ukelele.ArrayOf_processed_dk[k][2])) { + data += '[' + (label_modifier + ' ' + vk_label[0][1]).trim() + '] ' + "> dk(" + this.getHexFromChar(data_ukelele.ArrayOf_processed_dk[k][1]) + ") " + '\n' + console.log("start write 3D", data) + + } + } + } + } + + } } - line += "\n" - data += line + '\n' - console.log((data += line), "\n") + */ + data += '\########## OK #################################################################\n' + + data += '\nNOW MY C4 RULES **ccc ********* (only to get 02C6 ect) *********************\n\n' + console.log("data_ukelele.ArrayOf_processed_RuleData", data_ukelele.ArrayOf_processed_RuleData); + console.log("data_ukelele.ArrayOf_processed_RuleData.length ", data_ukelele.ArrayOf_processed_RuleData.length) + + const dk_line_array = workArray2D.filter(function ([A, B, C, D, E, F]) { + return (E === "isTerminator") + }); + console.log("dk_line_array", dk_line_array.length, dk_line_array) + + // remove duplicates + const [uniqueDeadkeys] = dk_line_array.reduce((acc, curr) => { + const [uniq, set] = acc; + if (!set.has(curr.join(','))) { + set.add(curr.join(',')); + uniq.push(curr); } + return acc; + }, [[], new Set()], + ); + console.log("uniquedk_line_array,uniqueDeadkeys", uniqueDeadkeys.length, uniqueDeadkeys); + + + for (let kkk = 0; kkk < uniqueDeadkeys.length; kkk++) { + let line: string = "" + line = "+ [" + uniqueDeadkeys[kkk][1] + " " + uniqueDeadkeys[kkk][2] + "] > dk(" + uniqueDeadkeys[kkk][6] + ")" + data += line + '\n' } + console.log(" data all together", data); + + // remove duplicates - const [uniqueDeadkeys] = dk_ss_array.reduce((acc, curr) => { + /*const [uniqueDeadkeys] = dk_ss_array.reduce((acc, curr) => { const [uniq, set] = acc; if (!set.has(curr.join(','))) { set.add(curr.join(',')); @@ -1700,29 +1820,17 @@ export class KeylayoutToKmnConverter { return acc; }, [[], new Set()], ); + console.log("uniqueDeadkeys", uniqueDeadkeys);*/ + // array ony of dk (array_dk_char [ '¨', 'ˆ', '´', '˜', '`' ]) const array_dk_char = [...new Set(data_ukelele.ArrayOf_processed_dk.map(a => a[1]))]; + console.log("array_dk_charN", array_dk_char); + + - console.log("data_ukelele.ArrayOf_processed_RuleData", data_ukelele.ArrayOf_processed_RuleData); - console.log("dk_ss_array", dk_ss_array); - console.log("uniqueDeadkeys", uniqueDeadkeys); - console.log("array_dk_charN", array_dk_char); - //console.log("data_ukelele.ArrayOf_processed_dk", data_ukelele.ArrayOf_processed_dk); - // let data = "\n" - // create a string array ....................................................... - const workArray2D: string[][] = [] - for (let k = 0; k < data_ukelele.ArrayOf_processed_RuleData.length; k++) { - const array1D: string[] = [] - for (let l = 0; l < data_ukelele.ArrayOf_processed_RuleData[k].length; l++) { - const u8data = data_ukelele.ArrayOf_processed_RuleData[k][l] - array1D.push(this.useElementAsString(u8data)) - } - workArray2D.push(array1D) - } - console.log("workArray2D", workArray2D) // we have 5 different types: /* C0: size: 4 [ 'first_modifier_C0', '33RIGHTSHIFT NCAPS', 'K_S', 'S' ] @@ -1758,6 +1866,7 @@ export class KeylayoutToKmnConverter { let deadkeyables_raw: string[][] = [] let deadkeyed_raw: string[][] = [] + // find deadkeyable [ 'first_modifier_C1', 'CAPS', 'K_A', 'A', '', '', '' ] deadkeyables_raw = workArray2D.filter(function ([A, B, C, D, E, F, G]) { return ((A === "first_modifier_C1") /*&& (B === shiftstate) && (C === key_name)*/ @@ -1766,15 +1875,17 @@ export class KeylayoutToKmnConverter { }); //console.log("deadkeyables_raw", deadkeyables_raw) + // find deadkeyed [ 'first_modifier_C2', 'CAPS', 'K_A', 'K_N', 'Ã' ] deadkeyed_raw = workArray2D.filter(function ([A, B, C, D, E, F, G]) { return ((A === "first_modifier_C2")/* && (B === shiftstate) && (C === key_name)*/ && ((C !== "K_SPACE")) - ) }); console.log("deadkeyables_raw", deadkeyables_raw.length, deadkeyables_raw) console.log("deadkeyed_raw", deadkeyed_raw.length, deadkeyed_raw) + + const dkable_dked_array2D: any[][] = [] // loop dedkeyables, take first for (let rr = 0; rr < deadkeyables_raw.length; rr++) { @@ -1796,9 +1907,9 @@ export class KeylayoutToKmnConverter { dkable_dked_array2D.push(dkable_dked_array) } } - console.log("dkable_dked_array2D", dkable_dked_array2D.length, dkable_dked_array2D) + // remove duplicates const [uniqueDeadkeyables] = dkable_dked_array2D.reduce((acc, curr) => { const [uniq, set] = acc; @@ -1812,31 +1923,42 @@ export class KeylayoutToKmnConverter { console.log("uniqueDeadkeyables", uniqueDeadkeyables.length, uniqueDeadkeyables); - const deadkeyedArray:string[][] = Array.from({ length: uniqueDeadkeys.length }, () => new Array(2).fill('')); - + const deadkeyedArray: string[][] = Array.from({ length: uniqueDeadkeys.length }, () => new Array(2).fill('')); console.log("deadkeyedArray", deadkeyedArray) - const deadkeyablesArray:string[][] = Array.from({ length: uniqueDeadkeys.length }, () => new Array(1).fill('')); + const deadkeyablesArray: string[][] = Array.from({ length: uniqueDeadkeys.length }, () => new Array(1).fill('')); + console.log("deadkeyablesArray", deadkeyablesArray) + + console.log("uniqueDeadkeys", uniqueDeadkeys) for (let i = 0; i < uniqueDeadkeys.length; i++) { for (let j = 0; j < uniqueDeadkeyables.length; j++) { - if (uniqueDeadkeys[i][0] === uniqueDeadkeyables[j][1]) { + console.log("uniqueDeadkeys[i][2] ", uniqueDeadkeys[i][2]) + console.log("uniqueDeadkeyables[j][1] ", uniqueDeadkeyables[j][1]) + + if (uniqueDeadkeys[i][2] === uniqueDeadkeyables[j][1]) { deadkeyablesArray[i][0] = deadkeyablesArray[i][0] + "\'" + uniqueDeadkeyables[j][0] + "\' " deadkeyedArray[i][0] = deadkeyedArray[i][0] + "\'" + uniqueDeadkeyables[j][2] + "\' " } } - deadkeyedArray[i][1]=(uniqueDeadkeys[i][2]) + deadkeyedArray[i][1] = (uniqueDeadkeys[i][6]) } + data += "\n" + data += '\########## OK #################################################################\n' + + data += '\nmatch > use(deadkeys)\n\n' + data += '\ngroup(deadkeys)\n\n' + // finally write out for (let i = 0; i < deadkeyablesArray.length; i++) { - data += "\n\ndk: "+ deadkeyedArray[i][1] + data += "\n\ndk: " + deadkeyedArray[i][1] console.log("dk: ", deadkeyedArray[i][1]) data += "\ndeadkeyablesArray" + deadkeyablesArray[i][0] console.log("deadkeyablesArray", deadkeyablesArray[i][0]) - data += "\ndeadkeyedArray "+ deadkeyedArray[i][0] + data += "\ndeadkeyedArray " + deadkeyedArray[i][0] console.log("deadkeyedArray ", deadkeyedArray[i][0]) } return data From 3af9cca8bc2a64ec52e851c8f9ea40b0fac503c7 Mon Sep 17 00:00:00 2001 From: Sabine Date: Fri, 20 Dec 2024 13:03:52 +0100 Subject: [PATCH 034/251] feat(developer): kmc-convert massive tidy up --- developer/src/kmc-convert/data/MyResult.kmn | 740 +++++++++++--- .../keylayout-to-kmn-converter.ts | 961 ++---------------- 2 files changed, 674 insertions(+), 1027 deletions(-) diff --git a/developer/src/kmc-convert/data/MyResult.kmn b/developer/src/kmc-convert/data/MyResult.kmn index 55f55043a99..9d99c6180ae 100644 --- a/developer/src/kmc-convert/data/MyResult.kmn +++ b/developer/src/kmc-convert/data/MyResult.kmn @@ -3,225 +3,689 @@ c c Keyman keyboard generated by kmn-convert c +########## OK ################################################################# store(&VERSION) '...' store(&TARGETS) 'any' store(&KEYBOARDVERSION) '...' store(©RIGHT) '© 2024 SIL International +########## OK ################################################################# + begin Unicode > use(main) group(main) using keys +########## OK ################################################################# Tipp: if K_? is replaced by undefined-> no enry in kmn_Key_Name=> add K_? there and it will be shown here Tipp: keys that are marked with sction do not aoear in ukelele_Array_output->do not appear in kmn -0-(modif:4-0) + [SHIFT NCAPS RALT K_A] > 'A' +0-(modif:3-0) + [NCAPS RALT K_A] > 'å' +0-(modif:4-0) + [SHIFT NCAPS RALT K_A] > 'Å' +0-(modif:5-0) + [CAPS RALT K_A] > 'Å' +0-(modif:6-0) + [NCAPS RALT K_A] > 'å' +0-(modif:7-0) + [NCAPS CTRL K_A] > '' +0-(modif:7-1) + [NCAPS RALT CTRL K_A] > '' 1-(modif:0-0) + [NCAPS K_S] > 's' -1-(modif:1-0) + [NCAPS SHIFT K_S] > 'S' -1-(modif:2-0) + [NCAPS RALT K_S] > 'S' -1-(modif:4-0) + [SHIFT NCAPS RALT K_S] > 'S' +1-(modif:0-1) + [NCAPS K_S] > 's' +1-(modif:1-0) + [SHIFT NCAPS K_S] > 'S' +1-(modif:1-1) + [RIGHTSHIFT NCAPS K_S] > 'S' +1-(modif:1-2) + [LEFTSHIFT NCAPS K_S] > 'S' +1-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_S] > 'S' +1-(modif:2-0) + [CAPS K_S] > 'S' +1-(modif:3-0) + [NCAPS RALT K_S] > 'ß' +1-(modif:4-0) + [SHIFT NCAPS RALT K_S] > '¯' +1-(modif:5-0) + [CAPS RALT K_S] > 'ß' +1-(modif:6-0) + [NCAPS RALT K_S] > 'ß' +1-(modif:7-0) + [NCAPS CTRL K_S] > '' +1-(modif:7-1) + [NCAPS RALT CTRL K_S] > '' 2-(modif:0-0) + [NCAPS K_D] > 'd' -2-(modif:1-0) + [NCAPS SHIFT K_D] > 'D' -2-(modif:2-0) + [NCAPS RALT K_D] > 'D' +2-(modif:0-1) + [NCAPS K_D] > 'd' +2-(modif:1-0) + [SHIFT NCAPS K_D] > 'D' +2-(modif:1-1) + [RIGHTSHIFT NCAPS K_D] > 'D' +2-(modif:1-2) + [LEFTSHIFT NCAPS K_D] > 'D' +2-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_D] > 'D' +2-(modif:2-0) + [CAPS K_D] > 'D' +2-(modif:3-0) + [NCAPS RALT K_D] > '∂' +2-(modif:4-0) + [SHIFT NCAPS RALT K_D] > '˘' +2-(modif:5-0) + [CAPS RALT K_D] > '∂' +2-(modif:6-0) + [NCAPS RALT K_D] > '∂' +2-(modif:7-0) + [NCAPS CTRL K_D] > '' +2-(modif:7-1) + [NCAPS RALT CTRL K_D] > '' 3-(modif:0-0) + [NCAPS K_F] > 'f' -3-(modif:1-0) + [NCAPS SHIFT K_F] > 'F' -3-(modif:2-0) + [NCAPS RALT K_F] > 'F' +3-(modif:0-1) + [NCAPS K_F] > 'f' +3-(modif:1-0) + [SHIFT NCAPS K_F] > 'F' +3-(modif:1-1) + [RIGHTSHIFT NCAPS K_F] > 'F' +3-(modif:1-2) + [LEFTSHIFT NCAPS K_F] > 'F' +3-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_F] > 'F' +3-(modif:2-0) + [CAPS K_F] > 'F' +3-(modif:3-0) + [NCAPS RALT K_F] > 'ƒ' +3-(modif:4-0) + [SHIFT NCAPS RALT K_F] > '˙' +3-(modif:5-0) + [CAPS RALT K_F] > 'ƒ' +3-(modif:6-0) + [NCAPS RALT K_F] > 'ƒ' +3-(modif:7-0) + [NCAPS CTRL K_F] > '' +3-(modif:7-1) + [NCAPS RALT CTRL K_F] > '' 4-(modif:0-0) + [NCAPS K_H] > 'h' -4-(modif:1-0) + [NCAPS SHIFT K_H] > 'H' -4-(modif:2-0) + [NCAPS RALT K_H] > 'H' +4-(modif:0-1) + [NCAPS K_H] > 'h' +4-(modif:1-0) + [SHIFT NCAPS K_H] > 'H' +4-(modif:1-1) + [RIGHTSHIFT NCAPS K_H] > 'H' +4-(modif:1-2) + [LEFTSHIFT NCAPS K_H] > 'H' +4-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_H] > 'H' +4-(modif:2-0) + [CAPS K_H] > '@' +4-(modif:3-0) + [NCAPS RALT K_H] > '∆' +4-(modif:4-0) + [SHIFT NCAPS RALT K_H] > '¸' +4-(modif:5-0) + [CAPS RALT K_H] > '€' +4-(modif:6-0) + [NCAPS RALT K_H] > 'ẞ' +4-(modif:7-0) + [NCAPS CTRL K_H] > '' +4-(modif:7-1) + [NCAPS RALT CTRL K_H] > '' 5-(modif:0-0) + [NCAPS K_G] > 'g' -5-(modif:1-0) + [NCAPS SHIFT K_G] > 'G' -5-(modif:2-0) + [NCAPS RALT K_G] > 'G' - -6-(modif:0-0) + [NCAPS K_Z] > 'y' -6-(modif:1-0) + [NCAPS SHIFT K_Z] > 'Y' -6-(modif:2-0) + [NCAPS RALT K_Z] > 'Y' +5-(modif:0-1) + [NCAPS K_G] > 'g' +5-(modif:1-0) + [SHIFT NCAPS K_G] > 'G' +5-(modif:1-1) + [RIGHTSHIFT NCAPS K_G] > 'G' +5-(modif:1-2) + [LEFTSHIFT NCAPS K_G] > 'G' +5-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_G] > 'G' +5-(modif:2-0) + [CAPS K_G] > 'G' +5-(modif:3-0) + [NCAPS RALT K_G] > '∞' +5-(modif:4-0) + [SHIFT NCAPS RALT K_G] > '˚' +5-(modif:5-0) + [CAPS RALT K_G] > '∞' +5-(modif:6-0) + [NCAPS RALT K_G] > '∞' +5-(modif:7-0) + [NCAPS CTRL K_G] > '' +5-(modif:7-1) + [NCAPS RALT CTRL K_G] > '' + +6-(modif:0-0) + [NCAPS K_Z] > 'z' +6-(modif:0-1) + [NCAPS K_Z] > 'z' +6-(modif:1-0) + [SHIFT NCAPS K_Z] > 'Z' +6-(modif:1-1) + [RIGHTSHIFT NCAPS K_Z] > 'Z' +6-(modif:1-2) + [LEFTSHIFT NCAPS K_Z] > 'Z' +6-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_Z] > 'Z' +6-(modif:2-0) + [CAPS K_Z] > 'Z' +6-(modif:3-0) + [NCAPS RALT K_Z] > '∑' +6-(modif:5-0) + [CAPS RALT K_Z] > '∑' +6-(modif:6-0) + [NCAPS RALT K_Z] > '∑' +6-(modif:7-0) + [NCAPS CTRL K_Z] > '' +6-(modif:7-1) + [NCAPS RALT CTRL K_Z] > '' 7-(modif:0-0) + [NCAPS K_X] > 'x' -7-(modif:1-0) + [NCAPS SHIFT K_X] > 'X' -7-(modif:2-0) + [NCAPS RALT K_X] > 'X' +7-(modif:0-1) + [NCAPS K_X] > 'x' +7-(modif:1-0) + [SHIFT NCAPS K_X] > 'X' +7-(modif:1-1) + [RIGHTSHIFT NCAPS K_X] > 'X' +7-(modif:1-2) + [LEFTSHIFT NCAPS K_X] > 'X' +7-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_X] > 'X' +7-(modif:2-0) + [CAPS K_X] > 'X' +7-(modif:3-0) + [NCAPS RALT K_X] > '†' +7-(modif:4-0) + [SHIFT NCAPS RALT K_X] > '‡' +7-(modif:5-0) + [CAPS RALT K_X] > '†' +7-(modif:6-0) + [NCAPS RALT K_X] > '†' +7-(modif:7-0) + [NCAPS CTRL K_X] > '' +7-(modif:7-1) + [NCAPS RALT CTRL K_X] > '' 8-(modif:0-0) + [NCAPS K_C] > 'c' -8-(modif:1-0) + [NCAPS SHIFT K_C] > 'C' -8-(modif:2-0) + [NCAPS RALT K_C] > 'C' +8-(modif:0-1) + [NCAPS K_C] > 'c' +8-(modif:1-0) + [SHIFT NCAPS K_C] > 'C' +8-(modif:1-1) + [RIGHTSHIFT NCAPS K_C] > 'C' +8-(modif:1-2) + [LEFTSHIFT NCAPS K_C] > 'C' +8-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_C] > 'C' +8-(modif:2-0) + [CAPS K_C] > 'C' +8-(modif:3-0) + [NCAPS RALT K_C] > '©' +8-(modif:4-0) + [SHIFT NCAPS RALT K_C] > 'Á' +8-(modif:5-0) + [CAPS RALT K_C] > '©' +8-(modif:6-0) + [NCAPS RALT K_C] > '©' +8-(modif:7-0) + [NCAPS CTRL K_C] > '' +8-(modif:7-1) + [NCAPS RALT CTRL K_C] > '' 9-(modif:0-0) + [NCAPS K_V] > 'v' -9-(modif:1-0) + [NCAPS SHIFT K_V] > 'V' -9-(modif:2-0) + [NCAPS RALT K_V] > 'V' - -10-(modif:1-0) + [NCAPS SHIFT K_BKQUOTE] > '±' -10-(modif:2-0) + [NCAPS RALT K_BKQUOTE] > '³' +9-(modif:0-1) + [NCAPS K_V] > 'v' +9-(modif:1-0) + [SHIFT NCAPS K_V] > 'V' +9-(modif:1-1) + [RIGHTSHIFT NCAPS K_V] > 'V' +9-(modif:1-2) + [LEFTSHIFT NCAPS K_V] > 'V' +9-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_V] > 'V' +9-(modif:2-0) + [CAPS K_V] > 'V' +9-(modif:3-0) + [NCAPS RALT K_V] > '√' +9-(modif:4-0) + [SHIFT NCAPS RALT K_V] > 'É' +9-(modif:5-0) + [CAPS RALT K_V] > '√' +9-(modif:6-0) + [NCAPS RALT K_V] > '√' +9-(modif:7-0) + [NCAPS CTRL K_V] > '' +9-(modif:7-1) + [NCAPS RALT CTRL K_V] > '' + +10-(modif:0-0) + [NCAPS K_BKQUOTE] > '\' +10-(modif:0-1) + [NCAPS K_BKQUOTE] > '\' +10-(modif:1-0) + [SHIFT NCAPS K_BKQUOTE] > '|' +10-(modif:1-1) + [RIGHTSHIFT NCAPS K_BKQUOTE] > '|' +10-(modif:1-2) + [LEFTSHIFT NCAPS K_BKQUOTE] > '|' +10-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_BKQUOTE] > '|' +10-(modif:2-0) + [CAPS K_BKQUOTE] > '\' +10-(modif:3-0) + [NCAPS RALT K_BKQUOTE] > '`' +10-(modif:4-0) + [SHIFT NCAPS RALT K_BKQUOTE] > 'ı' +10-(modif:5-0) + [CAPS RALT K_BKQUOTE] > '`' +10-(modif:6-0) + [NCAPS RALT K_BKQUOTE] > '`' +10-(modif:7-0) + [NCAPS CTRL K_BKQUOTE] > '' +10-(modif:7-1) + [NCAPS RALT CTRL K_BKQUOTE] > '' 11-(modif:0-0) + [NCAPS K_B] > 'b' -11-(modif:1-0) + [NCAPS SHIFT K_B] > 'B' -11-(modif:2-0) + [NCAPS RALT K_B] > 'B' +11-(modif:0-1) + [NCAPS K_B] > 'b' +11-(modif:1-0) + [SHIFT NCAPS K_B] > 'B' +11-(modif:1-1) + [RIGHTSHIFT NCAPS K_B] > 'B' +11-(modif:1-2) + [LEFTSHIFT NCAPS K_B] > 'B' +11-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_B] > 'B' +11-(modif:2-0) + [CAPS K_B] > 'B' +11-(modif:3-0) + [NCAPS RALT K_B] > '∫' +11-(modif:4-0) + [SHIFT NCAPS RALT K_B] > 'Í' +11-(modif:5-0) + [CAPS RALT K_B] > '∫' +11-(modif:6-0) + [NCAPS RALT K_B] > '∫' +11-(modif:7-0) + [NCAPS CTRL K_B] > '' +11-(modif:7-1) + [NCAPS RALT CTRL K_B] > '' 12-(modif:0-0) + [NCAPS K_Q] > 'q' -12-(modif:1-0) + [NCAPS SHIFT K_Q] > 'Q' -12-(modif:2-0) + [NCAPS RALT K_Q] > '@' +12-(modif:0-1) + [NCAPS K_Q] > 'q' +12-(modif:1-0) + [SHIFT NCAPS K_Q] > 'Q' +12-(modif:1-1) + [RIGHTSHIFT NCAPS K_Q] > 'Q' +12-(modif:1-2) + [LEFTSHIFT NCAPS K_Q] > 'Q' +12-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_Q] > 'Q' +12-(modif:2-0) + [CAPS K_Q] > 'Q' +12-(modif:3-0) + [NCAPS RALT K_Q] > '„' +12-(modif:4-0) + [SHIFT NCAPS RALT K_Q] > '‚' +12-(modif:5-0) + [CAPS RALT K_Q] > '„' +12-(modif:6-0) + [NCAPS RALT K_Q] > '„' +12-(modif:7-0) + [NCAPS CTRL K_Q] > '' +12-(modif:7-1) + [NCAPS RALT CTRL K_Q] > '' 13-(modif:0-0) + [NCAPS K_W] > 'w' -13-(modif:1-0) + [NCAPS SHIFT K_W] > 'W' -13-(modif:2-0) + [NCAPS RALT K_W] > 'W' - +13-(modif:0-1) + [NCAPS K_W] > 'w' +13-(modif:1-0) + [SHIFT NCAPS K_W] > 'W' +13-(modif:1-1) + [RIGHTSHIFT NCAPS K_W] > 'W' +13-(modif:1-2) + [LEFTSHIFT NCAPS K_W] > 'W' +13-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_W] > 'W' +13-(modif:2-0) + [CAPS K_W] > 'W' +13-(modif:3-0) + [NCAPS RALT K_W] > 'Ω' +13-(modif:4-0) + [SHIFT NCAPS RALT K_W] > 'À' +13-(modif:5-0) + [CAPS RALT K_W] > 'Ω' +13-(modif:6-0) + [NCAPS RALT K_W] > 'Ω' +13-(modif:7-0) + [NCAPS CTRL K_W] > '' +13-(modif:7-1) + [NCAPS RALT CTRL K_W] > '' + +14-(modif:3-0) + [NCAPS RALT K_E] > '€' +14-(modif:4-0) + [SHIFT NCAPS RALT K_E] > 'È' +14-(modif:5-0) + [CAPS RALT K_E] > '€' +14-(modif:6-0) + [NCAPS RALT K_E] > '€' +14-(modif:7-0) + [NCAPS CTRL K_E] > '' +14-(modif:7-1) + [NCAPS RALT CTRL K_E] > '' 15-(modif:0-0) + [NCAPS K_R] > 'r' -15-(modif:1-0) + [NCAPS SHIFT K_R] > 'R' -15-(modif:2-0) + [NCAPS RALT K_R] > 'R' - -16-(modif:0-0) + [NCAPS K_Y] > 'z' -16-(modif:1-0) + [NCAPS SHIFT K_Y] > 'Z' -16-(modif:2-0) + [NCAPS RALT K_Y] > 'Z' +15-(modif:0-1) + [NCAPS K_R] > 'r' +15-(modif:1-0) + [SHIFT NCAPS K_R] > 'R' +15-(modif:1-1) + [RIGHTSHIFT NCAPS K_R] > 'R' +15-(modif:1-2) + [LEFTSHIFT NCAPS K_R] > 'R' +15-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_R] > 'R' +15-(modif:2-0) + [CAPS K_R] > 'R' +15-(modif:3-0) + [NCAPS RALT K_R] > '®' +15-(modif:4-0) + [SHIFT NCAPS RALT K_R] > 'Ì' +15-(modif:5-0) + [CAPS RALT K_R] > '®' +15-(modif:6-0) + [NCAPS RALT K_R] > '®' +15-(modif:7-0) + [NCAPS CTRL K_R] > '' +15-(modif:7-1) + [NCAPS RALT CTRL K_R] > '' + +16-(modif:3-0) + [NCAPS RALT K_Y] > 'æ' +16-(modif:4-0) + [SHIFT NCAPS RALT K_Y] > 'Æ' +16-(modif:5-0) + [CAPS RALT K_Y] > 'Æ' +16-(modif:6-0) + [NCAPS RALT K_Y] > 'æ' +16-(modif:7-0) + [NCAPS CTRL K_Y] > '' +16-(modif:7-1) + [NCAPS RALT CTRL K_Y] > '' 17-(modif:0-0) + [NCAPS K_T] > 't' -17-(modif:1-0) + [NCAPS SHIFT K_T] > 'T' -17-(modif:2-0) + [NCAPS RALT K_T] > 'T' +17-(modif:0-1) + [NCAPS K_T] > 't' +17-(modif:1-0) + [SHIFT NCAPS K_T] > 'T' +17-(modif:1-1) + [RIGHTSHIFT NCAPS K_T] > 'T' +17-(modif:1-2) + [LEFTSHIFT NCAPS K_T] > 'T' +17-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_T] > 'T' +17-(modif:2-0) + [CAPS K_T] > 'T' +17-(modif:3-0) + [NCAPS RALT K_T] > '™' +17-(modif:4-0) + [SHIFT NCAPS RALT K_T] > 'Ò' +17-(modif:5-0) + [CAPS RALT K_T] > '™' +17-(modif:6-0) + [NCAPS RALT K_T] > '™' +17-(modif:7-0) + [NCAPS CTRL K_T] > '' +17-(modif:7-1) + [NCAPS RALT CTRL K_T] > '' 18-(modif:0-0) + [NCAPS K_1] > '1' -18-(modif:1-0) + [NCAPS SHIFT K_1] > '!' -18-(modif:2-0) + [NCAPS RALT K_1] > '1' +18-(modif:0-1) + [NCAPS K_1] > '1' +18-(modif:1-0) + [SHIFT NCAPS K_1] > '!' +18-(modif:1-1) + [RIGHTSHIFT NCAPS K_1] > '!' +18-(modif:1-2) + [LEFTSHIFT NCAPS K_1] > '!' +18-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_1] > '!' +18-(modif:2-0) + [CAPS K_1] > '1' +18-(modif:3-0) + [NCAPS RALT K_1] > '«' +18-(modif:4-0) + [SHIFT NCAPS RALT K_1] > '»' +18-(modif:5-0) + [CAPS RALT K_1] > '«' +18-(modif:6-0) + [NCAPS RALT K_1] > '«' +18-(modif:7-0) + [NCAPS CTRL K_1] > '1' +18-(modif:7-1) + [NCAPS RALT CTRL K_1] > '1' 19-(modif:0-0) + [NCAPS K_2] > '2' -19-(modif:1-0) + [NCAPS SHIFT K_2] > '@' -19-(modif:2-0) + [NCAPS RALT K_2] > '2' +19-(modif:0-1) + [NCAPS K_2] > '2' +19-(modif:1-0) + [SHIFT NCAPS K_2] > '"' +19-(modif:1-1) + [RIGHTSHIFT NCAPS K_2] > '"' +19-(modif:1-2) + [LEFTSHIFT NCAPS K_2] > '"' +19-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_2] > '"' +19-(modif:2-0) + [CAPS K_2] > '2' +19-(modif:3-0) + [NCAPS RALT K_2] > '“' +19-(modif:4-0) + [SHIFT NCAPS RALT K_2] > '”' +19-(modif:5-0) + [CAPS RALT K_2] > '“' +19-(modif:6-0) + [NCAPS RALT K_2] > '“' +19-(modif:7-0) + [NCAPS CTRL K_2] > '2' +19-(modif:7-1) + [NCAPS RALT CTRL K_2] > '2' 20-(modif:0-0) + [NCAPS K_3] > '3' -20-(modif:1-0) + [NCAPS SHIFT K_3] > '#' -20-(modif:2-0) + [NCAPS RALT K_3] > '3' +20-(modif:0-1) + [NCAPS K_3] > '3' +20-(modif:1-0) + [SHIFT NCAPS K_3] > '£' +20-(modif:1-1) + [RIGHTSHIFT NCAPS K_3] > '£' +20-(modif:1-2) + [LEFTSHIFT NCAPS K_3] > '£' +20-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_3] > '£' +20-(modif:2-0) + [CAPS K_3] > '3' +20-(modif:3-0) + [NCAPS RALT K_3] > '‘' +20-(modif:4-0) + [SHIFT NCAPS RALT K_3] > '’' +20-(modif:5-0) + [CAPS RALT K_3] > '‘' +20-(modif:6-0) + [NCAPS RALT K_3] > '‘' +20-(modif:7-0) + [NCAPS CTRL K_3] > '3' +20-(modif:7-1) + [NCAPS RALT CTRL K_3] > '3' 21-(modif:0-0) + [NCAPS K_4] > '4' -21-(modif:1-0) + [NCAPS SHIFT K_4] > '$' -21-(modif:2-0) + [NCAPS RALT K_4] > '4' +21-(modif:0-1) + [NCAPS K_4] > '4' +21-(modif:1-0) + [SHIFT NCAPS K_4] > '$' +21-(modif:1-1) + [RIGHTSHIFT NCAPS K_4] > '$' +21-(modif:1-2) + [LEFTSHIFT NCAPS K_4] > '$' +21-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_4] > '$' +21-(modif:2-0) + [CAPS K_4] > '4' +21-(modif:3-0) + [NCAPS RALT K_4] > '¥' +21-(modif:4-0) + [SHIFT NCAPS RALT K_4] > '¢' +21-(modif:5-0) + [CAPS RALT K_4] > '¥' +21-(modif:6-0) + [NCAPS RALT K_4] > '¥' +21-(modif:7-0) + [NCAPS CTRL K_4] > '4' +21-(modif:7-1) + [NCAPS RALT CTRL K_4] > '4' 22-(modif:0-0) + [NCAPS K_6] > '6' -22-(modif:1-0) + [NCAPS SHIFT K_6] > '^' -22-(modif:2-0) + [NCAPS RALT K_6] > '6' +22-(modif:0-1) + [NCAPS K_6] > '6' +22-(modif:1-0) + [SHIFT NCAPS K_6] > '&' +22-(modif:1-1) + [RIGHTSHIFT NCAPS K_6] > '&' +22-(modif:1-2) + [LEFTSHIFT NCAPS K_6] > '&' +22-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_6] > '&' +22-(modif:2-0) + [CAPS K_6] > '6' +22-(modif:3-0) + [NCAPS RALT K_6] > '‹' +22-(modif:4-0) + [SHIFT NCAPS RALT K_6] > '›' +22-(modif:5-0) + [CAPS RALT K_6] > '‹' +22-(modif:6-0) + [NCAPS RALT K_6] > '‹' +22-(modif:7-0) + [NCAPS CTRL K_6] > '6' +22-(modif:7-1) + [NCAPS RALT CTRL K_6] > '6' 23-(modif:0-0) + [NCAPS K_5] > '5' -23-(modif:1-0) + [NCAPS SHIFT K_5] > '%' -23-(modif:2-0) + [NCAPS RALT K_5] > '5' - +23-(modif:0-1) + [NCAPS K_5] > '5' +23-(modif:1-0) + [SHIFT NCAPS K_5] > '%' +23-(modif:1-1) + [RIGHTSHIFT NCAPS K_5] > '%' +23-(modif:1-2) + [LEFTSHIFT NCAPS K_5] > '%' +23-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_5] > '%' +23-(modif:2-0) + [CAPS K_5] > '5' +23-(modif:3-0) + [NCAPS RALT K_5] > '~' +23-(modif:4-0) + [SHIFT NCAPS RALT K_5] > '‰' +23-(modif:5-0) + [CAPS RALT K_5] > '~' +23-(modif:6-0) + [NCAPS RALT K_5] > '~' +23-(modif:7-0) + [NCAPS CTRL K_5] > '5' +23-(modif:7-1) + [NCAPS RALT CTRL K_5] > '5' + +24-(modif:1-0) + [SHIFT NCAPS K_EQUAL] > '^' +24-(modif:1-1) + [RIGHTSHIFT NCAPS K_EQUAL] > '^' +24-(modif:1-2) + [LEFTSHIFT NCAPS K_EQUAL] > '^' +24-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_EQUAL] > '^' +24-(modif:2-0) + [CAPS K_EQUAL] > 'ì' +24-(modif:4-0) + [SHIFT NCAPS RALT K_EQUAL] > '±' +24-(modif:5-0) + [CAPS RALT K_EQUAL] > 'ˆ' +24-(modif:6-0) + [NCAPS RALT K_EQUAL] > 'ˆ' +24-(modif:7-0) + [NCAPS CTRL K_EQUAL] > '=' +24-(modif:7-1) + [NCAPS RALT CTRL K_EQUAL] > '=' 25-(modif:0-0) + [NCAPS K_9] > '9' -25-(modif:1-0) + [NCAPS SHIFT K_9] > '(' -25-(modif:2-0) + [NCAPS RALT K_9] > '9' +25-(modif:0-1) + [NCAPS K_9] > '9' +25-(modif:1-0) + [SHIFT NCAPS K_9] > ')' +25-(modif:1-1) + [RIGHTSHIFT NCAPS K_9] > ')' +25-(modif:1-2) + [LEFTSHIFT NCAPS K_9] > ')' +25-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_9] > ')' +25-(modif:2-0) + [CAPS K_9] > '9' +25-(modif:5-0) + [CAPS RALT K_9] > '`' +25-(modif:6-0) + [NCAPS RALT K_9] > '`' +25-(modif:7-0) + [NCAPS CTRL K_9] > '9' +25-(modif:7-1) + [NCAPS RALT CTRL K_9] > '9' 26-(modif:0-0) + [NCAPS K_7] > '7' -26-(modif:1-0) + [NCAPS SHIFT K_7] > '&' -26-(modif:2-0) + [NCAPS RALT K_7] > '7' - -27-(modif:0-0) + [NCAPS K_HYPHEN] > '-' -27-(modif:1-0) + [NCAPS SHIFT K_HYPHEN] > '_' -27-(modif:2-0) + [NCAPS RALT K_HYPHEN] > '-' +26-(modif:0-1) + [NCAPS K_7] > '7' +26-(modif:1-0) + [SHIFT NCAPS K_7] > '/' +26-(modif:1-1) + [RIGHTSHIFT NCAPS K_7] > '/' +26-(modif:1-2) + [LEFTSHIFT NCAPS K_7] > '/' +26-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_7] > '/' +26-(modif:2-0) + [CAPS K_7] > '7' +26-(modif:3-0) + [NCAPS RALT K_7] > '÷' +26-(modif:4-0) + [SHIFT NCAPS RALT K_7] > '⁄' +26-(modif:5-0) + [CAPS RALT K_7] > '÷' +26-(modif:6-0) + [NCAPS RALT K_7] > '÷' +26-(modif:7-0) + [NCAPS CTRL K_7] > '7' +26-(modif:7-1) + [NCAPS RALT CTRL K_7] > '7' + +27-(modif:0-0) + [NCAPS K_HYPHEN] > ''' +27-(modif:0-1) + [NCAPS K_HYPHEN] > ''' +27-(modif:1-0) + [SHIFT NCAPS K_HYPHEN] > '?' +27-(modif:1-1) + [RIGHTSHIFT NCAPS K_HYPHEN] > '?' +27-(modif:1-2) + [LEFTSHIFT NCAPS K_HYPHEN] > '?' +27-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_HYPHEN] > '?' +27-(modif:2-0) + [CAPS K_HYPHEN] > ''' +27-(modif:3-0) + [NCAPS RALT K_HYPHEN] > '¡' +27-(modif:4-0) + [SHIFT NCAPS RALT K_HYPHEN] > '¿' +27-(modif:5-0) + [CAPS RALT K_HYPHEN] > '¡' +27-(modif:6-0) + [NCAPS RALT K_HYPHEN] > '¡' +27-(modif:7-0) + [NCAPS CTRL K_HYPHEN] > '' +27-(modif:7-1) + [NCAPS RALT CTRL K_HYPHEN] > '' 28-(modif:0-0) + [NCAPS K_8] > '8' -28-(modif:1-0) + [NCAPS SHIFT K_8] > '*' -28-(modif:2-0) + [NCAPS RALT K_8] > '8' +28-(modif:0-1) + [NCAPS K_8] > '8' +28-(modif:1-0) + [SHIFT NCAPS K_8] > '(' +28-(modif:1-1) + [RIGHTSHIFT NCAPS K_8] > '(' +28-(modif:1-2) + [LEFTSHIFT NCAPS K_8] > '(' +28-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_8] > '(' +28-(modif:2-0) + [CAPS K_8] > '8' +28-(modif:4-0) + [SHIFT NCAPS RALT K_8] > '' +28-(modif:5-0) + [CAPS RALT K_8] > '´' +28-(modif:6-0) + [NCAPS RALT K_8] > '´' +28-(modif:7-0) + [NCAPS CTRL K_8] > '8' +28-(modif:7-1) + [NCAPS RALT CTRL K_8] > '8' 29-(modif:0-0) + [NCAPS K_0] > '0' -29-(modif:1-0) + [NCAPS SHIFT K_0] > ')' -29-(modif:2-0) + [NCAPS RALT K_0] > '0' - -30-(modif:0-0) + [NCAPS K_RBRKT] > ']' -30-(modif:1-0) + [NCAPS SHIFT K_RBRKT] > '}' -30-(modif:2-0) + [NCAPS RALT K_RBRKT] > ']' - -31-(modif:2-0) + [NCAPS RALT K_O] > 'o' - - -33-(modif:0-0) + [NCAPS K_LBRKT] > 'ሴ' -33-(modif:1-0) + [NCAPS SHIFT K_LBRKT] > '{' -33-(modif:2-0) + [NCAPS RALT K_LBRKT] > '[' - +29-(modif:0-1) + [NCAPS K_0] > '0' +29-(modif:1-0) + [SHIFT NCAPS K_0] > '=' +29-(modif:1-1) + [RIGHTSHIFT NCAPS K_0] > '=' +29-(modif:1-2) + [LEFTSHIFT NCAPS K_0] > '=' +29-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_0] > '=' +29-(modif:2-0) + [CAPS K_0] > '0' +29-(modif:3-0) + [NCAPS RALT K_0] > '≠' +29-(modif:4-0) + [SHIFT NCAPS RALT K_0] > '≈' +29-(modif:5-0) + [CAPS RALT K_0] > '≠' +29-(modif:6-0) + [NCAPS RALT K_0] > '≠' +29-(modif:7-0) + [NCAPS CTRL K_0] > '0' +29-(modif:7-1) + [NCAPS RALT CTRL K_0] > '0' + +30-(modif:0-0) + [NCAPS K_RBRKT] > '+' +30-(modif:0-1) + [NCAPS K_RBRKT] > '+' +30-(modif:1-0) + [SHIFT NCAPS K_RBRKT] > '*' +30-(modif:1-1) + [RIGHTSHIFT NCAPS K_RBRKT] > '*' +30-(modif:1-2) + [LEFTSHIFT NCAPS K_RBRKT] > '*' +30-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_RBRKT] > '*' +30-(modif:2-0) + [CAPS K_RBRKT] > '+' +30-(modif:3-0) + [NCAPS RALT K_RBRKT] > ']' +30-(modif:4-0) + [SHIFT NCAPS RALT K_RBRKT] > '}' +30-(modif:5-0) + [CAPS RALT K_RBRKT] > ']' +30-(modif:6-0) + [NCAPS RALT K_RBRKT] > ']' +30-(modif:7-0) + [NCAPS CTRL K_RBRKT] > '' +30-(modif:7-1) + [NCAPS RALT CTRL K_RBRKT] > '' + +31-(modif:3-0) + [NCAPS RALT K_O] > 'ø' +31-(modif:4-0) + [SHIFT NCAPS RALT K_O] > 'Ø' +31-(modif:5-0) + [CAPS RALT K_O] > 'Ø' +31-(modif:6-0) + [NCAPS RALT K_O] > 'ø' +31-(modif:7-0) + [NCAPS CTRL K_O] > '' +31-(modif:7-1) + [NCAPS RALT CTRL K_O] > '' + +32-(modif:4-0) + [SHIFT NCAPS RALT K_U] > 'Ù' +32-(modif:5-0) + [CAPS RALT K_U] > '¨' +32-(modif:6-0) + [NCAPS RALT K_U] > '¨' +32-(modif:7-0) + [NCAPS CTRL K_U] > '' +32-(modif:7-1) + [NCAPS RALT CTRL K_U] > '' + +33-(modif:0-0) + [NCAPS K_LBRKT] > 'è' +33-(modif:0-1) + [NCAPS K_LBRKT] > 'è' +33-(modif:1-0) + [SHIFT NCAPS K_LBRKT] > 'é' +33-(modif:1-1) + [RIGHTSHIFT NCAPS K_LBRKT] > 'é' +33-(modif:1-2) + [LEFTSHIFT NCAPS K_LBRKT] > 'é' +33-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_LBRKT] > 'é' +33-(modif:2-0) + [CAPS K_LBRKT] > 'è' +33-(modif:3-0) + [NCAPS RALT K_LBRKT] > '[' +33-(modif:4-0) + [SHIFT NCAPS RALT K_LBRKT] > '{' +33-(modif:5-0) + [CAPS RALT K_LBRKT] > '[' +33-(modif:6-0) + [NCAPS RALT K_LBRKT] > '[' +33-(modif:7-0) + [NCAPS CTRL K_LBRKT] > '' +33-(modif:7-1) + [NCAPS RALT CTRL K_LBRKT] > '' + +34-(modif:3-0) + [NCAPS RALT K_I] > 'œ' +34-(modif:4-0) + [SHIFT NCAPS RALT K_I] > 'Œ' +34-(modif:5-0) + [CAPS RALT K_I] > 'Œ' +34-(modif:6-0) + [NCAPS RALT K_I] > 'œ' +34-(modif:7-0) + [NCAPS CTRL K_I] > ' ' +34-(modif:7-1) + [NCAPS RALT CTRL K_I] > ' ' 35-(modif:0-0) + [NCAPS K_P] > 'p' -35-(modif:1-0) + [NCAPS SHIFT K_P] > 'P' -35-(modif:2-0) + [NCAPS RALT K_P] > 'P' +35-(modif:0-1) + [NCAPS K_P] > 'p' +35-(modif:1-0) + [SHIFT NCAPS K_P] > 'P' +35-(modif:1-1) + [RIGHTSHIFT NCAPS K_P] > 'P' +35-(modif:1-2) + [LEFTSHIFT NCAPS K_P] > 'P' +35-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_P] > 'P' +35-(modif:2-0) + [CAPS K_P] > 'P' +35-(modif:3-0) + [NCAPS RALT K_P] > 'π' +35-(modif:4-0) + [SHIFT NCAPS RALT K_P] > '∏' +35-(modif:5-0) + [CAPS RALT K_P] > '∏' +35-(modif:6-0) + [NCAPS RALT K_P] > 'π' +35-(modif:7-0) + [NCAPS CTRL K_P] > '' +35-(modif:7-1) + [NCAPS RALT CTRL K_P] > '' 36-(modif:0-0) + [NCAPS K_ENTER] > ' ' -36-(modif:1-0) + [NCAPS SHIFT K_ENTER] > ' ' -36-(modif:2-0) + [NCAPS RALT K_ENTER] > ' ' +36-(modif:0-1) + [NCAPS K_ENTER] > ' ' +36-(modif:1-0) + [SHIFT NCAPS K_ENTER] > ' ' +36-(modif:1-1) + [RIGHTSHIFT NCAPS K_ENTER] > ' ' +36-(modif:1-2) + [LEFTSHIFT NCAPS K_ENTER] > ' ' +36-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_ENTER] > ' ' +36-(modif:2-0) + [CAPS K_ENTER] > ' ' +36-(modif:3-0) + [NCAPS RALT K_ENTER] > ' ' +36-(modif:4-0) + [SHIFT NCAPS RALT K_ENTER] > ' ' +36-(modif:5-0) + [CAPS RALT K_ENTER] > ' ' +36-(modif:6-0) + [NCAPS RALT K_ENTER] > ' ' +36-(modif:7-0) + [NCAPS CTRL K_ENTER] > ' ' +36-(modif:7-1) + [NCAPS RALT CTRL K_ENTER] > ' ' 37-(modif:0-0) + [NCAPS K_L] > 'l' -37-(modif:1-0) + [NCAPS SHIFT K_L] > 'L' -37-(modif:2-0) + [NCAPS RALT K_L] > 'L' +37-(modif:0-1) + [NCAPS K_L] > 'l' +37-(modif:1-0) + [SHIFT NCAPS K_L] > 'L' +37-(modif:1-1) + [RIGHTSHIFT NCAPS K_L] > 'L' +37-(modif:1-2) + [LEFTSHIFT NCAPS K_L] > 'L' +37-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_L] > 'L' +37-(modif:2-0) + [CAPS K_L] > 'L' +37-(modif:3-0) + [NCAPS RALT K_L] > '¬' +37-(modif:4-0) + [SHIFT NCAPS RALT K_L] > 'ˇ' +37-(modif:5-0) + [CAPS RALT K_L] > '¬' +37-(modif:6-0) + [NCAPS RALT K_L] > '¬' +37-(modif:7-0) + [NCAPS CTRL K_L] > ' ' +37-(modif:7-1) + [NCAPS RALT CTRL K_L] > ' ' 38-(modif:0-0) + [NCAPS K_J] > 'j' -38-(modif:1-0) + [NCAPS SHIFT K_J] > 'J' -38-(modif:2-0) + [NCAPS RALT K_J] > 'J' - -39-(modif:0-0) + [NCAPS K_QUOTE] > ''' -39-(modif:1-0) + [NCAPS SHIFT K_QUOTE] > '"' -39-(modif:2-0) + [NCAPS RALT K_QUOTE] > ''' +38-(modif:0-1) + [NCAPS K_J] > 'j' +38-(modif:1-0) + [SHIFT NCAPS K_J] > 'J' +38-(modif:1-1) + [RIGHTSHIFT NCAPS K_J] > 'J' +38-(modif:1-2) + [LEFTSHIFT NCAPS K_J] > 'J' +38-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_J] > 'J' +38-(modif:2-0) + [CAPS K_J] > 'J' +38-(modif:3-0) + [NCAPS RALT K_J] > 'ª' +38-(modif:4-0) + [SHIFT NCAPS RALT K_J] > '˝' +38-(modif:5-0) + [CAPS RALT K_J] > 'ª' +38-(modif:6-0) + [NCAPS RALT K_J] > 'ª' +38-(modif:7-0) + [NCAPS CTRL K_J] > ' ' +38-(modif:7-1) + [NCAPS RALT CTRL K_J] > ' ' + +39-(modif:0-0) + [NCAPS K_QUOTE] > 'à' +39-(modif:0-1) + [NCAPS K_QUOTE] > 'à' +39-(modif:1-0) + [SHIFT NCAPS K_QUOTE] > '°' +39-(modif:1-1) + [RIGHTSHIFT NCAPS K_QUOTE] > '°' +39-(modif:1-2) + [LEFTSHIFT NCAPS K_QUOTE] > '°' +39-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_QUOTE] > '°' +39-(modif:2-0) + [CAPS K_QUOTE] > 'à' +39-(modif:3-0) + [NCAPS RALT K_QUOTE] > '#' +39-(modif:4-0) + [SHIFT NCAPS RALT K_QUOTE] > '∞' +39-(modif:5-0) + [CAPS RALT K_QUOTE] > '#' +39-(modif:6-0) + [NCAPS RALT K_QUOTE] > '#' +39-(modif:7-0) + [NCAPS CTRL K_QUOTE] > '%' +39-(modif:7-1) + [NCAPS RALT CTRL K_QUOTE] > '%' 40-(modif:0-0) + [NCAPS K_K] > 'k' -40-(modif:1-0) + [NCAPS SHIFT K_K] > 'K' -40-(modif:2-0) + [NCAPS RALT K_K] > 'K' - -41-(modif:0-0) + [NCAPS K_COLON] > ';' -41-(modif:1-0) + [NCAPS SHIFT K_COLON] > ':' -41-(modif:2-0) + [NCAPS RALT K_COLON] > ';' - -42-(modif:0-0) + [NCAPS K_BKSLASH] > '\' -42-(modif:1-0) + [NCAPS SHIFT K_BKSLASH] > '|' -42-(modif:2-0) + [NCAPS RALT K_BKSLASH] > '\' +40-(modif:0-1) + [NCAPS K_K] > 'k' +40-(modif:1-0) + [SHIFT NCAPS K_K] > 'K' +40-(modif:1-1) + [RIGHTSHIFT NCAPS K_K] > 'K' +40-(modif:1-2) + [LEFTSHIFT NCAPS K_K] > 'K' +40-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_K] > 'K' +40-(modif:2-0) + [CAPS K_K] > 'K' +40-(modif:3-0) + [NCAPS RALT K_K] > 'º' +40-(modif:4-0) + [SHIFT NCAPS RALT K_K] > '˛' +40-(modif:5-0) + [CAPS RALT K_K] > 'º' +40-(modif:6-0) + [NCAPS RALT K_K] > 'º' +40-(modif:7-0) + [NCAPS CTRL K_K] > ' ' +40-(modif:7-1) + [NCAPS RALT CTRL K_K] > ' ' + +41-(modif:0-0) + [NCAPS K_COLON] > 'ò' +41-(modif:0-1) + [NCAPS K_COLON] > 'ò' +41-(modif:1-0) + [SHIFT NCAPS K_COLON] > 'ç' +41-(modif:1-1) + [RIGHTSHIFT NCAPS K_COLON] > 'ç' +41-(modif:1-2) + [LEFTSHIFT NCAPS K_COLON] > 'ç' +41-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_COLON] > 'ç' +41-(modif:2-0) + [CAPS K_COLON] > 'ò' +41-(modif:3-0) + [NCAPS RALT K_COLON] > '@' +41-(modif:4-0) + [SHIFT NCAPS RALT K_COLON] > 'Ç' +41-(modif:5-0) + [CAPS RALT K_COLON] > '@' +41-(modif:6-0) + [NCAPS RALT K_COLON] > '@' +41-(modif:7-0) + [NCAPS CTRL K_COLON] > ' ' +41-(modif:7-1) + [NCAPS RALT CTRL K_COLON] > ' ' + +42-(modif:0-0) + [NCAPS K_BKSLASH] > 'ù' +42-(modif:0-1) + [NCAPS K_BKSLASH] > 'ù' +42-(modif:1-0) + [SHIFT NCAPS K_BKSLASH] > '§' +42-(modif:1-1) + [RIGHTSHIFT NCAPS K_BKSLASH] > '§' +42-(modif:1-2) + [LEFTSHIFT NCAPS K_BKSLASH] > '§' +42-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_BKSLASH] > '§' +42-(modif:2-0) + [CAPS K_BKSLASH] > 'ù' +42-(modif:3-0) + [NCAPS RALT K_BKSLASH] > '¶' +42-(modif:4-0) + [SHIFT NCAPS RALT K_BKSLASH] > '◊' +42-(modif:5-0) + [CAPS RALT K_BKSLASH] > '¶' +42-(modif:6-0) + [NCAPS RALT K_BKSLASH] > '¶' +42-(modif:7-0) + [NCAPS CTRL K_BKSLASH] > '°' +42-(modif:7-1) + [NCAPS RALT CTRL K_BKSLASH] > '°' 43-(modif:0-0) + [NCAPS K_COMMA] > ',' -43-(modif:1-0) + [NCAPS SHIFT K_COMMA] > '<' -43-(modif:2-0) + [NCAPS RALT K_COMMA] > ',' - -44-(modif:0-0) + [NCAPS K_SLASH] > '/' -44-(modif:1-0) + [NCAPS SHIFT K_SLASH] > '?' -44-(modif:2-0) + [NCAPS RALT K_SLASH] > '/' - -45-(modif:0-0) + [NCAPS K_N] > 'n' -45-(modif:1-0) + [NCAPS SHIFT K_N] > 'N' -45-(modif:2-0) + [NCAPS RALT K_N] > 'N' +43-(modif:0-1) + [NCAPS K_COMMA] > ',' +43-(modif:1-0) + [SHIFT NCAPS K_COMMA] > ';' +43-(modif:1-1) + [RIGHTSHIFT NCAPS K_COMMA] > ';' +43-(modif:1-2) + [LEFTSHIFT NCAPS K_COMMA] > ';' +43-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_COMMA] > ';' +43-(modif:2-0) + [CAPS K_COMMA] > ',' +43-(modif:3-0) + [NCAPS RALT K_COMMA] > '…' +43-(modif:5-0) + [CAPS RALT K_COMMA] > '…' +43-(modif:6-0) + [NCAPS RALT K_COMMA] > '…' +43-(modif:7-0) + [NCAPS CTRL K_COMMA] > '.' +43-(modif:7-1) + [NCAPS RALT CTRL K_COMMA] > '.' + +44-(modif:0-0) + [NCAPS K_SLASH] > '-' +44-(modif:0-1) + [NCAPS K_SLASH] > '-' +44-(modif:1-0) + [SHIFT NCAPS K_SLASH] > '_' +44-(modif:1-1) + [RIGHTSHIFT NCAPS K_SLASH] > '_' +44-(modif:1-2) + [LEFTSHIFT NCAPS K_SLASH] > '_' +44-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_SLASH] > '_' +44-(modif:2-0) + [CAPS K_SLASH] > '-' +44-(modif:3-0) + [NCAPS RALT K_SLASH] > '–' +44-(modif:4-0) + [SHIFT NCAPS RALT K_SLASH] > '—' +44-(modif:5-0) + [CAPS RALT K_SLASH] > '–' +44-(modif:6-0) + [NCAPS RALT K_SLASH] > '–' +44-(modif:7-0) + [NCAPS CTRL K_SLASH] > '!' +44-(modif:7-1) + [NCAPS RALT CTRL K_SLASH] > '!' + +45-(modif:4-0) + [SHIFT NCAPS RALT K_N] > 'Ó' +45-(modif:5-0) + [CAPS RALT K_N] > '˜' +45-(modif:6-0) + [NCAPS RALT K_N] > '˜' +45-(modif:7-0) + [NCAPS CTRL K_N] > '' +45-(modif:7-1) + [NCAPS RALT CTRL K_N] > '' 46-(modif:0-0) + [NCAPS K_M] > 'm' -46-(modif:1-0) + [NCAPS SHIFT K_M] > 'M' -46-(modif:2-0) + [NCAPS RALT K_M] > 'M' +46-(modif:0-1) + [NCAPS K_M] > 'm' +46-(modif:1-0) + [SHIFT NCAPS K_M] > 'M' +46-(modif:1-1) + [RIGHTSHIFT NCAPS K_M] > 'M' +46-(modif:1-2) + [LEFTSHIFT NCAPS K_M] > 'M' +46-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_M] > 'M' +46-(modif:2-0) + [CAPS K_M] > 'M' +46-(modif:3-0) + [NCAPS RALT K_M] > 'µ' +46-(modif:4-0) + [SHIFT NCAPS RALT K_M] > 'Ú' +46-(modif:5-0) + [CAPS RALT K_M] > 'µ' +46-(modif:6-0) + [NCAPS RALT K_M] > 'µ' +46-(modif:7-0) + [NCAPS CTRL K_M] > '?' +46-(modif:7-1) + [NCAPS RALT CTRL K_M] > '?' 47-(modif:0-0) + [NCAPS K_PERIOD] > '.' -47-(modif:1-0) + [NCAPS SHIFT K_PERIOD] > '>' -47-(modif:2-0) + [NCAPS RALT K_PERIOD] > '.' +47-(modif:0-1) + [NCAPS K_PERIOD] > '.' +47-(modif:1-0) + [SHIFT NCAPS K_PERIOD] > ':' +47-(modif:1-1) + [RIGHTSHIFT NCAPS K_PERIOD] > ':' +47-(modif:1-2) + [LEFTSHIFT NCAPS K_PERIOD] > ':' +47-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_PERIOD] > ':' +47-(modif:2-0) + [CAPS K_PERIOD] > '.' +47-(modif:3-0) + [NCAPS RALT K_PERIOD] > '•' +47-(modif:4-0) + [SHIFT NCAPS RALT K_PERIOD] > '·' +47-(modif:5-0) + [CAPS RALT K_PERIOD] > '•' +47-(modif:6-0) + [NCAPS RALT K_PERIOD] > '•' +47-(modif:7-0) + [NCAPS CTRL K_PERIOD] > '/' +47-(modif:7-1) + [NCAPS RALT CTRL K_PERIOD] > '/' 48-(modif:0-0) + [NCAPS K_BKSLASH] > ' ' -48-(modif:1-0) + [NCAPS SHIFT K_BKSLASH] > ' ' -48-(modif:2-0) + [NCAPS RALT K_BKSLASH] > ' ' - - -[NCAPS K_BKQUOTE] > dk(005e) -[NCAPS SHIFT K_BKQUOTE] > dk(005e) -[NCAPS RALT K_BKQUOTE] > dk(005e) -[CAPS K_BKQUOTE] > dk(005e) -[SHIFT NCAPS RALT K_BKQUOTE] > dk(005e) -[NCAPS K_EQUAL] > dk(00b4) -[NCAPS SHIFT K_EQUAL] > dk(00b4) -[NCAPS RALT K_EQUAL] > dk(00b4) -[CAPS K_EQUAL] > dk(00b4) -[SHIFT NCAPS RALT K_EQUAL] > dk(00b4) -[NCAPS K_EQUAL] > dk(0060) -[NCAPS SHIFT K_EQUAL] > dk(0060) -[NCAPS RALT K_EQUAL] > dk(0060) -[CAPS K_EQUAL] > dk(0060) -[SHIFT NCAPS RALT K_EQUAL] > dk(0060) +48-(modif:0-1) + [NCAPS K_BKSLASH] > ' ' +48-(modif:1-0) + [SHIFT NCAPS K_BKSLASH] > ' ' +48-(modif:1-1) + [RIGHTSHIFT NCAPS K_BKSLASH] > ' ' +48-(modif:1-2) + [LEFTSHIFT NCAPS K_BKSLASH] > ' ' +48-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_BKSLASH] > ' ' +48-(modif:2-0) + [CAPS K_BKSLASH] > ' ' +48-(modif:3-0) + [NCAPS RALT K_BKSLASH] > ' ' +48-(modif:4-0) + [SHIFT NCAPS RALT K_BKSLASH] > ' ' +48-(modif:5-0) + [CAPS RALT K_BKSLASH] > ' ' +48-(modif:6-0) + [NCAPS RALT K_BKSLASH] > ' ' +48-(modif:7-0) + [NCAPS CTRL K_BKSLASH] > ' ' +48-(modif:7-1) + [NCAPS RALT CTRL K_BKSLASH] > ' ' + +########## OK ################################################################# + +NOW MY C4 RULES **ccc ********* (only to get 02C6 ect) ********************* + ++ [NCAPS K_EQUAL] > dk(02C6) ++ [NCAPS RALT K_EQUAL] > dk(02C6) ++ [NCAPS RALT K_9] > dk(0060) ++ [NCAPS RALT K_8] > dk(00B4) ++ [NCAPS RALT K_U] > dk(00A8) ++ [NCAPS RALT K_N] > dk(02DC) + +########## OK ################################################################# match > use(deadkeys) + group(deadkeys) -store(dkf005e) 'a' 'e' 'o' 'u' 'i' -store(dkt005e) 'â' 'ê' 'ô' 'û' 'î' -store(dkf0060) 'a' 'e' 'o' 'u' 'i' -store(dkt0060) 'à' 'è' 'ò' 'ù' 'ì' -store(dkf00b4) 'a' 'e' 'u' 'i' -store(dkt00b4) 'á' 'á' 'ú' 'í' +dk: 02C6 +deadkeyablesArray'a' 'A' 'e' 'E' 'o' 'O' 'u' 'U' 'i' 'I' +deadkeyedArray 'â' 'Â' 'ê' 'Ê' 'ô' 'Ô' 'û' 'Û' 'î' 'Î' + +dk: 02C6 +deadkeyablesArray'a' 'A' 'e' 'E' 'o' 'O' 'u' 'U' 'i' 'I' +deadkeyedArray 'â' 'Â' 'ê' 'Ê' 'ô' 'Ô' 'û' 'Û' 'î' 'Î' + +dk: 0060 +deadkeyablesArray'a' 'A' 'e' 'E' 'o' 'O' 'u' 'U' 'i' 'I' +deadkeyedArray 'à' 'À' 'è' 'È' 'ò' 'Ò' 'ù' 'Ù' 'ì' 'Ì' + +dk: 00B4 +deadkeyablesArray'a' 'A' 'e' 'E' 'o' 'O' 'u' 'U' 'i' 'I' +deadkeyedArray 'á' 'Á' 'é' 'É' 'ó' 'Ó' 'ú' 'Ú' 'í' 'Í' + +dk: 00A8 +deadkeyablesArray'a' 'A' 'e' 'E' 'y' 'Y' 'o' 'O' 'u' 'U' 'i' 'I' +deadkeyedArray 'ä' 'Ä' 'ë' 'Ë' 'ÿ' 'Ÿ' 'ö' 'Ö' 'ü' 'Ü' 'ï' 'Ï' +dk: 02DC +deadkeyablesArray'a' 'A' 'o' 'O' 'n' 'N' +deadkeyedArray 'ã' 'Ã' 'õ' 'Õ' 'ñ' 'Ñ' diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index f09cefac6d9..2fe6f7d595d 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -119,18 +119,11 @@ function boxArrays_S(source: any) { export interface convert_object { name: string, // needed?? remove - ArrayOf_Element_Layouts: string[], // needed?? I think no ArrayOf_Element_KeyOutput: Uint8Array[][], - ArrayOf_Element_KeyAction: Uint8Array[][], ArrayOf_Element_ALL_ModifierMaps: string[], ArrayOf_Element_ModifierMaps_ALLKeyMapSelect: string[][], - ArrayOf_Element_Terminators: Uint8Array[] // add terminators ( ^,´,`) ArrayOf_processed_VK_from_keylayout: (string | number)[][], - ArrayOf_processed_dk: string[][], // add dk-mapping ( dk1 <-> '^' ) - ArrayOf_processed_deadkeyables: string[][], // add char that can be modified with dk ( a,e,i,o,u) - ArrayOf_processed_deadkeyedChar: string[][], // add modified keys ( â,ê,î,ô,û) ArrayOf_processed_RuleData: Uint8Array[][], // add modified keys ( â,ê,î,ô,û) - ArrayOf_processed_dk_U8: Uint8Array[][] }; @@ -191,6 +184,23 @@ export class KeylayoutToKmnConverter { */ public read(filename: string): convert_object { + //const layouts_array: any[] = [] + const keys_output_all_Layers: Uint8Array[][] = [] + const modifierMap_all_Layers: string[] = [] // array holding all MODIFIER strings e.g. "anyShift caps anyOption" -why not put modifiers into Uint8Array along with values of keys of layer + const modifierMap_ALL_KeyMapSelects: string[][] = [] // modifier for each keymapselect + const kmn_Rules_AllLayers: Uint8Array[][] = [] + const vk: (string | number)[][] = [] + + // TODO remove unneccassary elements + const DataObject: convert_object = { + name: "Ukelele-kmn", // needed?? remove + ArrayOf_Element_KeyOutput: keys_output_all_Layers, + ArrayOf_Element_ALL_ModifierMaps: modifierMap_all_Layers, // all 18 modifiers in 1 array + ArrayOf_Element_ModifierMaps_ALLKeyMapSelect: modifierMap_ALL_KeyMapSelects, // 18 modifiers in 8 KeyMapSelect(behaviors) + ArrayOf_processed_VK_from_keylayout: vk, + ArrayOf_processed_RuleData: kmn_Rules_AllLayers, + }; + console.log("inputFilename read", filename) const options = { ignoreAttributes: false, @@ -207,50 +217,15 @@ export class KeylayoutToKmnConverter { const xmlFile1 = this.callbacks.loadFile(fullPath) console.log("xmlFile1",xmlFile1)*/ - - console.log("layouts_array read ") const parser = new XMLParser(options); const jsonObj = parser.parse(xmlFile); // get plain Object - const modifierMap_ALL_KeyMapSelects: string[][] = [] // modifier for each keymapselect - const modifierMap_all_Layers: string[] = [] // array holding all MODIFIER strings e.g. "anyShift caps anyOption" -why not put modifiers into Uint8Array along with values of keys of layer - const keys_output_all_Layers: Uint8Array[][] = [] - const keys_action_all_Layers: Uint8Array[][] = [] // array holding all values with ACTION attribute (needed for finding deadkeys) - const terminators_all_Layers: Uint8Array[] = [] // array holding all DEADKEYS for each mod state â, ê, ,.... - const duplicate_layouts_array: string[] = [] // array holding the layouts e.g. ANSI or JIS // needed?? I think no - const deadkeyedChars_all_Layers: string[][] = [] // array holding all DEADKEYS for each mod state â, ê, ,.... - const kmn_Rules_AllLayers: Uint8Array[][] = [] - let dk_pairs_all_Layers: string[][] = [] // add dk-mapping ( dk1 <-> '^' ) - const dk_pairs_all_Layers_U8: Uint8Array[][] = [] // add dk-mapping ( dk1 <-> '^' ) - - boxArrays_S(jsonObj.keyboard); - // fill arrays - // TODO call: get only ANSI - // Do I need to care or is there always ANSI which is always keyMapSet[0] - // if so code can be shortened - // ......................................................... - // LAYOUTS: get all groups like ANSI JIS, remove JIS - // ......................................................... + // const duplicate_layouts_array: string[] = [] // array holding the layouts e.g. ANSI or JIS // needed?? I think no - // in case we need to find ANSI - for (let i = 0; i < jsonObj.keyboard.layouts.layout.length; i++) { - duplicate_layouts_array[i] = jsonObj.keyboard.layouts.layout[i]['@_mapSet'] - } + boxArrays_S(jsonObj.keyboard); - // remove duplicates - const layouts_array: any[] = duplicate_layouts_array.filter(function (item, pos, self) { - return self.indexOf(item) == pos; - }) - // remove JIS (if keyMap contains baseMapSet it`s JIS) - for (let i = 0; i < layouts_array.length; i++) { - if (jsonObj.keyboard.keyMapSet[i].keyMap[0]['@_baseMapSet']) - layouts_array.splice(i, 1); - } // in case there always ANSI which is always keyMapSet[0] - //const layouts_array: string[] = duplicate_layouts_array - const keyMapSet_count = 0 - - //#### end layouts ############################################################################################################################################### + const keyMapSet_ANSI_count = 0 // ......................................................... // MODIFIER MAP: get behaviours(=MapIndex) and modifiers (shift? leftShift caps? ) @@ -264,244 +239,33 @@ export class KeylayoutToKmnConverter { } modifierMap_ALL_KeyMapSelects.push(modifierMap_ONE_InKeymapSelect) } - //#### end modifierMap ############################################################################################################################################### - + // ......................................................... + // KEYMAP - OUTPUT : get all keys for attribute "output" ( y,c,b,...) + // output type Uint8Array -> string + // ......................................................... for (let j = 0; j < jsonObj.keyboard.modifierMap.keyMapSelect.length; j++) { // create a new array of keys_in_Layer (type Uint8tarray) const keys_output_One_Layer: Uint8Array[] = [] - const keys_action_One_Layer: Uint8Array[] = [] - - // ......................................................... - // KEYMAP - OUTPUT : get all keys for attribute "output" ( y,c,b,...) - TODO can i use shorter function? - // output type Uint8Array -> string - // ......................................................... // loop keys - for (let i = 0; i < jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap[j].key.length; i++) { - if (jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap[j].key[i]['@_output'] !== "\0") { + for (let i = 0; i < jsonObj.keyboard.keyMapSet[keyMapSet_ANSI_count].keyMap[j].key.length; i++) { + if (jsonObj.keyboard.keyMapSet[keyMapSet_ANSI_count].keyMap[j].key[i]['@_output'] !== "\0") { // textencoder converts string -> bytes ( 'A' -> [ 65 ], '☺' -> [ 226, 152, 186 ]) // textencoder is of Uint8Array(1) for A and Uint8Array(3) for ☺ - keys_output_One_Layer[i] = new TextEncoder().encode(jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap[j].key[i]['@_output']); - } - // ToDo do I need empty fields in keys_output_all_Layers, keys_action_all_Layers - // ......................................................... - // KEYMAP - ACTION: get all keys for attribute "action" ( ^,a,e,i,...) - TODO can i use shorter function? - // action type Uint8Array -> string - // ......................................................... - else if (jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap[j].key[i]['@_action'] !== "\0") { - keys_action_One_Layer[i] = new TextEncoder().encode(jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap[j].key[i]['@_action']); + keys_output_One_Layer[i] = new TextEncoder().encode(jsonObj.keyboard.keyMapSet[keyMapSet_ANSI_count].keyMap[j].key[i]['@_output']); } } - - // ......................................................... - // create array of "action" and array of "output" + // create array of "output" keys_output_all_Layers.push(keys_output_One_Layer) // save all @output data ( will be used for conversion, write...) - keys_action_all_Layers.push(keys_action_One_Layer) // save all @action data ( will be used for deadkeys) - - - //#### end output+action ############################################################################################################################################### - } - - // ......................................................... - // ACTION: create array of "deadkey" / "deadkey names" - TODO can i use shorter function? - // action type string[] -> string[][] - // ......................................................... - const dk_pairs_all_Layers_max: string[][] = [] - // here replace with function to find - // C3 state none + next Nr => deadkeys - console.log("--------------------------------") - - // loop through actions and get the value of attribute "next" (which indicates this is a deadkey) - for (let jj = 0; jj < jsonObj.keyboard.actions.action.length; jj++) { - for (let kk = 0; kk < jsonObj.keyboard.actions.action[jj].when.length; kk++) { - - if (jsonObj.keyboard.actions.action[jj].when[kk]['@_next'] !== undefined) { - const vec1d: string[] = [] - let dk_to_print - - const text_attribute_next = jsonObj.keyboard.actions.action[jj].when[kk]['@_next'] - - // loop through terminators and get output of that next state - for (let n = 0; n < jsonObj.keyboard.terminators.when.length; n++) { - if (jsonObj.keyboard.terminators.when[n]['@_state'] === text_attribute_next) - dk_to_print = jsonObj.keyboard.terminators.when[n]['@_output'] - } - - vec1d.push(text_attribute_next) - vec1d.push(dk_to_print) - vec1d.push(jsonObj.keyboard.actions.action[jj]['@_id']) // todo remove later - dk_pairs_all_Layers_max.push(vec1d) - } - } - } - dk_pairs_all_Layers = dk_pairs_all_Layers_max.filter(function (item, pos, self) { - return self.indexOf(item) == pos; - }) - console.log("dk_pairs_all_Layers", dk_pairs_all_Layers) - const dk: string[] = []; - - // ......................................................... - // ACTION: create array of "deadkeyables_all_Layers" - TODO can i use shorter function? - // deadkeyables_one type Uint8Array -> string[][] - // ......................................................... - const deadkeyables_all_Layers: string[][] = [] - // needed? we just want ANSI = the first one - for (let j = 0; j < jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap.length; j++) { - const deadkeyables_one: string[] = [] - // loop through all keys of ANSI - for (let i = 0; i < jsonObj.keyboard.keyMapSet[keyMapSet_count].keyMap[0].key.length; i++) { - - let dk_char - // find output in action id - for (let jj = 0; jj < jsonObj.keyboard.actions.action.length; jj++) { - - // find the action ID which was specified in keymap->key->action e.g. a19 - const action_name = new TextDecoder().decode(keys_action_all_Layers[j][i]) - - if (action_name !== "") { - //console.log("ction_name",action_name) - // find action id in actions->action e.g. a19 - if (jsonObj.keyboard.actions.action[jj]['@_id'] === action_name) { - - //a85 - - // 4 cases: - // C1 state none + output => - // C2 state Nr + output => - // OK C3 state none + next Nr => deadkeys see above - // C4 state Nr + next Nr => loop deadkeyables - - - if (jsonObj.keyboard.actions.action[jj].when[0]['@_state'] === "none") { - dk_char = jsonObj.keyboard.actions.action[jj].when[0]['@_output'] - /* console.log("++++++++++++++++++++++dk_char", j, i, jj, "action_name", action_name, - jsonObj.keyboard.actions.action[jj].when[0], "===>", dk_char, "mytestVar", mytestVar)*/ - - // if @_next instead of @_output - // loop again - // and again... again...( -> recursive func!!) - } - } - } - } - // fills correct entries into modifier 1-3 then false ( because of no action any more) - - //const resulting_character = new TextDecoder().decode(keys_action_all_Layers[j][i]) - const resulting_character = dk_char - - if (resulting_character !== "") - deadkeyables_one.push(resulting_character) - } - for (let k = 0; k < dk_pairs_all_Layers.length; k++) { - dk.push(dk_pairs_all_Layers[k][1]) - } - - if (deadkeyables_one.length !== 0) { - deadkeyables_all_Layers.push(deadkeyables_one) - } } - //console.log("deadkeyables_all_Layers before",deadkeyables_all_Layers) - for (let j = 0; j < deadkeyables_all_Layers.length; j++) { - // filter out dk -> plain deadkeyables_all_Layers ( a,^, e,i,´,u => a,e,i,u) - // return all that don`t find ^,´, ` - deadkeyables_all_Layers[j] = deadkeyables_all_Layers[j].filter(function (el) { - return dk.indexOf(el) < 0; - }); - } - - //console.log("deadkeyables_all_Layers after", deadkeyables_all_Layers) - - //double??? // ......................................................... - // TERMINATOR: create array of "terminators" - TODO can i use shorter function? what element of terminators do i need - // terminators when state type Uint8Array[] + // KEYMAP - ACTION : get all keys for attribute "action" + // output type Uint8Array -> string // ......................................................... - for (let i = 0; i < jsonObj.keyboard.terminators.when.length; i++) { - terminators_all_Layers[i] = jsonObj.keyboard.terminators.when[i] - } - - // ......................................................... - // TODO can i use shorter function? -> yes use terminators, filter, map or reduce - - // this addresses state+output and none+output - // but not state+next or none+next - - // loop through all dk, key-actions and find @_action - // find this value in - // in their 'when' find output for dk - // for all 'action' at keys paragraph - - // ToDo URTGENT duplicate dk ????? - // todo use lookup functions - for (let j = 0; j < dk_pairs_all_Layers.length; j++) { - //for (let j = 0; j < keys_action_all_Layers.length; j++) { - const deadkeys_One_dk: string[] = [] - // find in action e.g. - for (let k = 0; k < keys_action_all_Layers[j].length; k++) { - - const action_from_keys_prargraph = new TextDecoder().decode(keys_action_all_Layers[j][k]) - if (action_from_keys_prargraph !== "") { - // find the same id (e.g. ) in the actions-paragraph - for (let l = 0; l < jsonObj.keyboard.actions.action.length; l++) { - - if (jsonObj.keyboard.actions.action[l]['@_id'] === action_from_keys_prargraph) { - // loop through when until dk name (e.g. dk s0) - for (let m = 0; m < jsonObj.keyboard.actions.action[l].when.length; m++) { - - // and get their @_output - if (jsonObj.keyboard.actions.action[l].when[m]['@_state'] === dk_pairs_all_Layers[j][0]) { - // todo push only if @output is found. if next is found: get value from terminators - //if (typeof jsonObj.keyboard.actions.action[l].when[m]['@_output'].property !== 'undefined') - deadkeys_One_dk.push(jsonObj.keyboard.actions.action[l].when[m]['@_output']) - //else - //console.log(deadkeys_One_dk, "§§§§§§ PROP UNDEFINED", j, "-", k, "-", l, "-", m, "-", dk_pairs_all_Layers[j][0], jsonObj.keyboard.actions.action[l].when[m].property) - } - } - } - } - } - - } - // do e clear - - // consoleconsole.log("deadkeys_One_dk", deadkeys_One_dk) - deadkeyedChars_all_Layers.push(deadkeys_One_dk) - - - //console.consolelog("deadkeyedChars_all_Layers", deadkeyedChars_all_Layers) - } - - - const vk: (string | number)[][] = [] - - // TODO remove unneccassary elements - const DataObject: convert_object = { - name: "Ukelele-kmn", // needed?? remove - ArrayOf_Element_Layouts: layouts_array, // needed?? I think no - ArrayOf_Element_KeyOutput: keys_output_all_Layers, - ArrayOf_Element_KeyAction: keys_action_all_Layers, - ArrayOf_Element_ALL_ModifierMaps: modifierMap_all_Layers, // all 18 modifiers in 1 array - ArrayOf_Element_ModifierMaps_ALLKeyMapSelect: modifierMap_ALL_KeyMapSelects, // 18 modifiers in 8 KeyMapSelect(behaviors) - ArrayOf_Element_Terminators: terminators_all_Layers, // add terminators ( ^,´,`) - ArrayOf_processed_VK_from_keylayout: vk, - ArrayOf_processed_dk: dk_pairs_all_Layers, // add dk-mapping ( dk1 <-> '^' ) - ArrayOf_processed_deadkeyables: deadkeyables_all_Layers, // add char that can be modified with dk ( a,e,i,o,u) - ArrayOf_processed_deadkeyedChar: deadkeyedChars_all_Layers, // add modified keys ( â,ê,î,ô,û) - ArrayOf_processed_RuleData: kmn_Rules_AllLayers, - ArrayOf_processed_dk_U8: dk_pairs_all_Layers_U8 - }; - // Todo ? move to convert? - // move up instead of action/output? - // do i need to return a value? - const rule_Data = this.createRuleData(DataObject, jsonObj) - - console.log("rule_Data-lenU8", rule_Data.ArrayOf_processed_RuleData.length) - //console.log("rule_Data_U8", rule_Data.ArrayOf_processed_RuleData) - // TODO review condition - return rule_Data + return this.createRuleData(DataObject, jsonObj) //return ((keys_output_all_Layers.length === nrOfStates + 5) && keys_output_all_Layers[0].length === nrOfKeys_inLayer) ? keys_output_all_Layers : null; } @@ -513,7 +277,6 @@ export class KeylayoutToKmnConverter { * @return outArray Uint8Array keys_all_Layers, the converted data for kmn-files if all layers have been converted; else null */ public convert(data_ukelele: convert_object): convert_object { - const data_VK_from_keylayout: (string | number)[][] = []; for (let i = 0; i < data_ukelele.ArrayOf_Element_KeyOutput[0].length; i++) { @@ -537,7 +300,6 @@ export class KeylayoutToKmnConverter { */ //TODO need to use export const USVirtualKeyCodes here public write(data_ukelele: convert_object): boolean { - console.log("start write") // ************************************************************* // **** write stores ******************************************* @@ -569,12 +331,11 @@ export class KeylayoutToKmnConverter { // **** write rules ******************************************** // *************************************************************^ // todo replace write rules with reading out of rule-array - console.log("start write 1") // if caps is used in .keylayout-file we need to add NCAPS in kmn-file let isCAPSused = false const used_Keys_count = 50 // do we need more than 50 keys?? const modi: string[] = data_ukelele.ArrayOf_Element_ALL_ModifierMaps; - // const modi: string[] = data_ukelele.ArrayOf_Element_ALL_ModifierMaps; // Todo check 2darray of modifiuers + const filteredModifiers: string[] = modi.filter((mod) => (String(mod) === ("caps"))) if (filteredModifiers.indexOf("caps") >= 0) isCAPSused = true @@ -583,7 +344,6 @@ export class KeylayoutToKmnConverter { // find all modifiers used per modifier combination // find resulting character from - // console.log("start write 2, ", "data_ukelele.ArrayOf_ALL_Element_ModifierMaps.length", data_ukelele.ArrayOf_Element_ALL_ModifierMaps.length) // loop through keys //for (let j = 0; j item[0] === data_ukelele.ArrayOf_processed_VK_from_keylayout[j][0]) - //console.log("---", "vk_label", vk_label) - //console.log("start write 2C-", j, i) - //console.log("start write 2C-", j, i, data_ukelele.ArrayOf_Element_KeyOutput[i][j]) // get the character from keymap-section of .keylayout-file that will be written as result in kmn-file const resulting_character = new TextDecoder().decode(data_ukelele.ArrayOf_Element_KeyOutput[ii][j]) - //console.log("start write 2D") // TODO remove j +"(modif:" + i + `) if (resulting_character !== '') { - //console.log("start write 2E") // e.g. [ NCAPS K_J ] > ' j ' data += j + "-(modif:" + ii + "-" + i + `) + [` + (label_modifier + ' ' + vk_label[0][1]).trim() + `] > \'` + resulting_character + '\'\n' } - //console.log("start write 2F") } } - //console.log("start write 2G") } - //......................................................................... - // end write out ........................................................ - //......................................................................... - //......................................................................... - const NEWDATA = this.writeLastPart(data_ukelele, isCAPSused) data += NEWDATA + '\n' - // console.log("start write 5") /*writeFileSync("data/MyResult.kmn", data, { flag: "w" })*/ const data_encoded = new TextEncoder().encode(data) this.callbacks.fs.writeFileSync("data/MyResult.kmn", data_encoded) // not usable here since it takes UInt8array data @@ -641,366 +388,10 @@ export class KeylayoutToKmnConverter { else return false - - //......................................................................... - // end write out ........................................................ - //......................................................................... - //......................................................................... - - //console.log("start write 3") data += '\n' - - // ************************************************************* - // **** write deadkeys ***************************************** - // ************************************************************* - - - data += 'NOW MY DEADKEYS : \n' - - /* console.log("start write 3: ", - data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect.length, - data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[1].length, - data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[1][1].length, - data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect - ) - for (let i = 0; i < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect.length; i++) { - for (let j = 0; j < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i].length; j++) { - console.log("Element: ", i, j, - data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i][j], - this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i][j], isCAPSused) - ) - } - }*/ - // old - - // all 109 keys with action a9 - for (let i = 0; i < data_ukelele.ArrayOf_Element_KeyAction.length; i++) { - // loop through keyMapSelect (8) - for (let ii = 0; ii < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect.length; ii++) { - //for (let ii = 0; ii < 8; ii++) { - // loop through modifiers - //for (let j = 0; j < data_ukelele.ArrayOf_Element_KeyAction.length; j++) { - // 8 behaviors - for (let j = 0; j < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect.length; j++) { - //console.log("start write 3A", i, ii, j) - - // get the modifier for the layer - //const label_modifier = this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ALL_ModifierMaps[j], isCAPSused) - const label_modifier = this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ALL_ModifierMaps[j], isCAPSused) - - // get the character from keymap-section of .keylayout-file that will be written as result in kmn-file - //const resulting_character = new TextDecoder().decode(data_ukelele.ArrayOf_Element_KeyAction[j][i]) - // wrong since it attempts to convert a9 and not 4 ( the termínator id ) - const resulting_character = new TextDecoder().decode(data_ukelele.ArrayOf_Element_KeyAction[ii][i]) - - // therefore get character from ~ <- 4 <- a9 - //const realChar = this.getCharacterFromActionName(data_ukelele, data_ukelele.ArrayOf_Element_KeyAction[ii][i]) - //console.log("realChar", realChar,i,ii,j ) - // console.log("data_ukelele.ArrayOf_Element_KeyAction[ii][i],", - // data_ukelele.ArrayOf_Element_KeyAction[ii][i], - // realChar) - - if (resulting_character !== "") { - console.log("start write 3B+3C", i, ii, j, label_modifier, "---", resulting_character) - - const VK: (string | number)[][] = data_ukelele.ArrayOf_processed_VK_from_keylayout - const vk_label = VK.filter(item => item[0] === data_ukelele.ArrayOf_processed_VK_from_keylayout[i][0]) - // console.log("VK", VK, "vk_label", vk_label) - - // console.log("start write 3D,data_ukelele.ArrayOf_processed_dk", data_ukelele.ArrayOf_processed_dk) - for (let k = 0; k < data_ukelele.ArrayOf_processed_dk.length; k++) { - console.log("start write 3E") - console.log("resulting_character", resulting_character, "data_ukelele.ArrayOf_processed_dk[k][1]", data_ukelele.ArrayOf_processed_dk[k][1]) - console.log("data_ukelele.ArrayOf_processed_dk is", data_ukelele.ArrayOf_processed_dk) - console.log("resulting_characte, data_ukelele.ArrayOf_processed_dk is", resulting_character, data_ukelele.ArrayOf_processed_dk[k][2]) - if ((resulting_character !== "") && (resulting_character === data_ukelele.ArrayOf_processed_dk[k][2])) { - data += '[' + (label_modifier + ' ' + vk_label[0][1]).trim() + '] ' + "> dk(" + this.getHexFromChar(data_ukelele.ArrayOf_processed_dk[k][1]) + ") " + '\n' - console.log("start write 3D", data) - - } - } - } - } - - } - } - - - - // console.log("start write 4") - data += "\n" - data += "match > use(deadkeys)\n\n" - data += "group(deadkeys)\n" - data += "\n" - //console.log("data_ukelele.ArrayOf_processed_deadkeyables.length", data_ukelele.ArrayOf_processed_deadkeyables.length) - // console.log("data_ukelele.String(data_ukelele.ArrayOf_processed_deadkeyables[i])).length", String(data_ukelele.ArrayOf_processed_deadkeyables[0])) - //console.log("data_ukelele.String(data_ukelele.ArrayOf_processed_deadkeyables[i])).length--", "\'", String(data_ukelele.ArrayOf_processed_deadkeyables[0]).trim().replace(/\,+/g, "' '"),) - - //const char = "\'" + String(data_ukelele.ArrayOf_processed_deadkeyables[0]).trim().replace(/\,+/g, "' '") - //console.log("char", char) - - //const char1 = char.slice(0, -1) - //console.log("char1", char1) - - for (let i = 0; i < data_ukelele.ArrayOf_processed_deadkeyables.length; i++) { - if (data_ukelele.ArrayOf_processed_deadkeyedChar[i] !== undefined) { - data += "store(dkf" + this.getHexFromChar(data_ukelele.ArrayOf_processed_dk[i][1]) + ") " + ("\'" + String(data_ukelele.ArrayOf_processed_deadkeyables[i])).replace(/\,+/g, "' '").slice(0, -1).trim() + "\n" - data += "store(dkt" + this.getHexFromChar(data_ukelele.ArrayOf_processed_dk[i][1]) + ") " + ("\'" + String(data_ukelele.ArrayOf_processed_deadkeyedChar[i])).replace(/\,+/g, "' '") + "'\n" - - data += "store(dkf" + this.getHexFromChar(data_ukelele.ArrayOf_processed_dk[i][1]) + ") " + ("\'" + String(data_ukelele.ArrayOf_processed_deadkeyables[i])).replace(/\,+/g, "' '").slice(0, -1).trim() + "\n" - data += "store(dkt" + this.getHexFromChar(data_ukelele.ArrayOf_processed_dk[i][1]) + ") " + ("\'" + String(data_ukelele.ArrayOf_processed_deadkeyedChar[i])).replace(/\,+/g, "' '") + "'\n" - data += '\n' - } - } - - - //TODO better distinction!!! - data += 'NOW MY RULES ********************************\n' - for (let kkk = 0; kkk < data_ukelele.ArrayOf_processed_RuleData.length; kkk++) { - if (data_ukelele.ArrayOf_processed_RuleData[kkk].length <= 6) { - let line: string = "" - for (let lll = 0; lll < data_ukelele.ArrayOf_processed_RuleData[kkk].length; lll++) { - const entry = new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][lll]) - line += " " + entry + " " - } - data += line + '\n' - } - } - - data += '\nNOW MY C4 RULES *********** (only to get 02C6 ect) *********************\n\n' - for (let kkk = 0; kkk < data_ukelele.ArrayOf_processed_RuleData.length; kkk++) { - if (new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][4]) === "isTerminator") { - let line: string = "" - for (let lll = 0; lll < data_ukelele.ArrayOf_processed_RuleData[kkk].length; lll++) { - const entry = new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][lll]) - line += " " + entry + " " - } - data += line + '\n' - } - } - - - - data += '......................................................\n' - for (let kkk = 0; kkk < data_ukelele.ArrayOf_processed_RuleData.length; kkk++) { - if (new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][4]) === "isTerminator") { - let line: string = "" - const entry = new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][6]) - line += " Hex dk: " + entry + " " - data += line + '\n' - } - } - - // array ony of dk (array_dk_char [ '¨', 'ˆ', '´', '˜', '`' ]) - const array_dk_char = [...new Set(data_ukelele.ArrayOf_processed_dk.map(a => a[1]))]; - console.log("array_dk_char", array_dk_char); - - - data += '\nNOW DEADKEYABLES ********************************\n\n' - - - const deadkeyables_array = [] - // loop al data rules - for (let kkk = 0; kkk < data_ukelele.ArrayOf_processed_RuleData.length; kkk++) { - - // find dk rules - if ((new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][0]) === ("first_modifier_C2")) - && (data_ukelele.ArrayOf_processed_RuleData[kkk].length === 5)) { - - // if char of pos4 is in array_dk_char [ '¨', 'ˆ', '´', '˜', '`' ]) - if (!array_dk_char.includes(new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][4]))) { - deadkeyables_array.push(new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][2])) - } - } - } - - // remove duplicates -> array_deadkeyables_unique1 [ 'K_A', 'K_E', 'K_Y', 'K_O', 'K_U', 'K_I', 'K_N' ] - const array_deadkeyables_unique = deadkeyables_array.filter(function (item, pos, self) { - return self.indexOf(item) == pos; - }) - - - data += " store dk... : " - //console.log("array_deadkeyables_unique", array_deadkeyables_unique) - - for (let i = 0; i < array_deadkeyables_unique.length; i++) { - data += '\'' + array_deadkeyables_unique[i] + '\' ' - } - - data += '\nNOW DEADKEYED ********************************\n\n' - let counter = 0 - const deadkeyed_array = [] - // loop al data rules - for (let kkk = 0; kkk < data_ukelele.ArrayOf_processed_RuleData.length; kkk++) { - - // find dk rules - if ((new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][0]) === ("first_modifier_C2")) - && (data_ukelele.ArrayOf_processed_RuleData[kkk].length === 5)) { - - const deadkeyed_array_1D = [] - if (!array_dk_char.includes(new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][4]))) { - deadkeyed_array_1D.push(new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][1])) - deadkeyed_array_1D.push(new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][2])) - deadkeyed_array_1D.push(new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][3])) - deadkeyed_array_1D.push(new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][4])) - } - deadkeyed_array.push(deadkeyed_array_1D) - counter++ - } - } - - // remove empty - const array_deadkeyed_unique = deadkeyed_array.filter(function (arr) { - return arr.length > 0 - }); - - data += " store dk... : " - // console.log("array_deadkeyed_unique", counter, array_deadkeyed_unique) - - for (let i = 0; i < array_deadkeyed_unique.length; i++) { - if (array_deadkeyed_unique[i].length !== 0) - data += '\n\'' + array_deadkeyed_unique[i] + '\' ' - // console.log("array_deadkeyed_unique[i][1]", array_deadkeyed_unique[i][1]) - } - - // console.log("modiArray", modiArray) - data += '\'\n' - data += '\nNOW DEADKEYS ********************************\n\n' - - - //############################################################################################## - //######################all##################################################################### - - const All_array: any[] = [] - // loop al data rules and push dk rules to array - for (let kkk = 0; kkk < data_ukelele.ArrayOf_processed_RuleData.length; kkk++) { - const deadkeyed_array_1D = [] - deadkeyed_array_1D.push(new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][0])) //modifier - deadkeyed_array_1D.push(new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][1])) //shiftstates - deadkeyed_array_1D.push(new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][2])) //keyname 1 - deadkeyed_array_1D.push(new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][3])) //output character/ keyname 2 / shiftstate 2 - if (data_ukelele.ArrayOf_processed_RuleData[kkk].length === 4) - deadkeyed_array_1D.push(new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][4])) // -- / keyname 2 - else - deadkeyed_array_1D.push("") - if (data_ukelele.ArrayOf_processed_RuleData[kkk].length === 5) - deadkeyed_array_1D.push(new TextDecoder().decode(data_ukelele.ArrayOf_processed_RuleData[kkk][5])) // -- / output character - else - deadkeyed_array_1D.push("") - - if (deadkeyed_array_1D.length > 0) - All_array.push(deadkeyed_array_1D) - counter++ - } - - // - // console.log("All_array", All_array) - data += " store dk... : \n" - - - let All_C1_Shift_Keyname_all - let All_C1_Shift_Keyname - let Shift: any - const modiDeadkeyable1_all_lines: any[][] = [] - const deadkeyables_combi: any[][] = [] - const deadkeyables_combiAndSS: any[][] = [] - - //loop through all behaviours (8) - for (let j = 0; j < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect.length; j++) { - - // for (let j = 0; j < 1; j++) { - let deadkeyables_without_VKspace: any[] = [] - - //loop through all modifiers (4) for behaviour - for (let k = 0; k < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[j].length; k++) { - const deadkeyables_line: any[] = [] - const modiDeadkeyable1_arr: any[] = [] - const deadkeyables_combi2: any[][] = [] - // loop all keys - for (let i = 0; i < 50; i++) { - const Keyname = this.map_UkeleleKC_To_VK(i) - Shift = this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[j][k], isCAPSused) - // const Shift = "CAPS" - // console.log("Keyname", Keyname, "xxShift", Shift) - - - // find deadkeyable [ 'first_modifier_C1', 'CAPS', 'K_A', 'A', '', '', '' ] - All_C1_Shift_Keyname_all = All_array.filter(function ([A, B, C, D, E, F, G]) { - return ((A === "first_modifier_C1") && (B === Shift) && (C === Keyname)) - }); - //console.log("All_C1_Shift_Keyname_all", All_C1_Shift_Keyname_all.length,All_C1_Shift_Keyname_all) - - - - - - All_C1_Shift_Keyname = All_C1_Shift_Keyname_all - - // console.log("All_C1_Shift_Keyname", All_C1_Shift_Keyname.length, All_C1_Shift_Keyname) - - // in case there are more rules-should not be the case - for (let xi = 0; xi < All_C1_Shift_Keyname.length; xi++) { - modiDeadkeyable1_arr.push(All_C1_Shift_Keyname[xi]) - } - - } - - //console.log("modiDeadkeyable1_arr", modiDeadkeyable1_arr.length, modiDeadkeyable1_arr, modiDeadkeyable1_arr[0]) - - - deadkeyables_without_VKspace = modiDeadkeyable1_arr.filter(function (mod) { - return ((mod !== undefined) && (mod[2] !== "K_SPACE")) - }); - console.log("deadkeyables_without_VKspace", deadkeyables_without_VKspace.length, deadkeyables_without_VKspace) - - for (let i = 0; i < deadkeyables_without_VKspace.length; i++) { - //deadkeyables_line.push(deadkeyables_without_VKspace[i][2]) - deadkeyables_line.push(deadkeyables_without_VKspace[i][3]) - - const deadkeyables_line_forC: any[] = [] - for (let zz = 2; zz < 4; zz++) { - deadkeyables_line_forC.push(deadkeyables_without_VKspace[i][zz]) - } - deadkeyables_combi.push(deadkeyables_line_forC) - deadkeyables_combi2.push(deadkeyables_line_forC) - } - - // console.log("deadkeyables_combi2[k][1]", deadkeyables_combi2[k], deadkeyables_combi2[j]) - - if (deadkeyables_line.length != 0) { - modiDeadkeyable1_all_lines.push(deadkeyables_line) - data += "Deadkeyables: " + deadkeyables_line + "\n" - data += "dk : " + deadkeyables_combi2[k][j] + "\n" - } - - deadkeyables_combiAndSS.push(deadkeyables_combi2) - } - // THIS IS DEADKEYABLES OUTPUT - // console.log("modiDeadkeyable1_all_lines", modiDeadkeyable1_all_lines.length, modiDeadkeyable1_all_lines) - } - data += '\n' - - // console.log("deadkeyables_combiAndSS", deadkeyables_combiAndSS) - - - - - - //const NEWDATA = this.writeLastPart(data_ukelele, isCAPSused) - /* data += NEWDATA + '\n' - - // console.log("start write 5") - //writeFileSync("data/MyResult.kmn", data, { flag: "w" }) - const data_encoded = new TextEncoder().encode(data) - this.callbacks.fs.writeFileSync("data/MyResult.kmn", data_encoded) // not usable here since it takes UInt8array data - - // ToDo conditions? - if (data.length > 0) - return true; - else - return false*/ } + //... helpers ............................................................................................. // TODO move outside of class? @@ -1037,20 +428,12 @@ export class KeylayoutToKmnConverter { // loop modifiers for (let l = 0; l < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i].length; l++) { - const DataArraySingleStateC0_U8: Uint8Array[] = [] if (output_id !== "") { const first_modifier_C0_U8 = new TextEncoder().encode(this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i][l], isCapsused)); - const result_C0_U8 = new TextEncoder().encode(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output']); const first_key_C0_U8 = new TextEncoder().encode(this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']))); - - /* console.log("### Key Nr ", - jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], - "[ + C0 modifiers->", i, first_modifier_C0.padEnd(25, " "), "] ", - this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])).padEnd(8, " "), - "> ", - jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'])*/ + const result_C0_U8 = new TextEncoder().encode(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output']); DataArraySingleStateC0_U8.push(new TextEncoder().encode("first_modifier_C0")) DataArraySingleStateC0_U8.push(first_modifier_C0_U8) @@ -1093,14 +476,6 @@ export class KeylayoutToKmnConverter { const first_modifier_C1_U8 = new TextEncoder().encode(this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i][l], isCapsused)) const first_key_C1_U8 = new TextEncoder().encode(this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']))) - /*console.log( - "### Key Nr ", - jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], - "[ + C1 modifiers->", i, first_modifier_C1.padEnd(25, " "), "] ", - this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])).padEnd(8, " "), - "> ", - result_C1)*/ - DataArraySingleStateC1_U8.push(new TextEncoder().encode("first_modifier_C1")) DataArraySingleStateC1_U8.push(first_modifier_C1_U8) DataArraySingleStateC1_U8.push(first_key_C1_U8) @@ -1152,43 +527,14 @@ export class KeylayoutToKmnConverter { // for all modifier combinations for (let l = 0; l < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i].length; l++) { - // const DataArraySingleStateC2: string[] = [] const DataArraySingleStateC2_U8: Uint8Array[] = [] - for (let k = 0; k < nextvalArray.length; k++) { if (result_C2 !== undefined) { - /* const first_modifier_C2 = this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i][l], isCapsused) - const first_Key_C2 = this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])) - const second_Key_C2 = this.map_UkeleleKC_To_VK(Number(this.lookup_11_KeyMapAction__To__KeyMapCode(jsonObj, nextvalArray[k]))) - */ const first_modifier_C2_U8 = new TextEncoder().encode(this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i][l], isCapsused)) const first_Key_C2_U8 = new TextEncoder().encode(this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']))) const second_Key_C2_U8 = new TextEncoder().encode(this.map_UkeleleKC_To_VK(Number(this.lookup_11_KeyMapAction__To__KeyMapCode(jsonObj, nextvalArray[k])))) - /*console.log( - " ### Key Nr", - "nextvalArray.length", nextvalArray.length, - j, - "[ + C2 modifiers->", i, first_modifier_C2.padEnd(25, " "), "] ", - //this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])).padEnd(8, " "), - first_Key_C2.padEnd(8, " "), - "> ", - result_C2, - "\t stateV ->", stateVal, - jsonObj.keyboard.keyMapSet[0].keyMap[i].key[jj]['@_code'], - nextvalArray[k], - - "-", - nextvalArray, - "-----", - "### Key Nr", - "+modixx2 +key nr", - this.lookup_11_KeyMapAction__To__KeyMapCode(jsonObj, nextvalArray[k]), - " +keymapindex of this", - this.lookup_11_KeyMapAction__To__KeyIndex(jsonObj, nextvalArray[k]) - )*/ - DataArraySingleStateC2_U8.push(new TextEncoder().encode("first_modifier_C2")) DataArraySingleStateC2_U8.push(first_modifier_C2_U8) DataArraySingleStateC2_U8.push(first_Key_C2_U8) @@ -1256,34 +602,19 @@ export class KeylayoutToKmnConverter { // get keyname e.g. 28-> K_8 first_key_C3_U8 = new TextEncoder().encode(this.map_UkeleleKC_To_VK(Number(the_ContextKeyNr))) } - - // const result_C3 = this.lookup_9_TerminatorState__To__TerminatorOutput_str(jsonObj, value_next) const result_C3_U8 = new TextEncoder().encode(this.lookup_9_TerminatorState__To__TerminatorOutput_str(jsonObj, value_next)) for (let l = 0; l < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i].length; l++) { - // const second_modifier_C3 = this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i][l], isCapsused) const second_modifier_C3_U8 = new TextEncoder().encode(this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i][l], isCapsused)) if (the_ContextKeyNr !== undefined) { - const second_key_Nr = Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']) - // const second_key_C3 = this.map_UkeleleKC_To_VK(second_key_Nr) - const second_key_C3_U8 = new TextEncoder().encode(this.map_UkeleleKC_To_VK(second_key_Nr)) for (let kk = 0; kk < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[keymapIndexForactionID_2[0][1]].length; kk++) { - const first_modifier_text_C3_U8 = data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[keymapIndexForactionID_2[0][1]][kk] const first_modifier_C3_U8 = new TextEncoder().encode(this.create_kmn_modifier(first_modifier_text_C3_U8, isCapsused)) - /*console.log(" ### Key Nr", jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], - "[ + C3 modifiers->", i, l, - "[", first_modifier_C3, first_key_C3, "]", - "> dk(dk1) ######### ", " dk(dk1) + [", - second_modifier_C3, second_key_C3, "] > ", result_C3, - the_ContextKeyNr, - keymapIndexForactionID_2, first_key_C3)*/ - DataArraySingleStateC3_U8.push(new TextEncoder().encode("first_modifier_C3")) DataArraySingleStateC3_U8.push(first_modifier_C3_U8) DataArraySingleStateC3_U8.push(first_key_C3_U8) @@ -1313,16 +644,13 @@ export class KeylayoutToKmnConverter { action_id = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] const next_id = this.lookup_3_ActionNone__To__ActionNext(jsonObj, action_id) - const result_C4 = this.lookup_9_TerminatorState__To__TerminatorOutput_str(jsonObj, next_id) const result_C4_U8 = new TextEncoder().encode(this.lookup_9_TerminatorState__To__TerminatorOutput_str(jsonObj, next_id)) for (let l = 0; l < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i].length; l++) { const DataArraySingleStateC4_U8: Uint8Array[] = [] - const first_modifier_C4_U8 = new TextEncoder().encode(this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i][l], isCapsused)) const first_key_C4_U8 = new TextEncoder().encode(this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']))) - const str_UTF8 = new TextDecoder().decode(result_C4_U8) DataArraySingleStateC4_U8.push(new TextEncoder().encode("first_modifier_C4")) @@ -1336,34 +664,16 @@ export class KeylayoutToKmnConverter { DataArraySingleStateC4_U8.push(new TextEncoder().encode(this.getHexFromChar(str_UTF8))) } - if (result_C4 !== "") { - console.log( - "### Key Nr ", - jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], - "[ + C4 modifiers->", i, "] ", - this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])).padEnd(8, " "), - "> ", - result_C4, - " [", - action_id, - next_id, - "]", - result_C4_U8, this.getHexFromChar(str_UTF8), - this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i][l], isCapsused) - ) - } if (DataArraySingleStateC4_U8.length > 0) DataArray_U8.push(DataArraySingleStateC4_U8) } } - else console.log("ERROR : some entries are not available") } } data_ukelele.ArrayOf_processed_RuleData = DataArray_U8 - console.log("DataArray_U8", DataArray_U8) return data_ukelele } @@ -1454,7 +764,6 @@ export class KeylayoutToKmnConverter { return k } return 0 - } public lookup_11_KeyMapAction__To__KeyMapCode(data: any, search: string): number { for (let kk = 0; kk < data.keyboard.keyMapSet[0].keyMap.length; kk++) { @@ -1478,7 +787,6 @@ export class KeylayoutToKmnConverter { } // get all entries that result in state 3 public lookup_12_ActionNext__from__ActionState(data: any, search: string): string { - // loop all action for (let jj = 0; jj < data.keyboard.actions.action.length; jj++) { // loop all when @@ -1490,7 +798,6 @@ export class KeylayoutToKmnConverter { } } } - return "" } public lookup_13_ActionNext__To__ActionID(data: any, search: string) { @@ -1498,7 +805,6 @@ export class KeylayoutToKmnConverter { for (let mm = 0; mm < data.keyboard.actions.action[ll].when.length; mm++) { if ((data.keyboard.actions.action[ll].when[mm]['@_next'] === search)) { return data.keyboard.actions.action[ll]['@_id'] - } } } @@ -1612,10 +918,10 @@ export class KeylayoutToKmnConverter { } /** - * @brief member function to map Ukelele keycodes to a Windows Keycodes - * @param pos Ukelele (=mac) keycodes - * @return keycode on Win Keyboard - */ + * @brief member function to map Ukelele keycodes to a Windows Keycodes + * @param pos Ukelele (=mac) keycodes + * @return keycode on Win Keyboard + */ // TODO finish all entries public map_UkeleleKC_To_VK(pos: number): string { // ukelele KC --> // VK_US @@ -1693,6 +999,7 @@ export class KeylayoutToKmnConverter { //---------------------------------------------------------------------------------------------------- public writeLastPart(data_ukelele: convert_object, isCAPSused: boolean): string { + // create a string array ....................................................... const workArray2D: string[][] = [] for (let k = 0; k < data_ukelele.ArrayOf_processed_RuleData.length; k++) { @@ -1703,134 +1010,40 @@ export class KeylayoutToKmnConverter { } workArray2D.push(array1D) } - console.log("workArray2D", workArray2D) + + //°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° - // DEADKEYS °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° + // DEADKEY RULES °° ([RALT K_8] > dk(00B4) °°°°°°°°°°°°°°°°°°°°°°°° //°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° - //const dk_ss_array: string[][] = [] - // ToDo get data from WorkArray // filter for dk values let data: string = "" - //data += '\n.. dk part here (+ [K_BKQUOTE] > dk(005e))\n\n' - - console.log("start dk-part ") - console.log("data_ukelele.ArrayOf_Element_KeyAction.length ", data_ukelele.ArrayOf_Element_KeyAction.length) - console.log(" data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect.length", data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect.length) - - - /* - // all 109 keys with action a9 - for (let i = 0; i < data_ukelele.ArrayOf_Element_KeyAction.length; i++) { - // loop through keyMapSelect (8) - for (let ii = 0; ii < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect.length; ii++) { - //for (let ii = 0; ii < 8; ii++) { - // loop through modifiers - //for (let j = 0; j < data_ukelele.ArrayOf_Element_KeyAction.length; j++) { - // 8 behaviors - for (let j = 0; j < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect.length; j++) { - //console.log("start write 3A", i, ii, j) - - // get the modifier for the layer - //const label_modifier = this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ALL_ModifierMaps[j], isCAPSused) - const label_modifier = this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ALL_ModifierMaps[j], isCAPSused) - console.log("label_modifier ", label_modifier) - - // get the character from keymap-section of .keylayout-file that will be written as result in kmn-file - //const resulting_character = new TextDecoder().decode(data_ukelele.ArrayOf_Element_KeyAction[j][i]) - // wrong since it attempts to convert a9 and not 4 ( the termínator id ) - const resulting_character = new TextDecoder().decode(data_ukelele.ArrayOf_Element_KeyAction[ii][i]) - console.log("resulting_character ",resulting_character ) - console.log("data_ukelele.ArrayOf_Element_KeyAction ",data_ukelele.ArrayOf_Element_KeyAction ) - - // therefore get character from ~ <- 4 <- a9 - //const realChar = this.getCharacterFromActionName(data_ukelele, data_ukelele.ArrayOf_Element_KeyAction[ii][i]) - //console.log("realChar", realChar,i,ii,j ) - // console.log("data_ukelele.ArrayOf_Element_KeyAction[ii][i],", - // data_ukelele.ArrayOf_Element_KeyAction[ii][i], - // realChar) - - if (resulting_character !== "") { - console.log("start write 3B+3C", i, ii, j, label_modifier, "---", resulting_character) - - const VK: (string | number)[][] = data_ukelele.ArrayOf_processed_VK_from_keylayout - const vk_label = VK.filter(item => item[0] === data_ukelele.ArrayOf_processed_VK_from_keylayout[i][0]) - // console.log("VK", VK, "vk_label", vk_label) - - // console.log("start write 3D,data_ukelele.ArrayOf_processed_dk", data_ukelele.ArrayOf_processed_dk) - for (let k = 0; k < data_ukelele.ArrayOf_processed_dk.length; k++) { - console.log("start write 3E") - console.log("resulting_character", resulting_character, "data_ukelele.ArrayOf_processed_dk[k][1]", data_ukelele.ArrayOf_processed_dk[k][1]) - console.log("data_ukelele.ArrayOf_processed_dk is", data_ukelele.ArrayOf_processed_dk) - console.log("resulting_characte, data_ukelele.ArrayOf_processed_dk is", resulting_character, data_ukelele.ArrayOf_processed_dk[k][2]) - if ((resulting_character !== "") && (resulting_character === data_ukelele.ArrayOf_processed_dk[k][2])) { - data += '[' + (label_modifier + ' ' + vk_label[0][1]).trim() + '] ' + "> dk(" + this.getHexFromChar(data_ukelele.ArrayOf_processed_dk[k][1]) + ") " + '\n' - console.log("start write 3D", data) - - } - } - } - } - - } - } - */ data += '\########## OK #################################################################\n' - data += '\nNOW MY C4 RULES **ccc ********* (only to get 02C6 ect) *********************\n\n' - console.log("data_ukelele.ArrayOf_processed_RuleData", data_ukelele.ArrayOf_processed_RuleData); - console.log("data_ukelele.ArrayOf_processed_RuleData.length ", data_ukelele.ArrayOf_processed_RuleData.length) - - const dk_line_array = workArray2D.filter(function ([A, B, C, D, E, F]) { - return (E === "isTerminator") - }); - console.log("dk_line_array", dk_line_array.length, dk_line_array) - // remove duplicates - const [uniqueDeadkeys] = dk_line_array.reduce((acc, curr) => { - const [uniq, set] = acc; - if (!set.has(curr.join(','))) { - set.add(curr.join(',')); - uniq.push(curr); + // select only lines that contain isTerminator and remove duplicates + const [uniqueDeadkeys] = workArray2D.reduce((acc, curr) => { + if (curr[4] === "isTerminator") { + const [uniq, set] = acc; + if (!set.has(curr.join(','))) { + set.add(curr.join(',')); + uniq.push(curr); + } } return acc; }, [[], new Set()], ); - console.log("uniquedk_line_array,uniqueDeadkeys", uniqueDeadkeys.length, uniqueDeadkeys); - for (let kkk = 0; kkk < uniqueDeadkeys.length; kkk++) { let line: string = "" line = "+ [" + uniqueDeadkeys[kkk][1] + " " + uniqueDeadkeys[kkk][2] + "] > dk(" + uniqueDeadkeys[kkk][6] + ")" data += line + '\n' } - console.log(" data all together", data); - - - - - // remove duplicates - /*const [uniqueDeadkeys] = dk_ss_array.reduce((acc, curr) => { - const [uniq, set] = acc; - if (!set.has(curr.join(','))) { - set.add(curr.join(',')); - uniq.push(curr); - } - return acc; - }, [[], new Set()], - ); - console.log("uniqueDeadkeys", uniqueDeadkeys);*/ - - - // array ony of dk (array_dk_char [ '¨', 'ˆ', '´', '˜', '`' ]) - const array_dk_char = [...new Set(data_ukelele.ArrayOf_processed_dk.map(a => a[1]))]; - console.log("array_dk_charN", array_dk_char); - - - - + //°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° + // DEADKEYABLE/DEADKEYED LIST (a,A,e,E) - (â,Â,ê,ê) °°°°°°°°°°°°°°° + //°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° // we have 5 different types: /* C0: size: 4 [ 'first_modifier_C0', '33RIGHTSHIFT NCAPS', 'K_S', 'S' ] @@ -1862,7 +1075,7 @@ export class KeylayoutToKmnConverter { */ - // create deadkeyables_raw, deadkeyed_raw array ....................................................... + // create deadkeyables_raw, deadkeyed_raw array let deadkeyables_raw: string[][] = [] let deadkeyed_raw: string[][] = [] @@ -1873,7 +1086,7 @@ export class KeylayoutToKmnConverter { && ((C !== "K_SPACE") && (D !== "")) ) }); - //console.log("deadkeyables_raw", deadkeyables_raw) + console.log("deadkeyables_raw", deadkeyables_raw.length, deadkeyables_raw) // find deadkeyed [ 'first_modifier_C2', 'CAPS', 'K_A', 'K_N', 'Ã' ] @@ -1882,36 +1095,30 @@ export class KeylayoutToKmnConverter { && ((C !== "K_SPACE")) ) }); - console.log("deadkeyables_raw", deadkeyables_raw.length, deadkeyables_raw) console.log("deadkeyed_raw", deadkeyed_raw.length, deadkeyed_raw) - const dkable_dked_array2D: any[][] = [] - // loop dedkeyables, take first + const join_dkable_dked: any[][] = [] + // loop dedkeyables, take Keyname for (let rr = 0; rr < deadkeyables_raw.length; rr++) { - // loop dedkeyed, take first + // loop dedkeyed, take Keyname for (let ss = 0; ss < deadkeyed_raw.length; ss++) { const dkable_dked_array: any[] = [] - //if available ( shifts the same, keyname the same) + //if available ( shiftstate the same, keyname the same) if ((deadkeyables_raw[rr][1] === deadkeyed_raw[ss][1]) && ((deadkeyables_raw[rr][2] === deadkeyed_raw[ss][2]))) { - //copy dedkeyables name, deadkeyable - //copy dedkeyed Secondname, deadkeyed - // dkable_dked_array.push(deadkeyables_raw[rr][1]) - dkable_dked_array.push(deadkeyables_raw[rr][3]) - dkable_dked_array.push(deadkeyed_raw[ss][3]) - dkable_dked_array.push(deadkeyed_raw[ss][4]) + dkable_dked_array.push(deadkeyables_raw[rr][3]) // deadkeyable e.g. a + dkable_dked_array.push(deadkeyed_raw[ss][3]) // Keyname dk e.g. K_EQUAL + dkable_dked_array.push(deadkeyed_raw[ss][4]) // deadkeyed e.g. â } - // dkable_dked_array2D.push(dkable_dked_array) if (dkable_dked_array.length > 0) - dkable_dked_array2D.push(dkable_dked_array) + join_dkable_dked.push(dkable_dked_array) } } - console.log("dkable_dked_array2D", dkable_dked_array2D.length, dkable_dked_array2D) - + console.log("join_dkable_dked", join_dkable_dked.length, join_dkable_dked) // remove duplicates - const [uniqueDeadkeyables] = dkable_dked_array2D.reduce((acc, curr) => { + const [unique_join_dkable_dked] = join_dkable_dked.reduce((acc, curr) => { const [uniq, set] = acc; if (!set.has(curr.join(','))) { set.add(curr.join(',')); @@ -1920,61 +1127,37 @@ export class KeylayoutToKmnConverter { return acc; }, [[], new Set()], ); - console.log("uniqueDeadkeyables", uniqueDeadkeyables.length, uniqueDeadkeyables); - + console.log("unique_join_dkable_dked", unique_join_dkable_dked.length, unique_join_dkable_dked); + // create 2dArray uniqueDeadkeys.length*unique_join_dkable_dked const deadkeyedArray: string[][] = Array.from({ length: uniqueDeadkeys.length }, () => new Array(2).fill('')); - console.log("deadkeyedArray", deadkeyedArray) const deadkeyablesArray: string[][] = Array.from({ length: uniqueDeadkeys.length }, () => new Array(1).fill('')); - console.log("deadkeyablesArray", deadkeyablesArray) - - console.log("uniqueDeadkeys", uniqueDeadkeys) for (let i = 0; i < uniqueDeadkeys.length; i++) { - for (let j = 0; j < uniqueDeadkeyables.length; j++) { - console.log("uniqueDeadkeys[i][2] ", uniqueDeadkeys[i][2]) - console.log("uniqueDeadkeyables[j][1] ", uniqueDeadkeyables[j][1]) + for (let j = 0; j < unique_join_dkable_dked.length; j++) { - if (uniqueDeadkeys[i][2] === uniqueDeadkeyables[j][1]) { - deadkeyablesArray[i][0] = deadkeyablesArray[i][0] + "\'" + uniqueDeadkeyables[j][0] + "\' " - deadkeyedArray[i][0] = deadkeyedArray[i][0] + "\'" + uniqueDeadkeyables[j][2] + "\' " + if (uniqueDeadkeys[i][2] === unique_join_dkable_dked[j][1]) { + deadkeyablesArray[i][0] = deadkeyablesArray[i][0] + "\'" + unique_join_dkable_dked[j][0] + "\' " + deadkeyedArray[i][0] = deadkeyedArray[i][0] + "\'" + unique_join_dkable_dked[j][2] + "\' " } } deadkeyedArray[i][1] = (uniqueDeadkeys[i][6]) } - data += "\n" data += '\########## OK #################################################################\n' - + data += '\nmatch > use(deadkeys)\n\n' data += '\ngroup(deadkeys)\n\n' // finally write out for (let i = 0; i < deadkeyablesArray.length; i++) { data += "\n\ndk: " + deadkeyedArray[i][1] - console.log("dk: ", deadkeyedArray[i][1]) - data += "\ndeadkeyablesArray" + deadkeyablesArray[i][0] - console.log("deadkeyablesArray", deadkeyablesArray[i][0]) - data += "\ndeadkeyedArray " + deadkeyedArray[i][0] - console.log("deadkeyedArray ", deadkeyedArray[i][0]) } return data } - public writeLines(inArray: string[]): string { - let editedLine: string = "" - for (let i = 0; i < inArray.length; i++) { - if (inArray[i] !== " ") - editedLine = editedLine + "\'" + inArray[i] + "\' " - else - editedLine = editedLine + " " - } - return editedLine - } - - } From a99abc9b06d0b268e9b35774daa81103eb07266a Mon Sep 17 00:00:00 2001 From: Sabine Date: Mon, 6 Jan 2025 15:24:57 +0100 Subject: [PATCH 035/251] feat(developer): kmc-convert remove unused functions --- .../keylayout-to-kmn-converter.ts | 229 +++++++----------- 1 file changed, 93 insertions(+), 136 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 2fe6f7d595d..fff0a3da054 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -15,10 +15,10 @@ import boxXmlArray = util.boxXmlArray;*/ // write read, convert, write // tests for 3 functions read write convert // add data to object - // Use filter functions - // action/output:use filter etc to shorten func - // deadkeyables:use filter etc to shorten func - // dk-> for all action:use filter etc to shorten func + // OK Use filter functions + // OK action/output:use filter etc to shorten func + // OK deadkeyables:use filter etc to shorten func + // OK dk-> for all action:use filter etc to shorten func // remove unneccessary data from dataObject // rename symbols // OK remove part using kmn_key_Name1 @@ -32,22 +32,26 @@ import boxXmlArray = util.boxXmlArray;*/ // TODO waht about using actions twice in a row??? // Usable for all keylayout files // Return conditions - // Use callbacks as for writeFileSync + // OK Use callbacks as for writeFileSync // Tests throws // Conditions NCAPS,OPT;... // TODO move func outside of class // Functions as object methods? // objects contain only used stuff READ in: -- out: only read arrays / CONVERT in: only read arrays out: return only to write arrays // Use catch blocks for file read - // read: answer : + [K_A] > 'a' is OK / TODO which format to use in output ? + [K_A] > 'a' (character code) or + [K_A] > U+0061 (virt Keycode) + // OK read: answer : + [K_A] > 'a' is OK / TODO which format to use in output ? + [K_A] > 'a' (character code) or + [K_A] > U+0061 (virt Keycode) // read TODO which stores? - // one entry vs several entry in tags + // OK one entry vs several entry in tags // false arrangement of tags - // no added NCAPS when first modifier in modifierMap does not contain "caps" or"caps?" + // OK no added NCAPS when first modifier in modifierMap does not contain "caps" or"caps?" // use length to clear array instead of defining evetry time new (modifierMap_ONE_InKeymapSelect.length=0 // naming of for-loop var i,j,k?... // warning if contrADICTING RULES E:G: [ 'modifier_C0', 'SHIFT NCAPS', 'K_C', 'c', '0', '1' ], vs [ 'modifier_C0', 'SHIFT NCAPS', 'K_C', 'C', '1', '0' ], - // print NCAPS as the first of the modifiers in create_kmn_modifier + // print NCAPS as the first of the modifiers in create_kmn_modifier + // use boxXmlArray from codebase instead of my own + // where are rules for action+none ( a, e, u, etc) + // + // } import { XMLParser } from 'fast-xml-parser'; // for reading a file @@ -119,10 +123,7 @@ function boxArrays_S(source: any) { export interface convert_object { name: string, // needed?? remove - ArrayOf_Element_KeyOutput: Uint8Array[][], - ArrayOf_Element_ALL_ModifierMaps: string[], ArrayOf_Element_ModifierMaps_ALLKeyMapSelect: string[][], - ArrayOf_processed_VK_from_keylayout: (string | number)[][], ArrayOf_processed_RuleData: Uint8Array[][], // add modified keys ( â,ê,î,ô,û) }; @@ -184,20 +185,13 @@ export class KeylayoutToKmnConverter { */ public read(filename: string): convert_object { - //const layouts_array: any[] = [] - const keys_output_all_Layers: Uint8Array[][] = [] - const modifierMap_all_Layers: string[] = [] // array holding all MODIFIER strings e.g. "anyShift caps anyOption" -why not put modifiers into Uint8Array along with values of keys of layer - const modifierMap_ALL_KeyMapSelects: string[][] = [] // modifier for each keymapselect + const modifierMap_ALL_KeyMapSelects: string[][] = [] // modifier for each keymapselect const kmn_Rules_AllLayers: Uint8Array[][] = [] - const vk: (string | number)[][] = [] // TODO remove unneccassary elements const DataObject: convert_object = { name: "Ukelele-kmn", // needed?? remove - ArrayOf_Element_KeyOutput: keys_output_all_Layers, - ArrayOf_Element_ALL_ModifierMaps: modifierMap_all_Layers, // all 18 modifiers in 1 array ArrayOf_Element_ModifierMaps_ALLKeyMapSelect: modifierMap_ALL_KeyMapSelects, // 18 modifiers in 8 KeyMapSelect(behaviors) - ArrayOf_processed_VK_from_keylayout: vk, ArrayOf_processed_RuleData: kmn_Rules_AllLayers, }; @@ -222,10 +216,11 @@ export class KeylayoutToKmnConverter { // const duplicate_layouts_array: string[] = [] // array holding the layouts e.g. ANSI or JIS // needed?? I think no + // jsonObj now contains only arrays; no single fields boxArrays_S(jsonObj.keyboard); // in case there always ANSI which is always keyMapSet[0] - const keyMapSet_ANSI_count = 0 + // const keyMapSet_ANSI_count = 0 // ......................................................... // MODIFIER MAP: get behaviours(=MapIndex) and modifiers (shift? leftShift caps? ) @@ -234,39 +229,15 @@ export class KeylayoutToKmnConverter { const modifierMap_ONE_InKeymapSelect: string[] = [] for (let k = 0; k < jsonObj.keyboard.modifierMap.keyMapSelect[j].modifier.length; k++) { - modifierMap_all_Layers.push(jsonObj.keyboard.modifierMap.keyMapSelect[j].modifier[k]['@_keys']) modifierMap_ONE_InKeymapSelect.push(jsonObj.keyboard.modifierMap.keyMapSelect[j].modifier[k]['@_keys']) } modifierMap_ALL_KeyMapSelects.push(modifierMap_ONE_InKeymapSelect) } - // ......................................................... - // KEYMAP - OUTPUT : get all keys for attribute "output" ( y,c,b,...) - // output type Uint8Array -> string - // ......................................................... - for (let j = 0; j < jsonObj.keyboard.modifierMap.keyMapSelect.length; j++) { - // create a new array of keys_in_Layer (type Uint8tarray) - const keys_output_One_Layer: Uint8Array[] = [] - // loop keys - for (let i = 0; i < jsonObj.keyboard.keyMapSet[keyMapSet_ANSI_count].keyMap[j].key.length; i++) { - if (jsonObj.keyboard.keyMapSet[keyMapSet_ANSI_count].keyMap[j].key[i]['@_output'] !== "\0") { - // textencoder converts string -> bytes ( 'A' -> [ 65 ], '☺' -> [ 226, 152, 186 ]) - // textencoder is of Uint8Array(1) for A and Uint8Array(3) for ☺ - keys_output_One_Layer[i] = new TextEncoder().encode(jsonObj.keyboard.keyMapSet[keyMapSet_ANSI_count].keyMap[j].key[i]['@_output']); - } - } - // create array of "output" - keys_output_all_Layers.push(keys_output_One_Layer) // save all @output data ( will be used for conversion, write...) - } - - // ......................................................... - // KEYMAP - ACTION : get all keys for attribute "action" - // output type Uint8Array -> string - // ......................................................... // Todo ? move to convert? // TODO review condition + // start to read other data return this.createRuleData(DataObject, jsonObj) - //return ((keys_output_all_Layers.length === nrOfStates + 5) && keys_output_all_Layers[0].length === nrOfKeys_inLayer) ? keys_output_all_Layers : null; } @@ -277,18 +248,6 @@ export class KeylayoutToKmnConverter { * @return outArray Uint8Array keys_all_Layers, the converted data for kmn-files if all layers have been converted; else null */ public convert(data_ukelele: convert_object): convert_object { - const data_VK_from_keylayout: (string | number)[][] = []; - - for (let i = 0; i < data_ukelele.ArrayOf_Element_KeyOutput[0].length; i++) { - - const data_VK_from_keylayout_pair: (string | number)[] = []; - const vk_from_Ukelele: string = this.map_UkeleleKC_To_VK(i) - - data_VK_from_keylayout_pair.push(i) - data_VK_from_keylayout_pair.push(vk_from_Ukelele) - data_VK_from_keylayout.push(data_VK_from_keylayout_pair) - } - data_ukelele.ArrayOf_processed_VK_from_keylayout = data_VK_from_keylayout return data_ukelele } @@ -329,58 +288,15 @@ export class KeylayoutToKmnConverter { // ************************************************************* // **** write rules ******************************************** - // *************************************************************^ - // todo replace write rules with reading out of rule-array - // if caps is used in .keylayout-file we need to add NCAPS in kmn-file - let isCAPSused = false - const used_Keys_count = 50 // do we need more than 50 keys?? - const modi: string[] = data_ukelele.ArrayOf_Element_ALL_ModifierMaps; - - const filteredModifiers: string[] = modi.filter((mod) => (String(mod) === ("caps"))) - if (filteredModifiers.indexOf("caps") >= 0) - isCAPSused = true - - // TODO good explanation - // find all modifiers used per modifier combination - // find resulting character from - - // loop through keys - //for (let j = 0; j item[0] === data_ukelele.ArrayOf_processed_VK_from_keylayout[j][0]) - // get the character from keymap-section of .keylayout-file that will be written as result in kmn-file - const resulting_character = new TextDecoder().decode(data_ukelele.ArrayOf_Element_KeyOutput[ii][j]) - - // TODO remove j +"(modif:" + i + `) - if (resulting_character !== '') { - // e.g. [ NCAPS K_J ] > ' j ' - data += j + "-(modif:" + ii + "-" + i + `) + [` + (label_modifier + ' ' + vk_label[0][1]).trim() + `] > \'` + resulting_character + '\'\n' - } - } - } - } - - const NEWDATA = this.writeLastPart(data_ukelele, isCAPSused) - data += NEWDATA + '\n' + data += this.writeLastPart(data_ukelele) + '\n' /*writeFileSync("data/MyResult.kmn", data, { flag: "w" })*/ - const data_encoded = new TextEncoder().encode(data) - this.callbacks.fs.writeFileSync("data/MyResult.kmn", data_encoded) // not usable here since it takes UInt8array data + this.callbacks.fs.writeFileSync("data/MyResult.kmn", new TextEncoder().encode(data)) // not usable here since it takes UInt8array data // ToDo conditions? if (data.length > 0) @@ -404,11 +320,12 @@ export class KeylayoutToKmnConverter { let action_id let output_id + const used_Keys_count = 51 const isCapsused = this.checkIfCapsUsed(data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect) - // loop keys + // loop keys 0-50 (= all that we use) //for (let j = 0; j < jsonObj.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { - for (let j = 0; j < 52; j++) { + for (let j = 0; j < used_Keys_count; j++) { // loop behaviors for (let i = 0; i < jsonObj.keyboard.keyMapSet[0].keyMap.length; i++) { @@ -420,7 +337,7 @@ export class KeylayoutToKmnConverter { // ...................................................................................................... // in keys at top for code 1 (K_S) take output ("s") [italian copy] // get modifiers [modifer of Keymap index 0] - // write [modifer of Keymap index 0] + K_S > s + // write [modifer-of-Keymap-index-0 K_S] > s // ...................................................................................................... if (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] !== undefined) { @@ -461,7 +378,7 @@ export class KeylayoutToKmnConverter { // goto id a9 // in action id a9 find "none" // get output "a" - // write [modifer of Keymap index 0] + K_A > a + // write [modifer-of-Keymap-index-0 K_A] > a // ...................................................................................................... action_id = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] @@ -500,7 +417,7 @@ export class KeylayoutToKmnConverter { // take code = 25 and map keycode to VK (VK= K_9) // get second modifiers [modifer of Keymap index 3] (=anyOption) // [modifer of Keymap index 3] + K_A + K_9 > à - // write: [anyOption + K_A] > dk(dk1) ; dk(dk1) + [second modifiers K_9] > à + // write: [modifer-of-Keymap-index-0 K_A] > dk(dk1) ; dk(dk1) + [second modifiers K_9] > à // ...................................................................................................... let result_C2 @@ -639,7 +556,7 @@ export class KeylayoutToKmnConverter { // get modifiers [modifer of Keymap index 3] // in actions a16 () find state "none" and get next (=4) // in terminators ( ) find the state (=4) and get output ("¨") - // write [modifer of Keymap index 3] + K_U -> "¨" + // write [modifer of Keymap index 3 + K_U] -> "¨" action_id = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] @@ -674,6 +591,9 @@ export class KeylayoutToKmnConverter { } data_ukelele.ArrayOf_processed_RuleData = DataArray_U8 + + console.log("DataArray_U8 ", DataArray_U8) + return data_ukelele } @@ -951,9 +871,10 @@ export class KeylayoutToKmnConverter { if (pos === 0x23) return "K_P" /* P */ if (pos === 0x21) return "K_LBRKT" /* [ */ if (pos === 0x1E) return "K_RBRKT" /* ] */ - //if (pos === 0x32) return "K_BKSLASH" /* \ */ - if (pos === 0x30) return "K_BKSLASH" /* \ */ // for ANSI correct?? - if (pos === 0x2A) return "K_BKSLASH" /* \ */ // for ISO correct?? + if (pos === 0x32) return "K_SPACE" /* \ */ + if (pos === 0x2A) return "K_BKSLASH" /* \ */ // 42 for ISO correct?? + // if (pos === 0x30) return "K_?C1" /* \ */ // 48 for ANSI correct?? + // TODO numbers OK?? if (pos === 0x00) return "K_A" /* A */ if (pos === 0x01) return "K_S" /* S */ @@ -998,7 +919,7 @@ export class KeylayoutToKmnConverter { //---------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------- - public writeLastPart(data_ukelele: convert_object, isCAPSused: boolean): string { + public writeLastPart(data_ukelele: convert_object): string { // create a string array ....................................................... const workArray2D: string[][] = [] @@ -1010,15 +931,55 @@ export class KeylayoutToKmnConverter { } workArray2D.push(array1D) } + console.log("workArray2D ", workArray2D) + //°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° + // FIRST PART RULES °° ( + [NCAPS K_S] > 's') °°°°°°°°°°°°°°°°°°°°° + //°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° + let data: string = "" + + // select only lines that contain C0 or C1 and no empty fields. Also remove duplicates + const [uniqueDeadkeys_first] = workArray2D.reduce((acc, curr) => { + if ((curr[3] !== "") && ((curr[0] === "first_modifier_C0") || (curr[0] === "first_modifier_C1"))) { + const [uniq, set] = acc; + if (!set.has(curr.join(','))) { + set.add(curr.join(',')); + uniq.push(curr); + } + } + return acc; + }, [[], new Set()], + ); + + + let keymarker = "" + for (let kkk = 0; kkk < uniqueDeadkeys_first.length; kkk++) { + + // find key nr + let keyNr = 0; + for (let pp = 0; pp < 50; pp++) { + if (this.map_UkeleleKC_To_VK(pp) === uniqueDeadkeys_first[kkk][2]) + keyNr = pp + } + + // skip keyNr 48 ( TAB ) + if (keyNr === 48) + continue + + if (keymarker !== uniqueDeadkeys_first[kkk][2]) + data += '\n' + + data += keyNr + "-(modif:" + "ii" + "-" + "i" + `) + [` + (uniqueDeadkeys_first[kkk][1] + ' ' + uniqueDeadkeys_first[kkk][2]).trim() + `] > \'` + uniqueDeadkeys_first[kkk][3] + '\'\n' + keymarker = uniqueDeadkeys_first[kkk][2] + } + data += '\n' + console.log("data ", data) //°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° // DEADKEY RULES °° ([RALT K_8] > dk(00B4) °°°°°°°°°°°°°°°°°°°°°°°° //°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° // filter for dk values - let data: string = "" - data += '\########## OK #################################################################\n' data += '\nNOW MY C4 RULES **ccc ********* (only to get 02C6 ect) *********************\n\n' @@ -1046,34 +1007,30 @@ export class KeylayoutToKmnConverter { //°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° // we have 5 different types: /* - C0: size: 4 [ 'first_modifier_C0', '33RIGHTSHIFT NCAPS', 'K_S', 'S' ] - C1: size: 4 [ 'first_modifier_C1', 'CAPS', 'K_N', 'N' ], - C2: size: 5 [ 'first_modifier_C2', 'CAPS', 'K_E', 'K_9', 'È' ], - use 2.(K_E) and 4.('È') to get Name and DEADKEYED - C3: size: 6 ['first_modifier_C3', 'NCAPS RALT', 'K_8', 'NCAPS RALT', 'K_U', 'ˆ' - C4: size: 4 ['first_modifier_C4', 'NCAPS 0', 'K_SPACE', '' ], - size: 7 ['first_modifier_C4', 'NCAPS RALT', 'K_N', '˜', 'isTerminator', '˜', '02DC' ], - use 2.(K_N) , 5. (isTerminator) and 6.('02DC') to get Name and DEADKEY in hex + C0: size: 4 ['first_modifier_C0', 'RIGHTSHIFT ', 'K_S', 'S' ] + C1: size: 4 ['first_modifier_C1', 'CAPS', 'K_N', 'N' ], + C2: size: 5 ['first_modifier_C2', 'CAPS', 'K_E', 'K_9', 'È' ], use 2.(K_E) and 4.('È') to get Name and DEADKEYED + C3: size: 6 ['first_modifier_C3', 'NCAPS RALT', 'K_8', 'NCAPS RALT', 'K_U', 'ˆ' ], + C4: size: 4 ['first_modifier_C4', 'NCAPS 0', 'K_SPACE', '' ], + C4: size: 7 ['first_modifier_C4', 'NCAPS RALT', 'K_N', '˜', 'isTerminator', '˜', '02DC '], use 2.(K_N) , 5. (isTerminator) and 6.('02DC') to get Name and DEADKEY in hex Find DEADKEYABLE 1) first_modifier_C1 CAPS K_A A 2) first_modifier_C2 CAPS K_A K_EQUAL  3) first_modifier_C2 CAPS K_A K_9 À - - Find C2 rule with Deadkeyed ( n= 5) - - get C1 rule with first n=3 entries -> (first_modifier_C1 CAPS K_A) - - get 4th entry == DEADKEYABLE + - Find C2 rule with Deadkeyed ( n = 5) + - get C1 rule with same second and third entries -> (first_modifier_C1 CAPS K_A) + - get 4th entry ===> DEADKEYABLE (e.g. A) Find DEADKEY - 1) look in modifier_C4 (n=7) - 2) get 7th entry (=02DC) + 1) look in modifier_C4 (n = 7) + 2) get 7th entry ===> DEADKEY (e.g. 02DC) Find DEADKEYED - 1)look in modifier_C2 - 2) get 5th entry (='È') - 2) get 3th entry (='K_E') - - - */ + 1) look in modifier_C2 + 2) get 3rd entry (='K_A') + 3) get 5th entry ===> DEADKEYED (='Â') + */ // create deadkeyables_raw, deadkeyed_raw array let deadkeyables_raw: string[][] = [] From c102d83eed2ec74ccde3e3b10202c5911bb1e795 Mon Sep 17 00:00:00 2001 From: Sabine Date: Mon, 6 Jan 2025 19:29:23 +0100 Subject: [PATCH 036/251] feat(developer): kmc-convert seperate write into 3 functions --- .../keylayout-to-kmn-converter.ts | 466 +++++++++--------- 1 file changed, 227 insertions(+), 239 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index fff0a3da054..44d3552b88c 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -46,7 +46,7 @@ import boxXmlArray = util.boxXmlArray;*/ // OK no added NCAPS when first modifier in modifierMap does not contain "caps" or"caps?" // use length to clear array instead of defining evetry time new (modifierMap_ONE_InKeymapSelect.length=0 // naming of for-loop var i,j,k?... - // warning if contrADICTING RULES E:G: [ 'modifier_C0', 'SHIFT NCAPS', 'K_C', 'c', '0', '1' ], vs [ 'modifier_C0', 'SHIFT NCAPS', 'K_C', 'C', '1', '0' ], + // warning if contrADICTING RULES E:G: [ 'modifier_C0', 'SHIFT NCAPS', 'K_C', 'c'], vs [ 'modifier_C0', 'SHIFT NCAPS', 'K_C', 'C' ], // print NCAPS as the first of the modifiers in create_kmn_modifier // use boxXmlArray from codebase instead of my own // where are rules for action+none ( a, e, u, etc) @@ -185,13 +185,12 @@ export class KeylayoutToKmnConverter { */ public read(filename: string): convert_object { - const modifierMap_ALL_KeyMapSelects: string[][] = [] // modifier for each keymapselect + const modifierBehaviors: string[][] = [] // modifier for each keymapselect const kmn_Rules_AllLayers: Uint8Array[][] = [] - // TODO remove unneccassary elements const DataObject: convert_object = { name: "Ukelele-kmn", // needed?? remove - ArrayOf_Element_ModifierMaps_ALLKeyMapSelect: modifierMap_ALL_KeyMapSelects, // 18 modifiers in 8 KeyMapSelect(behaviors) + ArrayOf_Element_ModifierMaps_ALLKeyMapSelect: modifierBehaviors, // 18 modifiers in 8 KeyMapSelect(behaviors) ArrayOf_processed_RuleData: kmn_Rules_AllLayers, }; @@ -214,29 +213,23 @@ export class KeylayoutToKmnConverter { const parser = new XMLParser(options); const jsonObj = parser.parse(xmlFile); // get plain Object - // const duplicate_layouts_array: string[] = [] // array holding the layouts e.g. ANSI or JIS // needed?? I think no - // jsonObj now contains only arrays; no single fields boxArrays_S(jsonObj.keyboard); - // in case there always ANSI which is always keyMapSet[0] - // const keyMapSet_ANSI_count = 0 - // ......................................................... // MODIFIER MAP: get behaviours(=MapIndex) and modifiers (shift? leftShift caps? ) // ......................................................... for (let j = 0; j < jsonObj.keyboard.modifierMap.keyMapSelect.length; j++) { - const modifierMap_ONE_InKeymapSelect: string[] = [] + const singleModifierSet: string[] = [] for (let k = 0; k < jsonObj.keyboard.modifierMap.keyMapSelect[j].modifier.length; k++) { - modifierMap_ONE_InKeymapSelect.push(jsonObj.keyboard.modifierMap.keyMapSelect[j].modifier[k]['@_keys']) + singleModifierSet.push(jsonObj.keyboard.modifierMap.keyMapSelect[j].modifier[k]['@_keys']) } - modifierMap_ALL_KeyMapSelects.push(modifierMap_ONE_InKeymapSelect) + modifierBehaviors.push(singleModifierSet) } // Todo ? move to convert? // TODO review condition - // start to read other data return this.createRuleData(DataObject, jsonObj) } @@ -260,41 +253,10 @@ export class KeylayoutToKmnConverter { //TODO need to use export const USVirtualKeyCodes here public write(data_ukelele: convert_object): boolean { - // ************************************************************* - // **** write stores ******************************************* - // ************************************************************* let data = "\n" - data += "c\n" - data += "c Keyman keyboard generated by kmn-convert\n" - data += "c\n" - data += "\n" - - data += '\########## OK #################################################################\n' - data += "store(&VERSION) \'...\'\n" - data += "store(&TARGETS) \'any\'\n" - data += "store(&KEYBOARDVERSION) \'...\'\n" - data += "store(©RIGHT) '© 2024 SIL International\n" - // TODO what else ?? - - data += '\########## OK #################################################################\n' - data += "\n" - data += "begin Unicode > use(main)\n\n" - data += "group(main) using keys\n\n" - - data += '\########## OK #################################################################\n' - data += "Tipp: if K_? is replaced by undefined-> no enry in kmn_Key_Name=> add K_? there and it will be shown here\n" - data += "Tipp: keys that are marked with sction do not aoear in ukelele_Array_output->do not appear in kmn\n" + data += this.createDataToWrite(data_ukelele) data += "\n" - // ************************************************************* - // **** write rules ******************************************** - // ************************************************************* - - // if caps is used in .keylayout-file we need to add NCAPS in the kmn-file - - - data += this.writeLastPart(data_ukelele) + '\n' - /*writeFileSync("data/MyResult.kmn", data, { flag: "w" })*/ this.callbacks.fs.writeFileSync("data/MyResult.kmn", new TextEncoder().encode(data)) // not usable here since it takes UInt8array data @@ -307,13 +269,9 @@ export class KeylayoutToKmnConverter { data += '\n' } - - //... helpers ............................................................................................. - // TODO move outside of class? // ToDo keep only uint8array-version - // for more info about mapping and cases C0-C4 - // see https://docs.google.com/document/d/1ISjACTA9aUBueTo1AoKnOsI6QR5kXeeD_maI0XUyXqg/edit?tab=t.0 + // for more info about mapping and cases C0-C4 see https://docs.google.com/document/d/1ISjACTA9aUBueTo1AoKnOsI6QR5kXeeD_maI0XUyXqg/edit?tab=t.0 public createRuleData(data_ukelele: convert_object, jsonObj: any): convert_object { const DataArray_U8: Uint8Array[][] = [] @@ -323,16 +281,15 @@ export class KeylayoutToKmnConverter { const used_Keys_count = 51 const isCapsused = this.checkIfCapsUsed(data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect) - // loop keys 0-50 (= all that we use) - //for (let j = 0; j < jsonObj.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { + // loop keys 0-50 (= all keys we use) for (let j = 0; j < used_Keys_count; j++) { - // loop behaviors + // loop behaviors ( in ukelele it is possible to define multiple modifier combinations that behave the same) for (let i = 0; i < jsonObj.keyboard.keyMapSet[0].keyMap.length; i++) { // ...................................................................................................... // case C0: output ...................................................................................... - // a key is mapped to a character ( code-> output) ...................................................... + // a key is mapped to a character directly ( code-> output) ............................................. // ...............e. g. ...................................................... // ...................................................................................................... // in keys at top for code 1 (K_S) take output ("s") [italian copy] @@ -343,7 +300,7 @@ export class KeylayoutToKmnConverter { if (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] !== undefined) { output_id = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] - // loop modifiers + // loop modifier combinations for (let l = 0; l < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i].length; l++) { const DataArraySingleStateC0_U8: Uint8Array[] = [] @@ -363,29 +320,26 @@ export class KeylayoutToKmnConverter { } // ...................................................................................................... - // actions ............................................................................... + // case C1: action + state none + output ................................................................ + // a key is mapped to an action and then to an output ................................................... + // code->action->action(none)->action(output) ........................................................... + // ...............e. g. a // ...................................................................................................... - else if (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] !== undefined) { - // ...................................................................................................... - // case C1: action + state none + output .............................................................. - // a key is mapped to an action and then to an output ................................................... - // code->action->action(none)->action(output) ........................................................... - // ...............e. g. a - // ...................................................................................................... + action_id = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] const result_C1 = this.lookup_6_ActionNone__To__ActionOutput(jsonObj, action_id) const result_C1_U8 = new TextEncoder().encode(this.lookup_6_ActionNone__To__ActionOutput(jsonObj, action_id)) - // modifiers + // loop modifiers for (let l = 0; l < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i].length; l++) { const DataArraySingleStateC1_U8: Uint8Array[] = [] @@ -547,7 +501,7 @@ export class KeylayoutToKmnConverter { } } // ...................................................................................................... - // case C4: action + state none + Next ............................................................DONE . + // case C4: action + state none + Next .................................................................. // ...............e. g. ................................................... // a key is mapped to an action and then to a terminator ................................................ // code->action->action(none)->action(next)->terminator(output) ......................................... @@ -596,8 +550,6 @@ export class KeylayoutToKmnConverter { return data_ukelele } - - // public lookup_2_KeyMapAction__To__ActionAction() { } public lookup_3_ActionNone__To__ActionNext(data: any, search: string): string { for (let jj = 0; jj < data.keyboard.actions.action.length; jj++) { if (data.keyboard.actions.action[jj]['@_id'] === search) { @@ -609,7 +561,6 @@ export class KeylayoutToKmnConverter { } return "" } - //public lookup_4_ActionNext__To__ActionState() { } public lookup_5_ActionState__To__ActionNext(data: any, action_idName: string): string[] { const returnarray: string[] = [] // e.g. action_idName = 3 @@ -658,17 +609,6 @@ export class KeylayoutToKmnConverter { } return OutputValue } - //public lookup_7_ActionState__To__ActionOutput() { } - //public lookup_8_ActionNext__To__TerminatorState() { } - - public lookup_9_TerminatorState__To__TerminatorOutput_ui8(data: any, search: string): Uint8Array { - for (let jj = 0; jj < data.keyboard.terminators.when.length; jj++) { - if (data.keyboard.terminators.when[jj]['@_state'] === search) { - return new TextEncoder().encode(data.keyboard.terminators.when[jj]['@_output']); - } - } - return new TextEncoder().encode("") - } public lookup_9_TerminatorState__To__TerminatorOutput_str(data: any, search: string): string { let OutputValue = "" for (let jj = 0; jj < data.keyboard.terminators.when.length; jj++) { @@ -695,31 +635,6 @@ export class KeylayoutToKmnConverter { } return 999 } - public lookup_11_KeyMapAction__To__KeyIndex(data: any, search: string): number { - for (let kk = 0; kk < data.keyboard.keyMapSet[0].keyMap.length; kk++) { - for (let jj = 0; jj < data.keyboard.keyMapSet[0].keyMap[kk].key.length; jj++) { - if (data.keyboard.keyMapSet[0].keyMap[kk].key[jj]['@_action'] === search) { - return data.keyboard.keyMapSet[0].keyMap[kk]['@_index'] - } - } - } - return 999 - } - // get all entries that result in state 3 - public lookup_12_ActionNext__from__ActionState(data: any, search: string): string { - // loop all action - for (let jj = 0; jj < data.keyboard.actions.action.length; jj++) { - // loop all when - for (let kk = 0; kk < data.keyboard.actions.action[jj].when.length; kk++) { - // if next === a´search - if (data.keyboard.actions.action[jj].when[kk]['@_next'] === search) { - // return actionIDName - return data.keyboard.actions.action[jj]['@_id'] - } - } - } - return "" - } public lookup_13_ActionNext__To__ActionID(data: any, search: string) { for (let ll = 0; ll < data.keyboard.actions.action.length; ll++) { for (let mm = 0; mm < data.keyboard.actions.action[ll].when.length; mm++) { @@ -747,7 +662,6 @@ export class KeylayoutToKmnConverter { return mapIndexArray_max } - /** * @brief member function to return the unicode value of a character * @param character the value that will converted @@ -905,85 +819,19 @@ export class KeylayoutToKmnConverter { else return "" } - public useElementAsString(u18ArrayElemnent: Uint8Array): string { - return new TextDecoder().decode(u18ArrayElemnent) - } - public useAsString(u18ArrayElemnent: Uint8Array[]): string { - let str = "" - for (let i = 0; i < u18ArrayElemnent.length; i++) { - str = str + " " + new TextDecoder().decode(u18ArrayElemnent[i]) - } - return str - } //---------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------- - public writeLastPart(data_ukelele: convert_object): string { - // create a string array ....................................................... - const workArray2D: string[][] = [] - for (let k = 0; k < data_ukelele.ArrayOf_processed_RuleData.length; k++) { - const array1D: string[] = [] - for (let l = 0; l < data_ukelele.ArrayOf_processed_RuleData[k].length; l++) { - const u8data = data_ukelele.ArrayOf_processed_RuleData[k][l] - array1D.push(this.useElementAsString(u8data)) - } - workArray2D.push(array1D) - } - console.log("workArray2D ", workArray2D) + public createData_Deadkeys(data_ukelele: convert_object, workArray2D: string[][]): string { - //°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° - // FIRST PART RULES °° ( + [NCAPS K_S] > 's') °°°°°°°°°°°°°°°°°°°°° - //°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° let data: string = "" - - // select only lines that contain C0 or C1 and no empty fields. Also remove duplicates - const [uniqueDeadkeys_first] = workArray2D.reduce((acc, curr) => { - if ((curr[3] !== "") && ((curr[0] === "first_modifier_C0") || (curr[0] === "first_modifier_C1"))) { - const [uniq, set] = acc; - if (!set.has(curr.join(','))) { - set.add(curr.join(',')); - uniq.push(curr); - } - } - return acc; - }, [[], new Set()], - ); - - - let keymarker = "" - for (let kkk = 0; kkk < uniqueDeadkeys_first.length; kkk++) { - - // find key nr - let keyNr = 0; - for (let pp = 0; pp < 50; pp++) { - if (this.map_UkeleleKC_To_VK(pp) === uniqueDeadkeys_first[kkk][2]) - keyNr = pp - } - - // skip keyNr 48 ( TAB ) - if (keyNr === 48) - continue - - if (keymarker !== uniqueDeadkeys_first[kkk][2]) - data += '\n' - - data += keyNr + "-(modif:" + "ii" + "-" + "i" + `) + [` + (uniqueDeadkeys_first[kkk][1] + ' ' + uniqueDeadkeys_first[kkk][2]).trim() + `] > \'` + uniqueDeadkeys_first[kkk][3] + '\'\n' - keymarker = uniqueDeadkeys_first[kkk][2] - } - data += '\n' - console.log("data ", data) - - //°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° - // DEADKEY RULES °° ([RALT K_8] > dk(00B4) °°°°°°°°°°°°°°°°°°°°°°°° - //°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° - // filter for dk values data += '\########## OK #################################################################\n' data += '\nNOW MY C4 RULES **ccc ********* (only to get 02C6 ect) *********************\n\n' - // select only lines that contain isTerminator and remove duplicates + // select only lines that contain "isTerminator" and remove duplicates const [uniqueDeadkeys] = workArray2D.reduce((acc, curr) => { if (curr[4] === "isTerminator") { const [uniq, set] = acc; @@ -1002,43 +850,42 @@ export class KeylayoutToKmnConverter { data += line + '\n' } - //°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° - // DEADKEYABLE/DEADKEYED LIST (a,A,e,E) - (â,Â,ê,ê) °°°°°°°°°°°°°°° - //°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° - // we have 5 different types: - /* - C0: size: 4 ['first_modifier_C0', 'RIGHTSHIFT ', 'K_S', 'S' ] - C1: size: 4 ['first_modifier_C1', 'CAPS', 'K_N', 'N' ], - C2: size: 5 ['first_modifier_C2', 'CAPS', 'K_E', 'K_9', 'È' ], use 2.(K_E) and 4.('È') to get Name and DEADKEYED - C3: size: 6 ['first_modifier_C3', 'NCAPS RALT', 'K_8', 'NCAPS RALT', 'K_U', 'ˆ' ], - C4: size: 4 ['first_modifier_C4', 'NCAPS 0', 'K_SPACE', '' ], - C4: size: 7 ['first_modifier_C4', 'NCAPS RALT', 'K_N', '˜', 'isTerminator', '˜', '02DC '], use 2.(K_N) , 5. (isTerminator) and 6.('02DC') to get Name and DEADKEY in hex - - Find DEADKEYABLE - 1) first_modifier_C1 CAPS K_A A - 2) first_modifier_C2 CAPS K_A K_EQUAL  - 3) first_modifier_C2 CAPS K_A K_9 À - - Find C2 rule with Deadkeyed ( n = 5) - - get C1 rule with same second and third entries -> (first_modifier_C1 CAPS K_A) - - get 4th entry ===> DEADKEYABLE (e.g. A) + + /* + How to create rules from keylayout data ffrom data_ukelele.ArrayOf_processed_RuleData: + + There are 6 different types of data entries (C0-C4) in data_ukelele.ArrayOf_processed_RuleData e.g. that contain all data to retrieve deadkeys, deadkeyables and deadkeyed characters: + + C0: (size: 4) ['first_modifier_C0', 'RIGHTSHIFT ', 'K_S', 'S' ] + C1: (size: 4) ['first_modifier_C1', 'CAPS', 'K_A', 'A' ], + C2: (size: 5) ['first_modifier_C2', 'CAPS', 'K_A', 'K_N', 'Ã' ], use 2.(K_A) and 4.('Ã') to get name and DEADKEYED + C3: (size: 6) ['first_modifier_C3', 'NCAPS RALT', 'K_8', 'NCAPS RALT', 'K_U', 'ˆ' ], + C4: (size: 4) ['first_modifier_C4', 'NCAPS 0', 'K_SPACE', '' ], + C4: (size: 7) ['first_modifier_C4', 'NCAPS RALT', 'K_N', '˜', 'isTerminator', '˜', '02DC '], use 2.(K_N) , 5. (isTerminator) and 6.('02DC') to get key name and DEADKEY in hex - Find DEADKEY - 1) look in modifier_C4 (n = 7) - 2) get 7th entry ===> DEADKEY (e.g. 02DC) + To Find a DEADKEY e.g. ^ + 1) look in modifier_C4 with 'isTerminator' included (n = 7) + 2) get 7th entry ===> DEADKEY (e.g. 02DC) + + To Find a DEADKEYABLE ( a character that can be converted to a deadkey e.g. A (-> Ã) ): + 1) first_modifier_C1 CAPS K_A A + 2) first_modifier_C2 CAPS K_A K_N à + - Find C2 rule with 5 entries (Deadkeyed) (e.g. first_modifier_C2 CAPS K_A K_N Ã) + - get C1 rule with same second and third entries -> (e.g. first_modifier_C1 CAPS K_A) + - get 2nd entry of C1 rule ===> DEADKEYABLE (e.g. A) - Find DEADKEYED - 1) look in modifier_C2 - 2) get 3rd entry (='K_A') - 3) get 5th entry ===> DEADKEYED (='Â') + To Find a DEADKEYED ( a character that has been converted from another character e.g. à ): + 1) look in modifier_C2 CAPS K_A K_N à + 2) get 3rd entry (='K_A') + 3) get 5th entry ===> DEADKEYED (='Ã') */ - // create deadkeyables_raw, deadkeyed_raw array let deadkeyables_raw: string[][] = [] let deadkeyed_raw: string[][] = [] - // find deadkeyable [ 'first_modifier_C1', 'CAPS', 'K_A', 'A', '', '', '' ] - deadkeyables_raw = workArray2D.filter(function ([A, B, C, D, E, F, G]) { + // find C1 line for deadkeyable [ 'first_modifier_C1', 'CAPS', 'K_A', 'A' ] + deadkeyables_raw = workArray2D.filter(function ([A, B, C, D]) { return ((A === "first_modifier_C1") /*&& (B === shiftstate) && (C === key_name)*/ && ((C !== "K_SPACE") && (D !== "")) ) @@ -1046,8 +893,8 @@ export class KeylayoutToKmnConverter { console.log("deadkeyables_raw", deadkeyables_raw.length, deadkeyables_raw) - // find deadkeyed [ 'first_modifier_C2', 'CAPS', 'K_A', 'K_N', 'Ã' ] - deadkeyed_raw = workArray2D.filter(function ([A, B, C, D, E, F, G]) { + // find C2 line for deadkeyed [ 'first_modifier_C2', 'CAPS', 'K_A', 'K_N', 'Ã' ] + deadkeyed_raw = workArray2D.filter(function ([A, B, C]) { return ((A === "first_modifier_C2")/* && (B === shiftstate) && (C === key_name)*/ && ((C !== "K_SPACE")) ) @@ -1055,27 +902,29 @@ export class KeylayoutToKmnConverter { console.log("deadkeyed_raw", deadkeyed_raw.length, deadkeyed_raw) - const join_dkable_dked: any[][] = [] - // loop dedkeyables, take Keyname + const dk_array_comlpete: any[][] = [] + + // create 2D array with data of both deadkeyables_raw, deadkeyed_raw and remove possible duplicates + + for (let rr = 0; rr < deadkeyables_raw.length; rr++) { - // loop dedkeyed, take Keyname + // loop deadkeyed_raw, take Keyname for (let ss = 0; ss < deadkeyed_raw.length; ss++) { - const dkable_dked_array: any[] = [] - //if available ( shiftstate the same, keyname the same) - if ((deadkeyables_raw[rr][1] === deadkeyed_raw[ss][1]) - && ((deadkeyables_raw[rr][2] === deadkeyed_raw[ss][2]))) { - dkable_dked_array.push(deadkeyables_raw[rr][3]) // deadkeyable e.g. a - dkable_dked_array.push(deadkeyed_raw[ss][3]) // Keyname dk e.g. K_EQUAL - dkable_dked_array.push(deadkeyed_raw[ss][4]) // deadkeyed e.g. â + const dk_array: any[] = [] + //if available ( if both have the same shiftstate and keyname) + if ((deadkeyables_raw[rr][1] === deadkeyed_raw[ss][1]) && ((deadkeyables_raw[rr][2] === deadkeyed_raw[ss][2]))) { + dk_array.push(deadkeyables_raw[rr][3]) // deadkeyable e.g. A + dk_array.push(deadkeyed_raw[ss][3]) // Keyname dk e.g. K_N + dk_array.push(deadkeyed_raw[ss][4]) // deadkeyed e.g. à } - if (dkable_dked_array.length > 0) - join_dkable_dked.push(dkable_dked_array) + if (dk_array.length > 0) + dk_array_comlpete.push(dk_array) } } - console.log("join_dkable_dked", join_dkable_dked.length, join_dkable_dked) + console.log("dk_array_comlpete", dk_array_comlpete.length, dk_array_comlpete) // remove duplicates - const [unique_join_dkable_dked] = join_dkable_dked.reduce((acc, curr) => { + const [unique_dk_array_comlpete] = dk_array_comlpete.reduce((acc, curr) => { const [uniq, set] = acc; if (!set.has(curr.join(','))) { set.add(curr.join(',')); @@ -1084,21 +933,22 @@ export class KeylayoutToKmnConverter { return acc; }, [[], new Set()], ); - console.log("unique_join_dkable_dked", unique_join_dkable_dked.length, unique_join_dkable_dked); + console.log("unique_join_dkable_dked", unique_dk_array_comlpete.length, unique_dk_array_comlpete); - // create 2dArray uniqueDeadkeys.length*unique_join_dkable_dked - const deadkeyedArray: string[][] = Array.from({ length: uniqueDeadkeys.length }, () => new Array(2).fill('')); - const deadkeyablesArray: string[][] = Array.from({ length: uniqueDeadkeys.length }, () => new Array(1).fill('')); + // deadkeyablesArray'a' 'A' 'e' 'E' 'y' 'Y' 'o' 'O' 'u' 'U' 'i' 'I' + // deadkeyedArray 'ä' 'Ä' 'ë' 'Ë' 'ÿ' 'Ÿ' 'ö' 'Ö' 'ü' 'Ü' 'ï' 'Ï' + const deadkeyedElement: string[][] = Array.from({ length: uniqueDeadkeys.length }, () => new Array(2).fill('')); + const deadkeyablesElement: string[][] = Array.from({ length: uniqueDeadkeys.length }, () => new Array(1).fill('')); for (let i = 0; i < uniqueDeadkeys.length; i++) { - for (let j = 0; j < unique_join_dkable_dked.length; j++) { + for (let j = 0; j < unique_dk_array_comlpete.length; j++) { - if (uniqueDeadkeys[i][2] === unique_join_dkable_dked[j][1]) { - deadkeyablesArray[i][0] = deadkeyablesArray[i][0] + "\'" + unique_join_dkable_dked[j][0] + "\' " - deadkeyedArray[i][0] = deadkeyedArray[i][0] + "\'" + unique_join_dkable_dked[j][2] + "\' " + if (uniqueDeadkeys[i][2] === unique_dk_array_comlpete[j][1]) { + deadkeyablesElement[i][0] = deadkeyablesElement[i][0] + "\'" + unique_dk_array_comlpete[j][0] + "\' " + deadkeyedElement[i][0] = deadkeyedElement[i][0] + "\'" + unique_dk_array_comlpete[j][2] + "\' " } } - deadkeyedArray[i][1] = (uniqueDeadkeys[i][6]) + deadkeyedElement[i][1] = (uniqueDeadkeys[i][6]) } data += "\n" @@ -1106,15 +956,153 @@ export class KeylayoutToKmnConverter { data += '\nmatch > use(deadkeys)\n\n' data += '\ngroup(deadkeys)\n\n' - // finally write out - for (let i = 0; i < deadkeyablesArray.length; i++) { - data += "\n\ndk: " + deadkeyedArray[i][1] - data += "\ndeadkeyablesArray" + deadkeyablesArray[i][0] - data += "\ndeadkeyedArray " + deadkeyedArray[i][0] + for (let i = 0; i < deadkeyablesElement.length; i++) { + data += "\n\ndk: " + deadkeyedElement[i][1] + data += "\ndeadkeyablesArray" + deadkeyablesElement[i][0] + data += "\ndeadkeyedArray " + deadkeyedElement[i][0] + } + return data + } + + public createData_Rules(data_ukelele: convert_object, workArray2D: string[][]): string { + const maxkey = 50 + let data: string = "" + let keymarker = "" + + // select only lines that contain C0 or C1 and create an output. Also remove duplicates + const [uniqueDeadkeys] = workArray2D.reduce((acc, curr) => { + if ((curr[3] !== "") && ((curr[0] === "first_modifier_C0") || (curr[0] === "first_modifier_C1"))) { + const [uniq, set] = acc; + if (!set.has(curr.join(','))) { + set.add(curr.join(',')); + uniq.push(curr); + } + } + return acc; + }, [[], new Set()], + ); + + for (let kkk = 0; kkk < uniqueDeadkeys.length; kkk++) { + // lookup key nr of the key that is being processed + let keyNr = 0; + for (let pp = 0; pp < maxkey; pp++) { + if (this.map_UkeleleKC_To_VK(pp) === uniqueDeadkeys[kkk][2]) + keyNr = pp + } + + // skip keyNr 48 ( TAB ) + if (keyNr === 48) + continue + + // add a line after rules of each key + if (uniqueDeadkeys[kkk][2] !== keymarker) + data += '\n' + + data += keyNr + "-(modif:" + "ii" + "-" + "i" + `) + [` + (uniqueDeadkeys[kkk][1] + ' ' + uniqueDeadkeys[kkk][2]).trim() + `] > \'` + uniqueDeadkeys[kkk][3] + '\'\n' + keymarker = uniqueDeadkeys[kkk][2] } + + data += '\n' + console.log("data ", data) + return data } + public createData_Stores(data_ukelele: convert_object): string { + let data: string = "" + + data += "c\n" + data += "c Keyman keyboard generated by kmn-convert\n" + data += "c\n" + data += "\n" + + data += '\########## OK #################################################################\n' + data += "store(&VERSION) \'...\'\n" + data += "store(&TARGETS) \'any\'\n" + data += "store(&KEYBOARDVERSION) \'...\'\n" + data += "store(©RIGHT) '© 2024 SIL International\n" + // TODO what else ?? + + data += '\########## OK #################################################################\n' + data += "\n" + data += "begin Unicode > use(main)\n\n" + data += "group(main) using keys\n\n" + + data += '\########## OK #################################################################\n' + data += "Tipp: if K_? is replaced by undefined-> no enry in kmn_Key_Name=> add K_? there and it will be shown here\n" + data += "Tipp: keys that are marked with sction do not aoear in ukelele_Array_output->do not appear in kmn\n" + data += "\n" + + return data + } + + public createDataToWrite(data_ukelele: convert_object): string { + + // create a string array to work with ................................................ + const workArray2D: string[][] = [] + for (let k = 0; k < data_ukelele.ArrayOf_processed_RuleData.length; k++) { + const array1D: string[] = [] + for (let l = 0; l < data_ukelele.ArrayOf_processed_RuleData[k].length; l++) { + const u8data = data_ukelele.ArrayOf_processed_RuleData[k][l] + array1D.push(new TextDecoder().decode(u8data)) + } + workArray2D.push(array1D) + } + console.log("workArray2D ", workArray2D) + + + let data: string = "" + data += this.createData_Stores(data_ukelele) + data += this.createData_Rules(data_ukelele, workArray2D) + data += this.createData_Deadkeys(data_ukelele, workArray2D) + return data + } + + // public lookup_2_KeyMapAction__To__ActionAction() { } + //public lookup_4_ActionNext__To__ActionState() { } + //public lookup_7_ActionState__To__ActionOutput() { } + //public lookup_8_ActionNext__To__TerminatorState() { } + /* public lookup_9_TerminatorState__To__TerminatorOutput_ui8(data: any, search: string): Uint8Array { + for (let jj = 0; jj < data.keyboard.terminators.when.length; jj++) { + if (data.keyboard.terminators.when[jj]['@_state'] === search) { + return new TextEncoder().encode(data.keyboard.terminators.when[jj]['@_output']); + } + } + return new TextEncoder().encode("") + }*/ + /*public lookup_11_KeyMapAction__To__KeyIndex(data: any, search: string): number { + for (let kk = 0; kk < data.keyboard.keyMapSet[0].keyMap.length; kk++) { + for (let jj = 0; jj < data.keyboard.keyMapSet[0].keyMap[kk].key.length; jj++) { + if (data.keyboard.keyMapSet[0].keyMap[kk].key[jj]['@_action'] === search) { + return data.keyboard.keyMapSet[0].keyMap[kk]['@_index'] + } + } + } + return 999 + }*/ + // get all entries that result in state 3 + /*public lookup_12_ActionNext__from__ActionState(data: any, search: string): string { + // loop all action + for (let jj = 0; jj < data.keyboard.actions.action.length; jj++) { + // loop all when + for (let kk = 0; kk < data.keyboard.actions.action[jj].when.length; kk++) { + // if next === a´search + if (data.keyboard.actions.action[jj].when[kk]['@_next'] === search) { + // return actionIDName + return data.keyboard.actions.action[jj]['@_id'] + } + } + } + return "" + }*/ + /* + public useAsString(u18ArrayElemnent: Uint8Array[]): string { + let str = "" + for (let i = 0; i < u18ArrayElemnent.length; i++) { + str = str + " " + new TextDecoder().decode(u18ArrayElemnent[i]) + } + return str + }*/ } From ce1a49ede204fe64b4ef67c411cc82750371bd16 Mon Sep 17 00:00:00 2001 From: Sabine Date: Wed, 8 Jan 2025 17:52:58 +0100 Subject: [PATCH 037/251] feat(developer): kmc-convert use class Rules instead of array of rule data --- .../keylayout-to-kmn-converter.ts | 444 ++++++++++++------ 1 file changed, 306 insertions(+), 138 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 44d3552b88c..fb1da508393 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -14,7 +14,7 @@ import boxXmlArray = util.boxXmlArray;*/ // OK defaultIndex: The table number to use for modifier key combinations which are not explicitly specified by any element within the . // write read, convert, write // tests for 3 functions read write convert - // add data to object + // OK add data to object // OK Use filter functions // OK action/output:use filter etc to shorten func // OK deadkeyables:use filter etc to shorten func @@ -42,7 +42,7 @@ import boxXmlArray = util.boxXmlArray;*/ // OK read: answer : + [K_A] > 'a' is OK / TODO which format to use in output ? + [K_A] > 'a' (character code) or + [K_A] > U+0061 (virt Keycode) // read TODO which stores? // OK one entry vs several entry in tags - // false arrangement of tags + // false arrangement of tags ? // OK no added NCAPS when first modifier in modifierMap does not contain "caps" or"caps?" // use length to clear array instead of defining evetry time new (modifierMap_ONE_InKeymapSelect.length=0 // naming of for-loop var i,j,k?... @@ -50,8 +50,13 @@ import boxXmlArray = util.boxXmlArray;*/ // print NCAPS as the first of the modifiers in create_kmn_modifier // use boxXmlArray from codebase instead of my own // where are rules for action+none ( a, e, u, etc) - // - // + // order of object member var + // readfilesync with paths better way? + // rearrange code to use read, convert, write + // remove all any + // TODO rewrite explanantion for object instead of array + // remove all any types + // let push_count = 0 // Todo remove later } import { XMLParser } from 'fast-xml-parser'; // for reading a file @@ -119,12 +124,27 @@ function boxArrays_S(source: any) { return source; } +export interface rule_object { + type_C: string, /* rule type C0-C4 */ + modifiers_first: string, /* string of modifiers for the first key (e.g. "NCAPS RALT CTRL") */ + key_first: string, /* name of the first key (e.g. K_U) */ + modifiers_second: string, /* string of modifiers for the second key */ + key_second: string, /* name of the second key */ + + chars: Uint8Array, /* the output character */ + isTerminator: boolean, /* is this a terminator rule */ + dk_hex: string, /* deadkey in hex notation (e.g. 00B4 for "´" )*/ + dk_char: Uint8Array, //todo needed?/* */ + + deadkeys: Uint8Array, /* deadkeys to add to a character (e.g. ^,´,`,~ ) */ + deadkeyables: Uint8Array, /* characters that can use a deadkey (e.g. a,e,i,o,u )*/ + deadkeyed: Uint8Array, // deadkeys+deadkeyables (e.g. â,ê,î,ô,û) +}; export interface convert_object { - name: string, // needed?? remove - ArrayOf_Element_ModifierMaps_ALLKeyMapSelect: string[][], - ArrayOf_processed_RuleData: Uint8Array[][], // add modified keys ( â,ê,î,ô,û) + ArrayOf_Modifiers: string[][], + ArrayOf_Rules: rule_object[], }; @@ -179,19 +199,18 @@ export class KeylayoutToKmnConverter { /** * @brief take filename, open and read data from .keylayout-file and store in several arrays of the data object - * member function to read filename ( a .keylayout-file) and write contents into Uint8Array keys_all_Layers + * member function to read filename ( a .keylayout-file) and write contents into Uint8Array keys_all_Layers * @param filename the ukelele .keylayout-file to be converted * @return in case of success Uint8Array keys_all_Layers; else null */ public read(filename: string): convert_object { - const modifierBehaviors: string[][] = [] // modifier for each keymapselect - const kmn_Rules_AllLayers: Uint8Array[][] = [] + const modifierBehavior: string[][] = [] // modifier for each keymapselect + const RuleObject: rule_object[] = [] // an array of objects which hold data for a kmn rule const DataObject: convert_object = { - name: "Ukelele-kmn", // needed?? remove - ArrayOf_Element_ModifierMaps_ALLKeyMapSelect: modifierBehaviors, // 18 modifiers in 8 KeyMapSelect(behaviors) - ArrayOf_processed_RuleData: kmn_Rules_AllLayers, + ArrayOf_Modifiers: modifierBehavior, // e.g. 18 modifiers in 8 KeyMapSelect(behaviors) + ArrayOf_Rules: RuleObject }; console.log("inputFilename read", filename) @@ -216,16 +235,13 @@ export class KeylayoutToKmnConverter { // jsonObj now contains only arrays; no single fields boxArrays_S(jsonObj.keyboard); - // ......................................................... - // MODIFIER MAP: get behaviours(=MapIndex) and modifiers (shift? leftShift caps? ) - // ......................................................... + // MODIFIER MAP: get behaviours(=MapIndex) and modifiers (e.g. shift? leftShift caps? ) for (let j = 0; j < jsonObj.keyboard.modifierMap.keyMapSelect.length; j++) { const singleModifierSet: string[] = [] - for (let k = 0; k < jsonObj.keyboard.modifierMap.keyMapSelect[j].modifier.length; k++) { singleModifierSet.push(jsonObj.keyboard.modifierMap.keyMapSelect[j].modifier[k]['@_keys']) } - modifierBehaviors.push(singleModifierSet) + modifierBehavior.push(singleModifierSet) } // Todo ? move to convert? @@ -237,7 +253,7 @@ export class KeylayoutToKmnConverter { /** * @brief member function to convert data of .keylayout-file to kmn-file This will convert/rename modifiers, position of Keys and deadkeys and save into an array * @param take data_ukelele and create a mapping from mac Keycodes to key-names and save to data_ukelele object - * @param data_ukelele (Uint8Array) data of the ukelele .keylayout-file + * @param data_ukelele (Uint8Array) data of the ukelele .keylayout-file * @return outArray Uint8Array keys_all_Layers, the converted data for kmn-files if all layers have been converted; else null */ public convert(data_ukelele: convert_object): convert_object { @@ -252,9 +268,10 @@ export class KeylayoutToKmnConverter { */ //TODO need to use export const USVirtualKeyCodes here public write(data_ukelele: convert_object): boolean { + console.log("\n###################################################\n") let data = "\n" - data += this.createDataToWrite(data_ukelele) + data += this.create_KMN_Data(data_ukelele) data += "\n" /*writeFileSync("data/MyResult.kmn", data, { flag: "w" })*/ @@ -275,16 +292,18 @@ export class KeylayoutToKmnConverter { public createRuleData(data_ukelele: convert_object, jsonObj: any): convert_object { const DataArray_U8: Uint8Array[][] = [] + const ObjectArray: any[] = [] let action_id let output_id + let push_count = 0 // Todo remove later const used_Keys_count = 51 - const isCapsused = this.checkIfCapsUsed(data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect) + const isCapsused = this.checkIfCapsUsed(data_ukelele.ArrayOf_Modifiers) // loop keys 0-50 (= all keys we use) for (let j = 0; j < used_Keys_count; j++) { - // loop behaviors ( in ukelele it is possible to define multiple modifier combinations that behave the same) + // loop behaviors ( in ukelele it is possible to define multiple modifier combinations that behave in the same) for (let i = 0; i < jsonObj.keyboard.keyMapSet[0].keyMap.length; i++) { // ...................................................................................................... @@ -296,16 +315,16 @@ export class KeylayoutToKmnConverter { // get modifiers [modifer of Keymap index 0] // write [modifer-of-Keymap-index-0 K_S] > s // ...................................................................................................... - + let RuleObj if (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] !== undefined) { output_id = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] // loop modifier combinations - for (let l = 0; l < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i].length; l++) { + for (let l = 0; l < data_ukelele.ArrayOf_Modifiers[i].length; l++) { const DataArraySingleStateC0_U8: Uint8Array[] = [] - if (output_id !== "") { - const first_modifier_C0_U8 = new TextEncoder().encode(this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i][l], isCapsused)); + if ((output_id !== "") || (output_id !== undefined)) { + const first_modifier_C0_U8 = new TextEncoder().encode(this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[i][l], isCapsused)); const first_key_C0_U8 = new TextEncoder().encode(this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']))); const result_C0_U8 = new TextEncoder().encode(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output']); @@ -313,12 +332,31 @@ export class KeylayoutToKmnConverter { DataArraySingleStateC0_U8.push(first_modifier_C0_U8) DataArraySingleStateC0_U8.push(first_key_C0_U8) DataArraySingleStateC0_U8.push(result_C0_U8) + + RuleObj = new Rules( + "first_modifier_C0", + this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[i][l], isCapsused), + this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), + "", + "", + result_C0_U8, + false, + "", + new TextEncoder().encode(""), + new TextEncoder().encode(""), + new TextEncoder().encode(""), + new TextEncoder().encode("") + ) + } - if (DataArraySingleStateC0_U8.length > 0) + + if (DataArraySingleStateC0_U8.length > 0) { DataArray_U8.push(DataArraySingleStateC0_U8) + push_count++ + ObjectArray.push(RuleObj) + } } } - // ...................................................................................................... // case C1: action + state none + output ................................................................ // a key is mapped to an action and then to an output ................................................... @@ -340,21 +378,41 @@ export class KeylayoutToKmnConverter { const result_C1_U8 = new TextEncoder().encode(this.lookup_6_ActionNone__To__ActionOutput(jsonObj, action_id)) // loop modifiers - for (let l = 0; l < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i].length; l++) { + for (let l = 0; l < data_ukelele.ArrayOf_Modifiers[i].length; l++) { const DataArraySingleStateC1_U8: Uint8Array[] = [] if (result_C1 !== undefined) { - const first_modifier_C1_U8 = new TextEncoder().encode(this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i][l], isCapsused)) + const first_modifier_C1_U8 = new TextEncoder().encode(this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[i][l], isCapsused)) const first_key_C1_U8 = new TextEncoder().encode(this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']))) DataArraySingleStateC1_U8.push(new TextEncoder().encode("first_modifier_C1")) DataArraySingleStateC1_U8.push(first_modifier_C1_U8) DataArraySingleStateC1_U8.push(first_key_C1_U8) DataArraySingleStateC1_U8.push(result_C1_U8) - } - if (DataArraySingleStateC1_U8.length > 0) - DataArray_U8.push(DataArraySingleStateC1_U8) + RuleObj = new Rules( + "first_modifier_C1", + this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[i][l], isCapsused), + this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), + "", + "", + result_C1_U8, + false, + "", + new TextEncoder().encode(""), + new TextEncoder().encode(""), + new TextEncoder().encode(""), + new TextEncoder().encode("") + ) + + + if (DataArraySingleStateC1_U8.length > 0) { + DataArray_U8.push(DataArraySingleStateC1_U8) + + push_count++ + } + ObjectArray.push(RuleObj) + } } // ...................................................................................................... // case C2: action + state Nr + output .................................................................. @@ -396,13 +454,13 @@ export class KeylayoutToKmnConverter { nextvalArray = this.lookup_5_ActionState__To__ActionNext_none(jsonObj, stateVal) // for all modifier combinations - for (let l = 0; l < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i].length; l++) { + for (let l = 0; l < data_ukelele.ArrayOf_Modifiers[i].length; l++) { const DataArraySingleStateC2_U8: Uint8Array[] = [] for (let k = 0; k < nextvalArray.length; k++) { if (result_C2 !== undefined) { - const first_modifier_C2_U8 = new TextEncoder().encode(this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i][l], isCapsused)) + const first_modifier_C2_U8 = new TextEncoder().encode(this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[i][l], isCapsused)) const first_Key_C2_U8 = new TextEncoder().encode(this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']))) const second_Key_C2_U8 = new TextEncoder().encode(this.map_UkeleleKC_To_VK(Number(this.lookup_11_KeyMapAction__To__KeyMapCode(jsonObj, nextvalArray[k])))) @@ -411,10 +469,30 @@ export class KeylayoutToKmnConverter { DataArraySingleStateC2_U8.push(first_Key_C2_U8) DataArraySingleStateC2_U8.push(second_Key_C2_U8)// state = none -> no modifier DataArraySingleStateC2_U8.push(result_C2_U8) - } - if (DataArraySingleStateC2_U8.length > 0) - DataArray_U8.push(DataArraySingleStateC2_U8) + RuleObj = new Rules( + "first_modifier_C2", + this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[i][l], isCapsused), + this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), + "", + this.map_UkeleleKC_To_VK(Number(this.lookup_11_KeyMapAction__To__KeyMapCode(jsonObj, nextvalArray[k]))), + new TextEncoder().encode(""), + false, + "", + new TextEncoder().encode(""), + new TextEncoder().encode(""), + new TextEncoder().encode(""), + result_C2_U8 + ) + + + if (DataArraySingleStateC2_U8.length > 0) { + DataArray_U8.push(DataArraySingleStateC2_U8) + + push_count++ + ObjectArray.push(RuleObj) + } + } } } } @@ -475,28 +553,51 @@ export class KeylayoutToKmnConverter { } const result_C3_U8 = new TextEncoder().encode(this.lookup_9_TerminatorState__To__TerminatorOutput_str(jsonObj, value_next)) - for (let l = 0; l < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i].length; l++) { - const second_modifier_C3_U8 = new TextEncoder().encode(this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i][l], isCapsused)) + for (let l = 0; l < data_ukelele.ArrayOf_Modifiers[i].length; l++) { + const second_modifier_C3_U8 = new TextEncoder().encode(this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[i][l], isCapsused)) if (the_ContextKeyNr !== undefined) { const second_key_Nr = Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']) const second_key_C3_U8 = new TextEncoder().encode(this.map_UkeleleKC_To_VK(second_key_Nr)) - for (let kk = 0; kk < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[keymapIndexForactionID_2[0][1]].length; kk++) { - const first_modifier_text_C3_U8 = data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[keymapIndexForactionID_2[0][1]][kk] + for (let kk = 0; kk < data_ukelele.ArrayOf_Modifiers[keymapIndexForactionID_2[0][1]].length; kk++) { + const first_modifier_text_C3_U8 = data_ukelele.ArrayOf_Modifiers[keymapIndexForactionID_2[0][1]][kk] const first_modifier_C3_U8 = new TextEncoder().encode(this.create_kmn_modifier(first_modifier_text_C3_U8, isCapsused)) DataArraySingleStateC3_U8.push(new TextEncoder().encode("first_modifier_C3")) DataArraySingleStateC3_U8.push(first_modifier_C3_U8) DataArraySingleStateC3_U8.push(first_key_C3_U8) + DataArraySingleStateC3_U8.push(second_modifier_C3_U8) DataArraySingleStateC3_U8.push(second_key_C3_U8) + DataArraySingleStateC3_U8.push(result_C3_U8) - } - if (DataArraySingleStateC3_U8.length > 0) - DataArray_U8.push(DataArraySingleStateC3_U8) + RuleObj = new Rules( + "first_modifier_C3", + this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[i][l], isCapsused), + this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), + + this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[i][l], isCapsused), + this.map_UkeleleKC_To_VK(second_key_Nr), + + result_C3_U8, + false, + "", + new TextEncoder().encode(""), + new TextEncoder().encode(""), + new TextEncoder().encode(""), + new TextEncoder().encode("") + ) + + if (DataArraySingleStateC3_U8.length > 0) { + DataArray_U8.push(DataArraySingleStateC3_U8) + + push_count++ + } + } + ObjectArray.push(RuleObj) } } } @@ -517,10 +618,10 @@ export class KeylayoutToKmnConverter { const next_id = this.lookup_3_ActionNone__To__ActionNext(jsonObj, action_id) const result_C4_U8 = new TextEncoder().encode(this.lookup_9_TerminatorState__To__TerminatorOutput_str(jsonObj, next_id)) - for (let l = 0; l < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i].length; l++) { + for (let l = 0; l < data_ukelele.ArrayOf_Modifiers[i].length; l++) { const DataArraySingleStateC4_U8: Uint8Array[] = [] - const first_modifier_C4_U8 = new TextEncoder().encode(this.create_kmn_modifier(data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i][l], isCapsused)) + const first_modifier_C4_U8 = new TextEncoder().encode(this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[i][l], isCapsused)) const first_key_C4_U8 = new TextEncoder().encode(this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']))) const str_UTF8 = new TextDecoder().decode(result_C4_U8) @@ -533,10 +634,29 @@ export class KeylayoutToKmnConverter { DataArraySingleStateC4_U8.push(new TextEncoder().encode("isTerminator")) DataArraySingleStateC4_U8.push(result_C4_U8) DataArraySingleStateC4_U8.push(new TextEncoder().encode(this.getHexFromChar(str_UTF8))) + + + RuleObj = new Rules( + "first_modifier_C4", + this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[i][l], isCapsused), + this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), + "", + "", + new TextEncoder().encode(this.lookup_9_TerminatorState__To__TerminatorOutput_str(jsonObj, next_id)), + true, + this.getHexFromChar(str_UTF8), + new TextEncoder().encode(this.getHexFromChar(str_UTF8)), + new TextEncoder().encode(this.lookup_9_TerminatorState__To__TerminatorOutput_str(jsonObj, next_id)), + new TextEncoder().encode(this.lookup_9_TerminatorState__To__TerminatorOutput_str(jsonObj, next_id)), + new TextEncoder().encode(this.lookup_9_TerminatorState__To__TerminatorOutput_str(jsonObj, next_id)) + ) } - if (DataArraySingleStateC4_U8.length > 0) + if (DataArraySingleStateC4_U8.length > 0) { DataArray_U8.push(DataArraySingleStateC4_U8) + push_count++ + } + ObjectArray.push(RuleObj) } } else @@ -544,10 +664,7 @@ export class KeylayoutToKmnConverter { } } - data_ukelele.ArrayOf_processed_RuleData = DataArray_U8 - - console.log("DataArray_U8 ", DataArray_U8) - + data_ukelele.ArrayOf_Rules = ObjectArray return data_ukelele } public lookup_3_ActionNone__To__ActionNext(data: any, search: string): string { @@ -697,7 +814,7 @@ export class KeylayoutToKmnConverter { if (isCAPSused && (String(keylayout_modifier).indexOf("caps") === -1)) kmn_ncaps = " NCAPS " - // TODO go over, find more conditions & simplify + // TODO review, find more conditions & simplify if (String(modifier_state[i]) === "anyOption") add_modifier = "RALT " else if (String(modifier_state[i]) === "anyShift") add_modifier = "SHIFT " else if (String(modifier_state[i]) === "anyControl") add_modifier = "CTRL " @@ -785,9 +902,9 @@ export class KeylayoutToKmnConverter { if (pos === 0x23) return "K_P" /* P */ if (pos === 0x21) return "K_LBRKT" /* [ */ if (pos === 0x1E) return "K_RBRKT" /* ] */ - if (pos === 0x32) return "K_SPACE" /* \ */ + if (pos === 0x32) return "K_SPACE" /* \ */ if (pos === 0x2A) return "K_BKSLASH" /* \ */ // 42 for ISO correct?? - // if (pos === 0x30) return "K_?C1" /* \ */ // 48 for ANSI correct?? + // if (pos === 0x30) return "K_?C1" /* \ */ // 48 for ANSI correct?? // TODO numbers OK?? if (pos === 0x00) return "K_A" /* A */ @@ -810,12 +927,11 @@ export class KeylayoutToKmnConverter { if (pos === 0x0B) return "K_B" /* B */ if (pos === 0x2D) return "K_N" /* N */ if (pos === 0x2E) return "K_M" /* M */ - if (pos === 43) return "K_COMMA" /* , */ - if (pos === 47) return "K_PERIOD" /* . */ - if (pos === 44) return "K_SLASH" /* / */ + if (pos === 0x2B) return "K_COMMA" /* , */ + if (pos === 0x2F) return "K_PERIOD" /* . */ + if (pos === 0x2C) return "K_SLASH" /* / */ - if (pos === 36) return "K_ENTER" - if (pos === 49) return "K_SPACE" + if (pos === 0x24) return "K_ENTER" else return "" } @@ -824,34 +940,42 @@ export class KeylayoutToKmnConverter { //---------------------------------------------------------------------------------------------------- - public createData_Deadkeys(data_ukelele: convert_object, workArray2D: string[][]): string { + public createData_Deadkeys(data_ukelele: convert_object, workArray2D: any[]): string { let data: string = "" // filter for dk values data += '\########## OK #################################################################\n' data += '\nNOW MY C4 RULES **ccc ********* (only to get 02C6 ect) *********************\n\n' - // select only lines that contain "isTerminator" and remove duplicates - const [uniqueDeadkeys] = workArray2D.reduce((acc, curr) => { - if (curr[4] === "isTerminator") { - const [uniq, set] = acc; - if (!set.has(curr.join(','))) { - set.add(curr.join(',')); - uniq.push(curr); - } + // ToDo in 1 func + // select only lines twhere isTerminator=true + const uniqueDeadkeys_all = workArray2D.filter((curr) => { + if (curr.isTerminator === true) { + return curr; } - return acc; - }, [[], new Set()], - ); + }); + + // remove duplicates + const uniqueDeadkeys = uniqueDeadkeys_all.reduce((unique, o) => { + if (!unique.some((obj: { chars: any; type_C: any; modifiers_first: any; key_first: any }) => + new TextDecoder().decode(obj.chars) === new TextDecoder().decode(o.chars) + && obj.key_first === o.key_first + && obj.type_C === o.type_C + && obj.modifiers_first === o.modifiers_first) + ) { + unique.push(o); + } + return unique; + }, []); + for (let kkk = 0; kkk < uniqueDeadkeys.length; kkk++) { let line: string = "" - line = "+ [" + uniqueDeadkeys[kkk][1] + " " + uniqueDeadkeys[kkk][2] + "] > dk(" + uniqueDeadkeys[kkk][6] + ")" + line = "+ [" + uniqueDeadkeys[kkk].modifiers_first + " " + uniqueDeadkeys[kkk].key_first + "] > dk(" + uniqueDeadkeys[kkk].dk_hex + ")" data += line + '\n' } - - /* + /* How to create rules from keylayout data ffrom data_ukelele.ArrayOf_processed_RuleData: There are 6 different types of data entries (C0-C4) in data_ukelele.ArrayOf_processed_RuleData e.g. that contain all data to retrieve deadkeys, deadkeyables and deadkeyed characters: @@ -880,51 +1004,55 @@ export class KeylayoutToKmnConverter { 3) get 5th entry ===> DEADKEYED (='Ã') */ - let deadkeyables_raw: string[][] = [] - let deadkeyed_raw: string[][] = [] - - // find C1 line for deadkeyable [ 'first_modifier_C1', 'CAPS', 'K_A', 'A' ] - deadkeyables_raw = workArray2D.filter(function ([A, B, C, D]) { - return ((A === "first_modifier_C1") /*&& (B === shiftstate) && (C === key_name)*/ - && ((C !== "K_SPACE") && (D !== "")) - ) + // select only lines for deadkeyables ( entries that contain C1, are not K_SPACE and create chars e.g. from 'first_modifier_C1', 'CAPS', 'K_A', 'A' ]) + const deadkeyables_raw = workArray2D.filter((curr) => { + if ((curr.type_C === "first_modifier_C1") && (curr.key_first !== "K_SPACE") && (new TextDecoder().decode(curr.chars) !== "")) { + return curr; + } }); - console.log("deadkeyables_raw", deadkeyables_raw.length, deadkeyables_raw) - - // find C2 line for deadkeyed [ 'first_modifier_C2', 'CAPS', 'K_A', 'K_N', 'Ã' ] - deadkeyed_raw = workArray2D.filter(function ([A, B, C]) { - return ((A === "first_modifier_C2")/* && (B === shiftstate) && (C === key_name)*/ - && ((C !== "K_SPACE")) - ) + // select only lines for deadkeyed ( entries that contain C2, are not K_SPACE and create a deadkeyed) e.g. from ['first_modifier_C2', 'CAPS', 'K_A', 'K_N', 'Ã' ] + const deadkeyed_raw_multiple = workArray2D.filter((curr) => { + if ((curr.type_C === "first_modifier_C2") && (curr.key_first !== "K_SPACE") && (curr.deadkeyed !== "")) { + return curr; + } }); - console.log("deadkeyed_raw", deadkeyed_raw.length, deadkeyed_raw) + // remove duplicate s + const deadkeyed_raw = deadkeyed_raw_multiple.reduce((unique, o) => { + if (!unique.some((obj: { chars: any; type_C: any; modifiers_first: any; key_first: any; deadkeyed: any }) => + new TextDecoder().decode(obj.deadkeyed) === new TextDecoder().decode(o.deadkeyed) + && obj.key_first === o.key_first + && obj.type_C === o.type_C + && obj.modifiers_first === o.modifiers_first) + ) { + unique.push(o); + } + return unique; + }, []); - const dk_array_comlpete: any[][] = [] + const dk_array_comlpete: any[] = [] // create 2D array with data of both deadkeyables_raw, deadkeyed_raw and remove possible duplicates - - for (let rr = 0; rr < deadkeyables_raw.length; rr++) { // loop deadkeyed_raw, take Keyname for (let ss = 0; ss < deadkeyed_raw.length; ss++) { const dk_array: any[] = [] //if available ( if both have the same shiftstate and keyname) - if ((deadkeyables_raw[rr][1] === deadkeyed_raw[ss][1]) && ((deadkeyables_raw[rr][2] === deadkeyed_raw[ss][2]))) { - dk_array.push(deadkeyables_raw[rr][3]) // deadkeyable e.g. A - dk_array.push(deadkeyed_raw[ss][3]) // Keyname dk e.g. K_N - dk_array.push(deadkeyed_raw[ss][4]) // deadkeyed e.g. à + if ((deadkeyables_raw[rr].modifiers_first === deadkeyed_raw[ss].modifiers_first) && + ((deadkeyables_raw[rr].key_first === deadkeyed_raw[ss].key_first))) { + + dk_array.push(new TextDecoder().decode(deadkeyables_raw[rr].chars)) // deadkeyable e.g. A + dk_array.push(deadkeyed_raw[ss].key_second) // Keyname dk e.g. K_N + dk_array.push(new TextDecoder().decode(deadkeyed_raw[ss].deadkeyed)) // deadkeyed e.g. à } if (dk_array.length > 0) dk_array_comlpete.push(dk_array) } } - console.log("dk_array_comlpete", dk_array_comlpete.length, dk_array_comlpete) - // remove duplicates - const [unique_dk_array_comlpete] = dk_array_comlpete.reduce((acc, curr) => { + const unique_dk_array_comlpete = dk_array_comlpete.reduce((acc, curr) => { const [uniq, set] = acc; if (!set.has(curr.join(','))) { set.add(curr.join(',')); @@ -933,22 +1061,21 @@ export class KeylayoutToKmnConverter { return acc; }, [[], new Set()], ); - console.log("unique_join_dkable_dked", unique_dk_array_comlpete.length, unique_dk_array_comlpete); - // deadkeyablesArray'a' 'A' 'e' 'E' 'y' 'Y' 'o' 'O' 'u' 'U' 'i' 'I' - // deadkeyedArray 'ä' 'Ä' 'ë' 'Ë' 'ÿ' 'Ÿ' 'ö' 'Ö' 'ü' 'Ü' 'ï' 'Ï' const deadkeyedElement: string[][] = Array.from({ length: uniqueDeadkeys.length }, () => new Array(2).fill('')); const deadkeyablesElement: string[][] = Array.from({ length: uniqueDeadkeys.length }, () => new Array(1).fill('')); + + // why is there a set entry???? deadkeyables_raw[0] for (let i = 0; i < uniqueDeadkeys.length; i++) { - for (let j = 0; j < unique_dk_array_comlpete.length; j++) { + for (let j = 0; j < unique_dk_array_comlpete[0].length; j++) { - if (uniqueDeadkeys[i][2] === unique_dk_array_comlpete[j][1]) { - deadkeyablesElement[i][0] = deadkeyablesElement[i][0] + "\'" + unique_dk_array_comlpete[j][0] + "\' " - deadkeyedElement[i][0] = deadkeyedElement[i][0] + "\'" + unique_dk_array_comlpete[j][2] + "\' " + if (uniqueDeadkeys[i].key_first === unique_dk_array_comlpete[0][j][1]) { + deadkeyablesElement[i][0] = deadkeyablesElement[i][0] + "\'" + unique_dk_array_comlpete[0][j][0] + "\' " + deadkeyedElement[i][0] = deadkeyedElement[i][0] + "\'" + unique_dk_array_comlpete[0][j][2] + "\' " } + deadkeyedElement[i][1] = uniqueDeadkeys[i].dk_hex } - deadkeyedElement[i][1] = (uniqueDeadkeys[i][6]) } data += "\n" @@ -965,29 +1092,40 @@ export class KeylayoutToKmnConverter { return data } - public createData_Rules(data_ukelele: convert_object, workArray2D: string[][]): string { + public createData_Rules(data_ukelele: convert_object, workArray2D: any[]): string { const maxkey = 50 let data: string = "" let keymarker = "" - // select only lines that contain C0 or C1 and create an output. Also remove duplicates - const [uniqueDeadkeys] = workArray2D.reduce((acc, curr) => { - if ((curr[3] !== "") && ((curr[0] === "first_modifier_C0") || (curr[0] === "first_modifier_C1"))) { - const [uniq, set] = acc; - if (!set.has(curr.join(','))) { - set.add(curr.join(',')); - uniq.push(curr); - } + // can I use dataUkeklele /ruledata to get uniqueDeadkeys_all + // select only lines that contain C0 or C1 and create an output. + const uniqueDeadkeys_all = workArray2D.filter((curr) => { + if ((curr.chars !== new TextEncoder().encode("") || curr.chars !== undefined) + && (curr.type_C === "first_modifier_C0") || (curr.type_C === "first_modifier_C1")) { + return curr; } - return acc; - }, [[], new Set()], - ); + }); + + // Also remove duplicates + const uniqueDeadkeys = uniqueDeadkeys_all.reduce((unique, o) => { + if (!unique.some((obj: { chars: any; type_C: any; modifiers_first: any; key_first: any }) => + new TextDecoder().decode(obj.chars) === new TextDecoder().decode(o.chars) + && obj.key_first === o.key_first + && obj.type_C === o.type_C + && obj.modifiers_first === o.modifiers_first) + ) { + unique.push(o); + } + return unique; + }, []); + for (let kkk = 0; kkk < uniqueDeadkeys.length; kkk++) { // lookup key nr of the key that is being processed + let keyNr = 0; for (let pp = 0; pp < maxkey; pp++) { - if (this.map_UkeleleKC_To_VK(pp) === uniqueDeadkeys[kkk][2]) + if (this.map_UkeleleKC_To_VK(pp) === uniqueDeadkeys[kkk].key_first) keyNr = pp } @@ -996,15 +1134,16 @@ export class KeylayoutToKmnConverter { continue // add a line after rules of each key - if (uniqueDeadkeys[kkk][2] !== keymarker) + if (uniqueDeadkeys[kkk].key_first !== keymarker) data += '\n' - data += keyNr + "-(modif:" + "ii" + "-" + "i" + `) + [` + (uniqueDeadkeys[kkk][1] + ' ' + uniqueDeadkeys[kkk][2]).trim() + `] > \'` + uniqueDeadkeys[kkk][3] + '\'\n' - keymarker = uniqueDeadkeys[kkk][2] + // write rule + data += keyNr + "-(modif:" + uniqueDeadkeys[kkk].type_C + "-" + "i" + `) + [` + (uniqueDeadkeys[kkk].modifiers_first + ' ' + uniqueDeadkeys[kkk].key_first).trim() + `] > \'` + new TextDecoder().decode(uniqueDeadkeys[kkk].chars) + '\'\n' + keymarker = uniqueDeadkeys[kkk].key_first } data += '\n' - console.log("data ", data) + // console.log("data ", data) return data } @@ -1037,28 +1176,32 @@ export class KeylayoutToKmnConverter { return data } - public createDataToWrite(data_ukelele: convert_object): string { + public create_KMN_Data(data_ukelele: convert_object): string { - // create a string array to work with ................................................ - const workArray2D: string[][] = [] - for (let k = 0; k < data_ukelele.ArrayOf_processed_RuleData.length; k++) { - const array1D: string[] = [] - for (let l = 0; l < data_ukelele.ArrayOf_processed_RuleData[k].length; l++) { - const u8data = data_ukelele.ArrayOf_processed_RuleData[k][l] - array1D.push(new TextDecoder().decode(u8data)) - } - workArray2D.push(array1D) + // create an array to work with ................................................ + const workArray2D: any[] = [] + for (let k = 0; k < data_ukelele.ArrayOf_Rules.length; k++) { + workArray2D.push(data_ukelele.ArrayOf_Rules[k]) } - console.log("workArray2D ", workArray2D) - let data: string = "" + // add top part of kmn file: STORES data += this.createData_Stores(data_ukelele) + // add middle part of kmn file: Rules data += this.createData_Rules(data_ukelele, workArray2D) + // add bottom part of kmn file: DEADKEYS data += this.createData_Deadkeys(data_ukelele, workArray2D) + return data } + /* public removeDuplicates(myArr: any[], type: string | number, modi: string | number, char: string | number) { + return myArr.filter((obj: { [x: string]: any; }, pos: any, arr: any[]) => { + return arr.map((mapObj: { [x: string]: any; }) => ( + (mapObj[type]).indexOf(obj[type]) === pos) + && ((mapObj[modi]).indexOf(obj[modi]) === pos)) + }) + }*/ // public lookup_2_KeyMapAction__To__ActionAction() { } //public lookup_4_ActionNext__To__ActionState() { } //public lookup_7_ActionState__To__ActionOutput() { } @@ -1104,5 +1247,30 @@ export class KeylayoutToKmnConverter { } return str }*/ +} + + +class Rules { + + constructor( + public type_C: string, + public modifiers_first: string, + public key_first: string, + public modifiers_second: string, + public key_second: string, + + public chars: Uint8Array, + public isTerminator: boolean, + public dk_hex: string, + public dk_char: Uint8Array, //todo needed? + + public deadkeys: Uint8Array, + public deadkeyables: Uint8Array, + public deadkeyed: Uint8Array, + ) { } + + public getval() { + return `blabla ${this.isTerminator} blub: ${this.type_C}...` + } } From a03c921df3d8ee5ae8615bfd10fbd86c3326a74a Mon Sep 17 00:00:00 2001 From: Sabine Date: Tue, 14 Jan 2025 17:01:47 +0100 Subject: [PATCH 038/251] feat(developer): kmc-convert C0, C1, C2, C4 create correct data --- .../keylayout-to-kmn-converter.ts | 1014 ++++++++++++----- 1 file changed, 722 insertions(+), 292 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index fb1da508393..4d0eec971ac 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -55,8 +55,9 @@ import boxXmlArray = util.boxXmlArray;*/ // rearrange code to use read, convert, write // remove all any // TODO rewrite explanantion for object instead of array - // remove all any types - // let push_count = 0 // Todo remove later + // remove all any types + // let push_count = 0 // Todo remove later + // check code for code styses keyman } import { XMLParser } from 'fast-xml-parser'; // for reading a file @@ -140,6 +141,23 @@ export interface rule_object { deadkeys: Uint8Array, /* deadkeys to add to a character (e.g. ^,´,`,~ ) */ deadkeyables: Uint8Array, /* characters that can use a deadkey (e.g. a,e,i,o,u )*/ deadkeyed: Uint8Array, // deadkeys+deadkeyables (e.g. â,ê,î,ô,û) + + + /* ****************************************** */ + + prev_deadkey: string, + modifier_prev_deadkey: string, + prev_deadkeys_Ch: Uint8Array, + + deadkey: string, + modifier_deadkey: string, + deadkeys_Ch: Uint8Array, + + key: string, + modifier_key: string, + deadkeyed_Ch: Uint8Array, + + }; export interface convert_object { @@ -152,7 +170,7 @@ export class KeylayoutToKmnConverter { static readonly INPUT_FILE_EXTENSION = '.keylayout'; static readonly OUTPUT_FILE_EXTENSION = '.kmn'; - // TODO use callbacks + // TODO use callbacks what about /*private*/ for options //constructor(/*private*/ _callbacks: CompilerCallbacks, /*private*/ _options: CompilerOptions) { constructor(private callbacks: CompilerCallbacks, options: CompilerOptions) { // TODO: if these are needed, uncomment /*private*/ and remove _, and they will then @@ -223,6 +241,7 @@ export class KeylayoutToKmnConverter { console.log("xmlFile_name", (process.cwd() + "\\data" + filename.substring(filename.lastIndexOf("\\"))).replace(" ", "")) //const xmlFile = readFileSync(`${process.cwd()}/data/MySample.keylayout`, 'utf8') const xmlFile = readFileSync((process.cwd() + "\\data" + filename.substring(filename.lastIndexOf("\\"))).replace(" ", ""), 'utf8'); + console.log("xmlFile parsed ") // we don`t need file-read with uint8array return /*const fullPath = (process.cwd() + "\\data" + filename.substring(filename.lastIndexOf("\\"))).replace(" ", "") @@ -291,13 +310,48 @@ export class KeylayoutToKmnConverter { // for more info about mapping and cases C0-C4 see https://docs.google.com/document/d/1ISjACTA9aUBueTo1AoKnOsI6QR5kXeeD_maI0XUyXqg/edit?tab=t.0 public createRuleData(data_ukelele: convert_object, jsonObj: any): convert_object { - const DataArray_U8: Uint8Array[][] = [] const ObjectArray: any[] = [] + let dk_counter = 0 + + // start Tests v ToDo remove + const testArray_Ukelele: string[] = [] + let testArray_Ukelele_count = 0 + const testArray_Ukelele_action: string[] = [] + let testArray_Ukelele_action_count = 0 + + const testArray_kmn: string[] = [] + const testArray_kmn_action: string[] = [] + let testArray_kmn_action1: string[] = [] + let testArray_kmn_count = 0 + let testArray_kmn_action_count = 0 + + + // loop behaviors ( in ukelele it is possible to define multiple modifier combinations that behave in the same) + for (let i = 0; i < jsonObj.keyboard.keyMapSet[0].keyMap.length; i++) { + // loop keys 0-50 (= all keys we use) + for (let j = 0; j < 51; j++) { + + if ((jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] !== undefined)) { + testArray_Ukelele.push(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output']) + testArray_Ukelele_count++ + } + } + } + + for (let k = 0; k < jsonObj.keyboard.actions.action.length; k++) { + for (let j = 0; j < jsonObj.keyboard.actions.action[k].when.length; j++) { + if (jsonObj.keyboard.actions.action[k].when[j]['@_output'] !== undefined) { + testArray_Ukelele_action.push(jsonObj.keyboard.actions.action[k].when[j]['@_output']) + testArray_Ukelele_action_count++ + } + } + } + // End Tests ToDo remove ^ + let action_id - let output_id - let push_count = 0 // Todo remove later const used_Keys_count = 51 + const isCapsused = this.checkIfCapsUsed(data_ukelele.ArrayOf_Modifiers) // loop keys 0-50 (= all keys we use) @@ -308,109 +362,128 @@ export class KeylayoutToKmnConverter { // ...................................................................................................... // case C0: output ...................................................................................... - // a key is mapped to a character directly ( code-> output) ............................................. + /*// a key is mapped to a character directly ( code-> output) ............................................. // ...............e. g. ...................................................... // ...................................................................................................... // in keys at top for code 1 (K_S) take output ("s") [italian copy] // get modifiers [modifer of Keymap index 0] // write [modifer-of-Keymap-index-0 K_S] > s + + [ key code="1" -> output="s" ] + + + + */ // ...................................................................................................... let RuleObj - if (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] !== undefined) { - output_id = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] + let out_ch = "" + // if this is an output tag + if ((jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] !== undefined)) { + + testArray_kmn.push(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output']) + testArray_kmn_count++ + if (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] !== "") + out_ch = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] // loop modifier combinations for (let l = 0; l < data_ukelele.ArrayOf_Modifiers[i].length; l++) { - const DataArraySingleStateC0_U8: Uint8Array[] = [] - - if ((output_id !== "") || (output_id !== undefined)) { - const first_modifier_C0_U8 = new TextEncoder().encode(this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[i][l], isCapsused)); - const first_key_C0_U8 = new TextEncoder().encode(this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']))); - const result_C0_U8 = new TextEncoder().encode(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output']); - - DataArraySingleStateC0_U8.push(new TextEncoder().encode("first_modifier_C0")) - DataArraySingleStateC0_U8.push(first_modifier_C0_U8) - DataArraySingleStateC0_U8.push(first_key_C0_U8) - DataArraySingleStateC0_U8.push(result_C0_U8) - + if (this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']))) { RuleObj = new Rules( - "first_modifier_C0", + "C0", this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[i][l], isCapsused), this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), "", "", - result_C0_U8, + new TextEncoder().encode(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output']), false, "", new TextEncoder().encode(""), new TextEncoder().encode(""), new TextEncoder().encode(""), - new TextEncoder().encode("") - ) + new TextEncoder().encode(""), - } + "", + "", + new TextEncoder().encode(""), + 0, + + "", + "", + new TextEncoder().encode(""), + 0, - if (DataArraySingleStateC0_U8.length > 0) { - DataArray_U8.push(DataArraySingleStateC0_U8) - push_count++ + this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[i][l], isCapsused), + this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), + new TextEncoder().encode(out_ch), + ) ObjectArray.push(RuleObj) } } } - // ...................................................................................................... - // case C1: action + state none + output ................................................................ - // a key is mapped to an action and then to an output ................................................... - // code->action->action(none)->action(output) ........................................................... - // ...............e. g. a - // ...................................................................................................... + // if this is an action tag else if (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] !== undefined) { + // ...................................................................................................... + // case C1: action + state none + output ................................................................ + // a key is mapped to an action and then to an output ................................................... + // code->action->action(none)->action(output) ........................................................... + // ...............e. g. a + /* + + /* [key code="0" -> action="a9" -> action id="a9" -> state="none" -> output="a" ] + + + + ... + + + + */ + // ...................................................................................................... action_id = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] - const result_C1 = this.lookup_6_ActionNone__To__ActionOutput(jsonObj, action_id) - const result_C1_U8 = new TextEncoder().encode(this.lookup_6_ActionNone__To__ActionOutput(jsonObj, action_id)) - // loop modifiers for (let l = 0; l < data_ukelele.ArrayOf_Modifiers[i].length; l++) { - const DataArraySingleStateC1_U8: Uint8Array[] = [] - if (result_C1 !== undefined) { - const first_modifier_C1_U8 = new TextEncoder().encode(this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[i][l], isCapsused)) - const first_key_C1_U8 = new TextEncoder().encode(this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']))) - - DataArraySingleStateC1_U8.push(new TextEncoder().encode("first_modifier_C1")) - DataArraySingleStateC1_U8.push(first_modifier_C1_U8) - DataArraySingleStateC1_U8.push(first_key_C1_U8) - DataArraySingleStateC1_U8.push(result_C1_U8) + const none_output = this.lookup_6_ActionNone__To__ActionOutput(jsonObj, action_id) + if (none_output !== undefined) { RuleObj = new Rules( - "first_modifier_C1", + "C1", this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[i][l], isCapsused), this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), "", "", - result_C1_U8, + new TextEncoder().encode(none_output), false, "", new TextEncoder().encode(""), new TextEncoder().encode(""), new TextEncoder().encode(""), - new TextEncoder().encode("") - ) + new TextEncoder().encode(""), + /* ****************************************** */ + "", + "", + new TextEncoder().encode(""), + 0, - if (DataArraySingleStateC1_U8.length > 0) { - DataArray_U8.push(DataArraySingleStateC1_U8) + "", + "", + new TextEncoder().encode(""), + 0, - push_count++ - } + this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[i][l], isCapsused), + this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), + new TextEncoder().encode(none_output) + ) ObjectArray.push(RuleObj) } } @@ -430,67 +503,92 @@ export class KeylayoutToKmnConverter { // get second modifiers [modifer of Keymap index 3] (=anyOption) // [modifer of Keymap index 3] + K_A + K_9 > à // write: [modifer-of-Keymap-index-0 K_A] > dk(dk1) ; dk(dk1) + [second modifiers K_9] > à + + /* [ key code="0" -> action="a9" -> action id="a9" -> state="1" -> output="â ] + + + + + + + + [state="1" ≙ next="1" <- state="none" <- action id="a18 <- key code="24" <- keyMap index="3"] + + + + + + + + */ // ...................................................................................................... - let result_C2 - let result_C2_U8 - let nextvalArray: string[] = [] + let result_C2: string + let nextVal: string[] = [] - // get action id: e.g. id a16 ->id nr 8 + // find the nth action id e.g. id a9 ->id nr 20 action_id = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] - const indexInActions = this.lookup_10_ActionId__To__ActioIndex(jsonObj, action_id) + const indexOfActions = this.lookup_10_ActionId__To__ActioIndex(jsonObj, action_id) - // loop through all actionh/when find state and get action id ( 8-> state 3) - for (let jj = 0; jj < jsonObj.keyboard.actions.action[indexInActions].when.length; jj++) { + // loop through all actionh/when find state and get action id ( 20-> state = 1) + for (let jj = 0; jj < jsonObj.keyboard.actions.action[indexOfActions].when.length; jj++) { + const stateVal = jsonObj.keyboard.actions.action[indexOfActions].when[jj]['@_state'] - const stateVal = jsonObj.keyboard.actions.action[indexInActions].when[jj]['@_state'] + if (jsonObj.keyboard.actions.action[indexOfActions].when[jj]['@_output'] !== undefined) { + testArray_kmn_action.push(jsonObj.keyboard.actions.action[indexOfActions].when[jj]['@_output']) + testArray_kmn_action_count++ + } + testArray_kmn_action1 = testArray_kmn_action.filter(function (item, pos, self) { + return self.indexOf(item) == pos; + }) - // if there is a state defined, collect all cases which result in that state ( e.g. which case has next = 3) + // if there is a state defined, collect all cases which result in that state ( e.g. which action id contains next = 1) if (stateVal !== undefined) { // get output - result_C2 = jsonObj.keyboard.actions.action[indexInActions].when[jj]['@_output'] - result_C2_U8 = new TextEncoder().encode(jsonObj.keyboard.actions.action[indexInActions].when[jj]['@_output']) + result_C2 = jsonObj.keyboard.actions.action[indexOfActions].when[jj]['@_output'] + // console.log(" typeof(result_C2",typeof(result_C2),typeof( new TextEncoder().encode(result_C2)),typeof(new TextDecoder().decode( (new TextEncoder().encode(result_C2))))) + // get all cases which result in state 3 - nextvalArray = this.lookup_5_ActionState__To__ActionNext_none(jsonObj, stateVal) + nextVal = this.lookup_5_ActionState__To__ActionNext_none(jsonObj, stateVal) // for all modifier combinations for (let l = 0; l < data_ukelele.ArrayOf_Modifiers[i].length; l++) { - - const DataArraySingleStateC2_U8: Uint8Array[] = [] - for (let k = 0; k < nextvalArray.length; k++) { + for (let k = 0; k < nextVal.length; k++) { if (result_C2 !== undefined) { + const KeymapIndey = this.lookup_15_KeyMapAction__To__KeyMapIndex(jsonObj, nextVal[k]) + + for (let zz = 0; zz < data_ukelele.ArrayOf_Modifiers[KeymapIndey].length; zz++) { + RuleObj = new Rules( + "C2", + this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[i][l], isCapsused), + this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), + this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[KeymapIndey][zz], isCapsused), + this.map_UkeleleKC_To_VK(Number(this.lookup_11_KeyMapAction__To__KeyMapCode(jsonObj, nextVal[k]))), + new TextEncoder().encode(""), + false, + "", + new TextEncoder().encode(""), + new TextEncoder().encode(""), + new TextEncoder().encode(""), + new TextEncoder().encode(result_C2), + + "", + "", + new TextEncoder().encode(""), + 0, + + this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[KeymapIndey][zz], isCapsused), + this.map_UkeleleKC_To_VK(Number(this.lookup_11_KeyMapAction__To__KeyMapCode(jsonObj, nextVal[k]))), + new TextEncoder().encode(""), + dk_counter++, + + this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[i][l], isCapsused), + this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), + new TextEncoder().encode(result_C2) + ) - const first_modifier_C2_U8 = new TextEncoder().encode(this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[i][l], isCapsused)) - const first_Key_C2_U8 = new TextEncoder().encode(this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']))) - const second_Key_C2_U8 = new TextEncoder().encode(this.map_UkeleleKC_To_VK(Number(this.lookup_11_KeyMapAction__To__KeyMapCode(jsonObj, nextvalArray[k])))) - - DataArraySingleStateC2_U8.push(new TextEncoder().encode("first_modifier_C2")) - DataArraySingleStateC2_U8.push(first_modifier_C2_U8) - DataArraySingleStateC2_U8.push(first_Key_C2_U8) - DataArraySingleStateC2_U8.push(second_Key_C2_U8)// state = none -> no modifier - DataArraySingleStateC2_U8.push(result_C2_U8) - - RuleObj = new Rules( - "first_modifier_C2", - this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[i][l], isCapsused), - this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), - "", - this.map_UkeleleKC_To_VK(Number(this.lookup_11_KeyMapAction__To__KeyMapCode(jsonObj, nextvalArray[k]))), - new TextEncoder().encode(""), - false, - "", - new TextEncoder().encode(""), - new TextEncoder().encode(""), - new TextEncoder().encode(""), - result_C2_U8 - ) - - - if (DataArraySingleStateC2_U8.length > 0) { - DataArray_U8.push(DataArraySingleStateC2_U8) - - push_count++ ObjectArray.push(RuleObj) + // console.log("RuleObj", RuleObj) } } } @@ -505,31 +603,67 @@ export class KeylayoutToKmnConverter { // a key is mapped to an action and then to a terminator ................................................ // code->action->action(state)->action(next)->terminator(output) ........................................ // ...................................................................................................... - {// in keys at top for code 10 (=K_BACKQUOTE) take actions id (a57) [German standard copy] - // code 10 = K_BACKQUOTE (or another key 93) - // get modifiers [modifer of Keymap index 0] - // goto action id a57 and find 14 in - // find all rules that result in 14 (next="14" - there might be several) - // get actionsId and of that rule (a80 ) - // look at top for a80 and find key Code (code 40 = K_K) - // get modifiers Index of that key (code 40) [modifer of Keymap index 3] - // lookup modifier names from modifiers Index - // take 20 ( of next="20") and look for state = 20 in terminators ("next" points to terminators) - // get output ("̭") - // [first modifier + K_K] > dk(dk1) ; dk(dk1) + [second modifier K_BKQUOTE] > "̭" - } + // in keys at top for code 10 (=K_BACKQUOTE) take actions id (a57) [German standard copy] + // code 10 = K_BACKQUOTE (or another key 93) + // get modifiers [modifer of Keymap index 0] + // goto action id a57 and find 14 in + // find all rules that result in 14 (next="14" - there might be several) + // get actionsId and of that rule (a80 ) + // look at top for a80 and find key Code (code 40 = K_K) + // get modifiers Index of that key (code 40) [modifer of Keymap index 3] + // lookup modifier names from modifiers Index + // take 20 ( of next="20") and look for state = 20 in terminators ("next" points to terminators) + // get output ("̭") + // [first modifier + K_K] > dk(dk1) ; dk(dk1) + [second modifier K_BKQUOTE] > "̭" + /* + + [ key code="10" -> action="a57" -> action id="a57" -> state="14" -> next="20 -> state="20" -> output="̭" ] + + + + + + + + + + + + + + [ action="a57" -> action id="a57" -> state="14" -> next="20 -> state="20" -> action id="a40" -> key code="37" ] + + + + + + [state="14" ≙ next="14" <- action id="a80 <- key code="40" <- keyMap index="3"] + + + + + + + + + + + + + */ // ...................................................................................................... - // get a9 in behavior/key - action_id = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] - const actionIdIndex = this.lookup_10_ActionId__To__ActioIndex(jsonObj, action_id) - const DataArraySingleStateC3_U8: Uint8Array[] = [] - let value_state let value_next - let the_ContextKeyNr - let first_key_C3_U8 + let ContextKeyNr_deadkey + let ContextKeyNr_deadkey1 let keymapIndexForactionID_2: any[][] + //let keymapIndexForactionID + let modifier: string[] + + // get a9 in behavior/key + action_id = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] + const actionIdIndex = this.lookup_10_ActionId__To__ActioIndex(jsonObj, action_id) // loop all action-when and find state-next-pair for (let l = 0; l < jsonObj.keyboard.actions.action[actionIdIndex].when.length; l++) { @@ -538,66 +672,157 @@ export class KeylayoutToKmnConverter { if ((jsonObj.keyboard.actions.action[actionIdIndex].when[l]['@_state'] !== "none") && (jsonObj.keyboard.actions.action[actionIdIndex].when[l]['@_next'] !== undefined)) { - value_state = jsonObj.keyboard.actions.action[actionIdIndex].when[l]['@_state'] // e.g. 3 - value_next = jsonObj.keyboard.actions.action[actionIdIndex].when[l]['@_next'] // e.g. 1 + // Data of Block Nr 5 .......................................................... + /* 5: state =3 */ value_state = jsonObj.keyboard.actions.action[actionIdIndex].when[l]['@_state'] + /* 5: next =1 */ value_next = jsonObj.keyboard.actions.action[actionIdIndex].when[l]['@_next'] + /* 5: actioniD = a16 */ const theContextID = jsonObj.keyboard.actions.action[actionIdIndex]['@_id'] // get actionId of that state/next pair (14,20) e.g. actionId a57 //my a16 NNNRRR 5 + // ........................................................................ + + // Data of Block Nr 4 .......................................................... + /* 4: code = 32 */ ContextKeyNr_deadkey = this.lookup_11_KeyMapAction__To__KeyMapCode(jsonObj, theContextID) // find keyNr of that actionID a57> code=37 // my 32 ( K_U) + /* 4: K_U */ //first_key_C3_U8_deadkey = new TextEncoder().encode(this.map_UkeleleKC_To_VK(Number(ContextKeyNr_deadkey))) + /* 4: MapIndexArr=[32 3] */ keymapIndexForactionID_2 = this.lookup_14_ActionName__To__MapIndex(jsonObj, String(theContextID)) + /* 4: MapIndex 3 */ //keymapIndexForactionID = this.lookup_14_ActionName__To__MapIndexSingle(jsonObj, String(theContextID)) + /* [32 3] */ modifier = this.lookup_11_KeyMapIndex__To__Modifier(data_ukelele.ArrayOf_Modifiers, 1) + // ........................................................................ + + // Data of Block Nr 3 .......................................................... + //must be array ??? + /* 3: actioniD = a17 */ const ActionId_prev_dk = this.lookup_5_ActionState__To__ActionNext_str(jsonObj, value_state) + // ........................................................................ + + // Data of Block Nr 2 .......................................................... + /* 2: code = 28 */ ContextKeyNr_deadkey1 = this.lookup_11_KeyMapAction__To__KeyMapCode(jsonObj, ActionId_prev_dk) + /* 2: K_8 */ const prev_deadkey = this.map_UkeleleKC_To_VK(Number(ContextKeyNr_deadkey1)) + /* 2 index=3 */ const modificator = this.lookup_14_ActionName__To__MapIndex(jsonObj, String(ActionId_prev_dk)) + /* 2 CAPS*/ const modiInText = this.lookup_11_KeyMapIndex__To__Modifier(data_ukelele.ArrayOf_Modifiers, modificator[0][1]) + // ........................................................................ + + // Data of Block Nr 6 .......................................................... + /* 6: [ 'a9', '1', 'â' ] */ const stateArray = this.lookup_13_ActionNext__To__AllState(jsonObj, value_next) + /* 6: output = â */ const output_all = this.lookup_17_ActionState__To__ActionOutput(jsonObj, value_next, stateArray[0][0]) + // ........................................................................ + + for (let a = 0; a < stateArray.length; a++) { + + // Data of Block Nr 1 .......................................................... + // todo get all state1´s + /* 2: code = 0 */ const keycode = this.lookup_11_KeyMapAction__To__KeyMapCode(jsonObj, stateArray[a][0]) + /* 2: K_A */ const keyname = this.map_UkeleleKC_To_VK(Number(keycode)) + // ........................................................................ + + // a16 hasstate + // field 1: which code has action a0 or a9 or... + const modif = this.lookup_15_KeyMapAction__To__KeyMapIndex_Arr(jsonObj, stateArray[a][0], keycode) + //console.log("modif ", modif) + + for (let jj = 0; jj < modif.length; jj++) { + + for (let kk = 0; kk < modiInText.length; kk++) { + + const modifierText = this.lookup_11_KeyMapIndex__To__Modifier(data_ukelele.ArrayOf_Modifiers, Number(modif[jj][0])) + const modiflat = modifierText.flat() + const modi = this.create_kmn_modifier(modiflat[0], isCapsused) + + RuleObj = new Rules( + "CX", + + modi, + keyname, - // get actionId of that state/next pair (3,1) e.g. actionId a17 - const theContextID = this.lookup_13_ActionNext__To__ActionID(jsonObj, value_state) - // find keyNr of that actionID a17-> code=28 - the_ContextKeyNr = this.lookup_11_KeyMapAction__To__KeyMapCode(jsonObj, theContextID) + //this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[i][l], isCapsused), + "modifier", + this.map_UkeleleKC_To_VK(Number(ContextKeyNr_deadkey)), + + new TextEncoder().encode(""), + false, + "", + new TextEncoder().encode(""), + new TextEncoder().encode(""), + new TextEncoder().encode(""), + new TextEncoder().encode(""), +/* ****************************************** */ + + this.create_kmn_modifier(modiInText[kk],isCapsused), + prev_deadkey, + new TextEncoder().encode(""), + dk_counter++, + + this.create_kmn_modifier( modifier[0],isCapsused), + this.map_UkeleleKC_To_VK(Number(ContextKeyNr_deadkey)), + new TextEncoder().encode(""), + dk_counter++, - // find all occurences of a17 e.g. key 28/3 [ [ '28', 3 ] ] - keymapIndexForactionID_2 = this.lookup_14_ActionName__To__MapIndex(jsonObj, String(theContextID)) - // get keyname e.g. 28-> K_8 - first_key_C3_U8 = new TextEncoder().encode(this.map_UkeleleKC_To_VK(Number(the_ContextKeyNr))) + modi, + keyname, + new TextEncoder().encode(output_all), + ) + ObjectArray.push(RuleObj) + console.log("qqqqq C3 RuleObj", RuleObj) + + + } + } + } } const result_C3_U8 = new TextEncoder().encode(this.lookup_9_TerminatorState__To__TerminatorOutput_str(jsonObj, value_next)) for (let l = 0; l < data_ukelele.ArrayOf_Modifiers[i].length; l++) { - const second_modifier_C3_U8 = new TextEncoder().encode(this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[i][l], isCapsused)) - if (the_ContextKeyNr !== undefined) { - const second_key_Nr = Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']) - const second_key_C3_U8 = new TextEncoder().encode(this.map_UkeleleKC_To_VK(second_key_Nr)) + if (ContextKeyNr_deadkey !== undefined) { for (let kk = 0; kk < data_ukelele.ArrayOf_Modifiers[keymapIndexForactionID_2[0][1]].length; kk++) { - const first_modifier_text_C3_U8 = data_ukelele.ArrayOf_Modifiers[keymapIndexForactionID_2[0][1]][kk] - const first_modifier_C3_U8 = new TextEncoder().encode(this.create_kmn_modifier(first_modifier_text_C3_U8, isCapsused)) + //console.log("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ") + + for (let jj = 0; jj < modifier.length; jj++) { - DataArraySingleStateC3_U8.push(new TextEncoder().encode("first_modifier_C3")) - DataArraySingleStateC3_U8.push(first_modifier_C3_U8) - DataArraySingleStateC3_U8.push(first_key_C3_U8) + const first_modifier_text_C3_U8_deadkey = data_ukelele.ArrayOf_Modifiers[keymapIndexForactionID_2[0][1]][kk] - DataArraySingleStateC3_U8.push(second_modifier_C3_U8) - DataArraySingleStateC3_U8.push(second_key_C3_U8) + if (this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])) !== "") { + console.log("(this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])) ", + (this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])))) - DataArraySingleStateC3_U8.push(result_C3_U8) + console.log(" ",) + console.log(" ",) + console.log("this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])) ", this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']))) + // ToDo is C3 this really neccessary? - I think no! ) + RuleObj = new Rules( + "C3", - RuleObj = new Rules( - "first_modifier_C3", - this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[i][l], isCapsused), - this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), + this.create_kmn_modifier(first_modifier_text_C3_U8_deadkey, isCapsused), + this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), - this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[i][l], isCapsused), - this.map_UkeleleKC_To_VK(second_key_Nr), + modifier[jj], + this.map_UkeleleKC_To_VK(Number(ContextKeyNr_deadkey)), - result_C3_U8, - false, - "", - new TextEncoder().encode(""), - new TextEncoder().encode(""), - new TextEncoder().encode(""), - new TextEncoder().encode("") - ) + result_C3_U8, + false, + "", + new TextEncoder().encode(""), + result_C3_U8, + new TextEncoder().encode(""), + new TextEncoder().encode(""), - if (DataArraySingleStateC3_U8.length > 0) { - DataArray_U8.push(DataArraySingleStateC3_U8) + this.create_kmn_modifier(modifier[jj], isCapsused), + this.map_UkeleleKC_To_VK(Number(ContextKeyNr_deadkey)), + new TextEncoder().encode(""), + 0, - push_count++ + this.create_kmn_modifier(first_modifier_text_C3_U8_deadkey, isCapsused), + this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), + new TextEncoder().encode(""), + 0, + + this.create_kmn_modifier(modifier[jj], isCapsused), + this.map_UkeleleKC_To_VK(Number(ContextKeyNr_deadkey)), + result_C3_U8 + ) + ObjectArray.push(RuleObj) + console.log("qqqqq C3 RuleObj", RuleObj) + } } } - ObjectArray.push(RuleObj) } } } @@ -612,49 +837,59 @@ export class KeylayoutToKmnConverter { // in actions a16 () find state "none" and get next (=4) // in terminators ( ) find the state (=4) and get output ("¨") // write [modifer of Keymap index 3 + K_U] -> "¨" + /* + [ action="a16" -> action id="a16" -> state="none" -> next="4 -> state="4" -> output="¨" ] + + + - action_id = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] + + + - const next_id = this.lookup_3_ActionNone__To__ActionNext(jsonObj, action_id) - const result_C4_U8 = new TextEncoder().encode(this.lookup_9_TerminatorState__To__TerminatorOutput_str(jsonObj, next_id)) + + + + */ - for (let l = 0; l < data_ukelele.ArrayOf_Modifiers[i].length; l++) { - const DataArraySingleStateC4_U8: Uint8Array[] = [] - const first_modifier_C4_U8 = new TextEncoder().encode(this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[i][l], isCapsused)) - const first_key_C4_U8 = new TextEncoder().encode(this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']))) - const str_UTF8 = new TextDecoder().decode(result_C4_U8) + action_id = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] - DataArraySingleStateC4_U8.push(new TextEncoder().encode("first_modifier_C4")) - DataArraySingleStateC4_U8.push(first_modifier_C4_U8) - DataArraySingleStateC4_U8.push(first_key_C4_U8) - DataArraySingleStateC4_U8.push(result_C4_U8) + const next_id = this.lookup_3_ActionNone__To__ActionNext(jsonObj, action_id) + const result_C4 = new TextEncoder().encode(this.lookup_9_TerminatorState__To__TerminatorOutput_str(jsonObj, next_id)) - if (result_C4_U8.length !== 0) { - DataArraySingleStateC4_U8.push(new TextEncoder().encode("isTerminator")) - DataArraySingleStateC4_U8.push(result_C4_U8) - DataArraySingleStateC4_U8.push(new TextEncoder().encode(this.getHexFromChar(str_UTF8))) + for (let l = 0; l < data_ukelele.ArrayOf_Modifiers[i].length; l++) { + if (result_C4.length !== 0) { RuleObj = new Rules( - "first_modifier_C4", + "C4", this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[i][l], isCapsused), this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), "", "", new TextEncoder().encode(this.lookup_9_TerminatorState__To__TerminatorOutput_str(jsonObj, next_id)), true, - this.getHexFromChar(str_UTF8), - new TextEncoder().encode(this.getHexFromChar(str_UTF8)), - new TextEncoder().encode(this.lookup_9_TerminatorState__To__TerminatorOutput_str(jsonObj, next_id)), - new TextEncoder().encode(this.lookup_9_TerminatorState__To__TerminatorOutput_str(jsonObj, next_id)), - new TextEncoder().encode(this.lookup_9_TerminatorState__To__TerminatorOutput_str(jsonObj, next_id)) - ) - } + this.getHexFromChar(new TextDecoder().decode(result_C4)), + new TextEncoder().encode(this.getHexFromChar(new TextDecoder().decode(result_C4))), + result_C4, /* todo which one to use???*/ + result_C4, + result_C4, - if (DataArraySingleStateC4_U8.length > 0) { - DataArray_U8.push(DataArraySingleStateC4_U8) - push_count++ + "", + "", + new TextEncoder().encode(""), + 0, + + "", + "", + new TextEncoder().encode(""), + 0, + + this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[i][l], isCapsused), + this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), + result_C4 + ) } ObjectArray.push(RuleObj) } @@ -664,9 +899,100 @@ export class KeylayoutToKmnConverter { } } + //--------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------------------- + // TODO remove: test files: checkif kmn gats the same output as ukelele file(except for C3 t works well :)) + //--------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------------------- + + + console.log("start check ", ObjectArray.length) + + for (let k = 0; k < ObjectArray.length; k++) { +//"ObjectArray: k + console.log("Obj: k ", k, + "\tType: ", (ObjectArray[k].type_C !== "" ? ObjectArray[k].type_C : "--".padEnd(4, " ")), + + "| modi_prev_dk: ", (ObjectArray[k].modifier_prev_deadkey !== "" ? ObjectArray[k].modifier_prev_deadkey.padEnd(23, " ") : "--".padEnd(23, " ")), + "key_prev_dk: ", (ObjectArray[k].prev_deadkey !== "" ? ObjectArray[k].prev_deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), + // "ch_prev_dk: ", (new TextDecoder().decode(ObjectArray[k].prev_deadkeys_Ch) !== "" ? new TextDecoder().decode(ObjectArray[k].prev_deadkeys_Ch).padEnd(10, " ") : "--".padEnd(10, " ")), + "is_prev dk(): ", (ObjectArray[k].dk_prev !== 0 ? ("dk_p(" +String(ObjectArray[k].dk_prev)+")").padEnd(11, " ") : "--".padEnd(11, " ")), + + "| modi_dk: ", (ObjectArray[k].modifier_deadkey !== "" ? ObjectArray[k].modifier_deadkey.padEnd(23, " ") : "--".padEnd(23, " ")), + "key_dk: ", (ObjectArray[k].deadkey !== "" ? ObjectArray[k].deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), + // "ch_dk: ", (new TextDecoder().decode(ObjectArray[k].deadkeys_Ch) !== "" ? new TextDecoder().decode(ObjectArray[k].deadkeys_Ch).padEnd(10, " ") : "--".padEnd(10, " ")), + "is dk(): ", (ObjectArray[k].dk !== 0 ? ("dk(" +String(ObjectArray[k].dk)+")").padEnd(9, " ") : "--".padEnd(9, " ")), + + "| modi: ", (ObjectArray[k].modifier_key !== "" ? ObjectArray[k].modifier_key.padEnd(20, " ") : "--".padEnd(20, " ")), + "key: ", (ObjectArray[k].key !== "" ? ObjectArray[k].key.padEnd(8, " ") : "--".padEnd(8, " ")), + "ch: ", (new TextDecoder().decode(ObjectArray[k].deadkeyed_Ch) !== "" ? new TextDecoder().decode(ObjectArray[k].deadkeyed_Ch).padEnd(10, " ") : "--".padEnd(10, " ")), + "| °°" + ) + } + + //remove entries that are available in both arrays + for (let i = 0; i < (testArray_Ukelele.length); i++) { + for (let j = 0; j < (testArray_kmn.length); j++) { + if (testArray_Ukelele[i] === testArray_kmn[j]) { + testArray_Ukelele[i] = "" + testArray_kmn[j] = "" + } + } + } + // remove empty fields + const testArray_Ukelele_filter = testArray_Ukelele.filter((el) => (el !== "")) + const testArray_kmn_filter = testArray_kmn.filter((el) => (el !== "")) + // should be empty now + if (testArray_kmn_filter.length !== testArray_Ukelele_filter.length) + console.log("OOOOHHHH DIFFERENT AMOUNTS ") + else + console.log("####### SAME AMOUNTS :)) ", + "testArray_kmn_filter:", testArray_kmn_filter, "testArray_Ukelele_filter:", testArray_Ukelele_filter) + + //****************************************************************************************** */ + const testArray_Ukelele_action_uni: string[] = testArray_Ukelele_action.filter(function (item, pos, self) { + return self.indexOf(item) == pos; + }) + + //remove entries that are available in both arrays + for (let i = 0; i < (testArray_Ukelele_action_uni.length); i++) { + for (let j = 0; j < (testArray_kmn_action1.length); j++) { + if (testArray_Ukelele_action_uni[i] === testArray_kmn_action1[j]) { + testArray_Ukelele_action_uni[i] = "" + testArray_kmn_action1[j] = "" + } + } + } + // remove empty fields + const testArray_Ukelele_action_uni_filter = testArray_Ukelele_action_uni.filter((el) => (el !== "")) + const testArray_kmn_action_uni_filter = testArray_kmn_action1.filter((el) => (el !== "")) + // should be empty now + if ((testArray_kmn_action_uni_filter.length === 0) && (testArray_Ukelele_action_uni_filter.length === 0)) + console.log("####### SAME AMOUNTS :)) HERE ALSo", + "testArray_kmn_action_uni_filter:", testArray_kmn_action_uni_filter, "testArray_Ukelele_action_uni_filter:", testArray_Ukelele_action_uni_filter) + else + console.log("OOOOHHHH DIFFERENT AMOUNTS ") + + //--------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------------------- + // Test files end + //--------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------------------- + + + data_ukelele.ArrayOf_Rules = ObjectArray return data_ukelele } + + + + + public lookup_3_ActionNone__To__ActionNext(data: any, search: string): string { for (let jj = 0; jj < data.keyboard.actions.action.length; jj++) { if (data.keyboard.actions.action[jj]['@_id'] === search) { @@ -680,7 +1006,7 @@ export class KeylayoutToKmnConverter { } public lookup_5_ActionState__To__ActionNext(data: any, action_idName: string): string[] { const returnarray: string[] = [] - // e.g. action_idName = 3 + // e.g. action_idName = 3 if (action_idName !== "none") { // loop all action/when for (let k = 0; k < data.keyboard.actions.action.length; k++) { @@ -694,6 +1020,21 @@ export class KeylayoutToKmnConverter { } return returnarray } + public lookup_5_ActionState__To__ActionNext_str(data: any, action_idName: string): string { + // e.g. action_idName = 3 + if (action_idName !== "none") { + // loop all action/when + for (let k = 0; k < data.keyboard.actions.action.length; k++) { + for (let j = 0; j < data.keyboard.actions.action[k].when.length; j++) { + // find attribute next === 3 + if (data.keyboard.actions.action[k].when[j]['@_next'] === action_idName) { + return data.keyboard.actions.action[k]['@_id'] + } + } + } + } + return "" + } public lookup_5_ActionState__To__ActionNext_none(data: any, action_idName: string): string[] { const returnarray: string[] = [] // e.g. action_idName = 3 @@ -726,6 +1067,52 @@ export class KeylayoutToKmnConverter { } return OutputValue } + // get all entries for state= and a given action id + public lookup_6_Action__To__State_Array(data: any, search: any): any[] { + const returnarray: string[] = [] + for (let jj = 0; jj < data.keyboard.actions.action.length; jj++) { + if (data.keyboard.actions.action[jj]['@_id'] === search) { + for (let kk = 0; kk < data.keyboard.actions.action[jj].when.length; kk++) { + if (data.keyboard.actions.action[jj].when[kk]['@_state'] !== "none") { + returnarray.push(data.keyboard.actions.action[jj].when[kk]['@_state']) + } + } + } + } + return returnarray + } + + // get all entries for state= and a given action id + public lookup_6_State__From__Next_Array(data: any, search: any): string[] { + const returnarray: string[] = [] + for (let jj = 0; jj < data.keyboard.actions.action.length; jj++) { + for (let kk = 0; kk < data.keyboard.actions.action[jj].when.length; kk++) { + if ((data.keyboard.actions.action[jj].when[kk]['@_next'] === search) && (data.keyboard.actions.action[jj].when[kk]['@_state'] !== "none")) { + returnarray.push(data.keyboard.actions.action[jj]['@_id']) + } + } + } + return returnarray + } + + public lookup_13_ActionNext__To__AllState(data: any, search: string) { + const returnarray2D: string[][] = [] + for (let ll = 0; ll < data.keyboard.actions.action.length; ll++) { + for (let mm = 0; mm < data.keyboard.actions.action[ll].when.length; mm++) { + const returnarray: string[] = [] + if ((data.keyboard.actions.action[ll].when[mm]['@_state'] === search)) { + returnarray.push(data.keyboard.actions.action[ll]['@_id']) + returnarray.push(data.keyboard.actions.action[ll].when[mm]['@_state']) + returnarray.push(data.keyboard.actions.action[ll].when[mm]['@_output']) + } + if (returnarray.length > 0) + returnarray2D.push(returnarray) + } + } + return returnarray2D + } + + public lookup_9_TerminatorState__To__TerminatorOutput_str(data: any, search: string): string { let OutputValue = "" for (let jj = 0; jj < data.keyboard.terminators.when.length; jj++) { @@ -750,7 +1137,7 @@ export class KeylayoutToKmnConverter { } } } - return 999 + return -1 } public lookup_13_ActionNext__To__ActionID(data: any, search: string) { for (let ll = 0; ll < data.keyboard.actions.action.length; ll++) { @@ -778,6 +1165,90 @@ export class KeylayoutToKmnConverter { } return mapIndexArray_max } + public lookup_14_ActionName__To__MapIndexSingle(data: any, search: string): number { + const mapIndexArray_max: number[][] = [] + for (let kk = 0; kk < data.keyboard.keyMapSet[0].keyMap.length; kk++) { + for (let jj = 0; jj < data.keyboard.keyMapSet[0].keyMap[kk].key.length; jj++) { + const mapIndexArrayperKey: number[] = [] + + if (data.keyboard.keyMapSet[0].keyMap[kk].key[jj]['@_action'] === search) { + mapIndexArrayperKey.push(data.keyboard.keyMapSet[0].keyMap[kk].key[jj]['@_code']) + mapIndexArrayperKey.push(kk) + } + if (mapIndexArrayperKey.length > 0) + mapIndexArray_max.push(mapIndexArrayperKey) + } + } + return mapIndexArray_max[0][1] + } + public lookup_15_KeyMapAction__To__State(data: any, search: string): string { + // todo loop + for (let k = 0; k < data.keyboard.actions.action.length; k++) { + if ((data.keyboard.actions.action[k]['@_id'] === search)) + // for (let l = 0; l < data.keyboard.actions.action[l].length; l++) { + for (let j = 0; j < data.keyboard.actions.action.when.length; j++) { + return "" + //return data.keyboard.actions.action[k].when[j]['@_state'] + } + //} + } + return "" + } + public lookup_15_KeyMapAction__To__Next(data: any, search: string): string { + for (let k = 0; k < data.keyboard.actions.action.length; k++) { + if ((data.keyboard.actions.action[k]['@_id'] === search)) + return data.keyboard.actions.action[k].when[1]['@_next'] + } + return "" + } + + public lookup_15_KeyMapAction__To__KeyMapIndex(data: any, search: string): number { + for (let kk = 0; kk < data.keyboard.keyMapSet[0].keyMap.length; kk++) { + for (let jj = 0; jj < data.keyboard.keyMapSet[0].keyMap[kk].key.length; jj++) { + if (data.keyboard.keyMapSet[0].keyMap[kk].key[jj]['@_action'] === search) { + return data.keyboard.keyMapSet[0].keyMap[kk]['@_index'] + } + } + } + return -1 + } + public lookup_15_KeyMapAction__To__KeyMapIndex_Arr(data: any, search: string, keycode: number): string[][] { + const returnarray2D: string[][] = [] + for (let kk = 0; kk < data.keyboard.keyMapSet[0].keyMap.length; kk++) { + for (let jj = 0; jj < data.keyboard.keyMapSet[0].keyMap[kk].key.length; jj++) { + const returnarray: string[] = [] + if (data.keyboard.keyMapSet[0].keyMap[kk].key[jj]['@_action'] === search) { + returnarray.push(data.keyboard.keyMapSet[0].keyMap[kk]['@_index']) + returnarray.push(data.keyboard.keyMapSet[0].keyMap[kk].key[jj]['@_code']) + returnarray.push(data.keyboard.keyMapSet[0].keyMap[kk].key[jj]['@_action']) + } + if (returnarray.length > 0) { + returnarray2D.push(returnarray) + } + } + } + + return returnarray2D + } + + public lookup_11_KeyMapIndex__To__Modifier(data: any, search: number): string[] { + return data[search] + } + public lookup_11_KeyMapIndex__To__Modifier2(data: any, search: number): string[] { + return data.ArrayOf_Modifiers[search] + //return data[search] + } + + public lookup_17_ActionState__To__ActionOutput(data: any, search: string, nextval: string): string { + for (let k = 0; k < data.keyboard.actions.action.length; k++) { + for (let j = 0; j < data.keyboard.actions.action[k].when.length; j++) { + if ((data.keyboard.actions.action[k].when[j]['@_state'] === search) && (data.keyboard.actions.action[k]['@_id'] === nextval)) { + return data.keyboard.actions.action[k].when[j]['@_output'] + } + } + } + return "" + } /** * @brief member function to return the unicode value of a character @@ -856,16 +1327,7 @@ export class KeylayoutToKmnConverter { } public checkIfCapsUsed(keylayout_modifier: string[][]): boolean { - for (let i = 0; i < keylayout_modifier.length; i++) { - for (let j = 0; j < keylayout_modifier[i].length; j++) { - const modifier_state: string[] = keylayout_modifier[i][j].split(" "); - for (let k = 0; k < modifier_state.length; k++) { - if ((modifier_state[k].indexOf("caps") !== -1) && (modifier_state[k].indexOf("caps?") === -1)) - return true - } - } - } - return false + return keylayout_modifier.flat().flat().includes("caps") } /** @@ -902,7 +1364,7 @@ export class KeylayoutToKmnConverter { if (pos === 0x23) return "K_P" /* P */ if (pos === 0x21) return "K_LBRKT" /* [ */ if (pos === 0x1E) return "K_RBRKT" /* ] */ - if (pos === 0x32) return "K_SPACE" /* \ */ + if (pos === 0x31) return "K_SPACE" /* \ */ if (pos === 0x2A) return "K_BKSLASH" /* \ */ // 42 for ISO correct?? // if (pos === 0x30) return "K_?C1" /* \ */ // 48 for ANSI correct?? // TODO numbers OK?? @@ -957,11 +1419,11 @@ export class KeylayoutToKmnConverter { // remove duplicates const uniqueDeadkeys = uniqueDeadkeys_all.reduce((unique, o) => { - if (!unique.some((obj: { chars: any; type_C: any; modifiers_first: any; key_first: any }) => + if (!unique.some((obj: { chars: any; type_C: any; modifier_key: any; key: any }) => new TextDecoder().decode(obj.chars) === new TextDecoder().decode(o.chars) - && obj.key_first === o.key_first + && obj.key === o.key && obj.type_C === o.type_C - && obj.modifiers_first === o.modifiers_first) + && obj.modifier_key === o.modifier_key) ) { unique.push(o); } @@ -971,7 +1433,7 @@ export class KeylayoutToKmnConverter { for (let kkk = 0; kkk < uniqueDeadkeys.length; kkk++) { let line: string = "" - line = "+ [" + uniqueDeadkeys[kkk].modifiers_first + " " + uniqueDeadkeys[kkk].key_first + "] > dk(" + uniqueDeadkeys[kkk].dk_hex + ")" + line = "+ [" + uniqueDeadkeys[kkk].modifier_key + " " + uniqueDeadkeys[kkk].key + "] > dk(" + uniqueDeadkeys[kkk].dk_hex + ")" data += line + '\n' } @@ -980,22 +1442,22 @@ export class KeylayoutToKmnConverter { There are 6 different types of data entries (C0-C4) in data_ukelele.ArrayOf_processed_RuleData e.g. that contain all data to retrieve deadkeys, deadkeyables and deadkeyed characters: - C0: (size: 4) ['first_modifier_C0', 'RIGHTSHIFT ', 'K_S', 'S' ] - C1: (size: 4) ['first_modifier_C1', 'CAPS', 'K_A', 'A' ], - C2: (size: 5) ['first_modifier_C2', 'CAPS', 'K_A', 'K_N', 'Ã' ], use 2.(K_A) and 4.('Ã') to get name and DEADKEYED - C3: (size: 6) ['first_modifier_C3', 'NCAPS RALT', 'K_8', 'NCAPS RALT', 'K_U', 'ˆ' ], - C4: (size: 4) ['first_modifier_C4', 'NCAPS 0', 'K_SPACE', '' ], - C4: (size: 7) ['first_modifier_C4', 'NCAPS RALT', 'K_N', '˜', 'isTerminator', '˜', '02DC '], use 2.(K_N) , 5. (isTerminator) and 6.('02DC') to get key name and DEADKEY in hex + C0: (size: 4) ['C0', 'RIGHTSHIFT ', 'K_S', 'S' ] + C1: (size: 4) ['C1', 'CAPS', 'K_A', 'A' ], + C2: (size: 5) ['C2', 'CAPS', 'K_A', 'K_N', 'Ã' ], use 2.(K_A) and 4.('Ã') to get name and DEADKEYED + C3: (size: 6) ['C3', 'NCAPS RALT', 'K_8', 'NCAPS RALT', 'K_U', 'ˆ' ], + C4: (size: 4) ['C4', 'NCAPS 0', 'K_SPACE', '' ], + C4: (size: 7) ['C4', 'NCAPS RALT', 'K_N', '˜', 'isTerminator', '˜', '02DC '], use 2.(K_N) , 5. (isTerminator) and 6.('02DC') to get key name and DEADKEY in hex To Find a DEADKEY e.g. ^ 1) look in modifier_C4 with 'isTerminator' included (n = 7) 2) get 7th entry ===> DEADKEY (e.g. 02DC) To Find a DEADKEYABLE ( a character that can be converted to a deadkey e.g. A (-> Ã) ): - 1) first_modifier_C1 CAPS K_A A - 2) first_modifier_C2 CAPS K_A K_N à - - Find C2 rule with 5 entries (Deadkeyed) (e.g. first_modifier_C2 CAPS K_A K_N Ã) - - get C1 rule with same second and third entries -> (e.g. first_modifier_C1 CAPS K_A) + 1) C1 CAPS K_A A + 2) C2 CAPS K_A K_N à + - Find C2 rule with 5 entries (Deadkeyed) (e.g. C2 CAPS K_A K_N Ã) + - get C1 rule with same second and third entries -> (e.g. C1 CAPS K_A) - get 2nd entry of C1 rule ===> DEADKEYABLE (e.g. A) To Find a DEADKEYED ( a character that has been converted from another character e.g. à ): @@ -1005,27 +1467,27 @@ export class KeylayoutToKmnConverter { */ - // select only lines for deadkeyables ( entries that contain C1, are not K_SPACE and create chars e.g. from 'first_modifier_C1', 'CAPS', 'K_A', 'A' ]) + // select only lines for deadkeyables ( entries that contain C1, are not K_SPACE and create chars e.g. from 'C1', 'CAPS', 'K_A', 'A' ]) const deadkeyables_raw = workArray2D.filter((curr) => { - if ((curr.type_C === "first_modifier_C1") && (curr.key_first !== "K_SPACE") && (new TextDecoder().decode(curr.chars) !== "")) { + if ((curr.type_C === "C1") && (curr.key !== "K_SPACE") && (new TextDecoder().decode(curr.chars) !== "")) { return curr; } }); - // select only lines for deadkeyed ( entries that contain C2, are not K_SPACE and create a deadkeyed) e.g. from ['first_modifier_C2', 'CAPS', 'K_A', 'K_N', 'Ã' ] + // select only lines for deadkeyed ( entries that contain C2, are not K_SPACE and create a deadkeyed) e.g. from ['C2', 'CAPS', 'K_A', 'K_N', 'Ã' ] const deadkeyed_raw_multiple = workArray2D.filter((curr) => { - if ((curr.type_C === "first_modifier_C2") && (curr.key_first !== "K_SPACE") && (curr.deadkeyed !== "")) { + if ((curr.type_C === "C2") && (curr.key !== "K_SPACE") && (curr.deadkeyed !== "")) { return curr; } }); // remove duplicate s const deadkeyed_raw = deadkeyed_raw_multiple.reduce((unique, o) => { - if (!unique.some((obj: { chars: any; type_C: any; modifiers_first: any; key_first: any; deadkeyed: any }) => + if (!unique.some((obj: { chars: any; type_C: any; modifier_key: any; key: any; deadkeyed: any }) => new TextDecoder().decode(obj.deadkeyed) === new TextDecoder().decode(o.deadkeyed) - && obj.key_first === o.key_first + && obj.key === o.key && obj.type_C === o.type_C - && obj.modifiers_first === o.modifiers_first) + && obj.modifier_key === o.modifier_key) ) { unique.push(o); } @@ -1040,8 +1502,8 @@ export class KeylayoutToKmnConverter { for (let ss = 0; ss < deadkeyed_raw.length; ss++) { const dk_array: any[] = [] //if available ( if both have the same shiftstate and keyname) - if ((deadkeyables_raw[rr].modifiers_first === deadkeyed_raw[ss].modifiers_first) && - ((deadkeyables_raw[rr].key_first === deadkeyed_raw[ss].key_first))) { + if ((deadkeyables_raw[rr].modifier_key === deadkeyed_raw[ss].modifier_key) && + ((deadkeyables_raw[rr].key === deadkeyed_raw[ss].key))) { dk_array.push(new TextDecoder().decode(deadkeyables_raw[rr].chars)) // deadkeyable e.g. A dk_array.push(deadkeyed_raw[ss].key_second) // Keyname dk e.g. K_N @@ -1070,7 +1532,7 @@ export class KeylayoutToKmnConverter { for (let i = 0; i < uniqueDeadkeys.length; i++) { for (let j = 0; j < unique_dk_array_comlpete[0].length; j++) { - if (uniqueDeadkeys[i].key_first === unique_dk_array_comlpete[0][j][1]) { + if (uniqueDeadkeys[i].key === unique_dk_array_comlpete[0][j][1]) { deadkeyablesElement[i][0] = deadkeyablesElement[i][0] + "\'" + unique_dk_array_comlpete[0][j][0] + "\' " deadkeyedElement[i][0] = deadkeyedElement[i][0] + "\'" + unique_dk_array_comlpete[0][j][2] + "\' " } @@ -1101,18 +1563,18 @@ export class KeylayoutToKmnConverter { // select only lines that contain C0 or C1 and create an output. const uniqueDeadkeys_all = workArray2D.filter((curr) => { if ((curr.chars !== new TextEncoder().encode("") || curr.chars !== undefined) - && (curr.type_C === "first_modifier_C0") || (curr.type_C === "first_modifier_C1")) { + && (curr.type_C === "C0") || (curr.type_C === "C1")) { return curr; } }); // Also remove duplicates const uniqueDeadkeys = uniqueDeadkeys_all.reduce((unique, o) => { - if (!unique.some((obj: { chars: any; type_C: any; modifiers_first: any; key_first: any }) => + if (!unique.some((obj: { chars: any; type_C: any; modifier_key: any; key: any }) => new TextDecoder().decode(obj.chars) === new TextDecoder().decode(o.chars) - && obj.key_first === o.key_first + && obj.key === o.key && obj.type_C === o.type_C - && obj.modifiers_first === o.modifiers_first) + && obj.modifier_key === o.modifier_key) ) { unique.push(o); } @@ -1125,21 +1587,22 @@ export class KeylayoutToKmnConverter { let keyNr = 0; for (let pp = 0; pp < maxkey; pp++) { - if (this.map_UkeleleKC_To_VK(pp) === uniqueDeadkeys[kkk].key_first) + if (this.map_UkeleleKC_To_VK(pp) === uniqueDeadkeys[kkk].key) keyNr = pp } + // todo wrong output: writes 49 with no K_ and 0 with space ???? // skip keyNr 48 ( TAB ) if (keyNr === 48) continue // add a line after rules of each key - if (uniqueDeadkeys[kkk].key_first !== keymarker) + if (uniqueDeadkeys[kkk].key !== keymarker) data += '\n' // write rule - data += keyNr + "-(modif:" + uniqueDeadkeys[kkk].type_C + "-" + "i" + `) + [` + (uniqueDeadkeys[kkk].modifiers_first + ' ' + uniqueDeadkeys[kkk].key_first).trim() + `] > \'` + new TextDecoder().decode(uniqueDeadkeys[kkk].chars) + '\'\n' - keymarker = uniqueDeadkeys[kkk].key_first + data += keyNr + "-(modif:" + uniqueDeadkeys[kkk].type_C + "-" + "i" + `) + [` + (uniqueDeadkeys[kkk].modifier_key + ' ' + uniqueDeadkeys[kkk].key).trim() + `] > \'` + new TextDecoder().decode(uniqueDeadkeys[kkk].chars) + '\'\n' + keymarker = uniqueDeadkeys[kkk].key } data += '\n' @@ -1194,59 +1657,6 @@ export class KeylayoutToKmnConverter { return data } - - /* public removeDuplicates(myArr: any[], type: string | number, modi: string | number, char: string | number) { - return myArr.filter((obj: { [x: string]: any; }, pos: any, arr: any[]) => { - return arr.map((mapObj: { [x: string]: any; }) => ( - (mapObj[type]).indexOf(obj[type]) === pos) - && ((mapObj[modi]).indexOf(obj[modi]) === pos)) - }) - }*/ - // public lookup_2_KeyMapAction__To__ActionAction() { } - //public lookup_4_ActionNext__To__ActionState() { } - //public lookup_7_ActionState__To__ActionOutput() { } - //public lookup_8_ActionNext__To__TerminatorState() { } - /* public lookup_9_TerminatorState__To__TerminatorOutput_ui8(data: any, search: string): Uint8Array { - for (let jj = 0; jj < data.keyboard.terminators.when.length; jj++) { - if (data.keyboard.terminators.when[jj]['@_state'] === search) { - return new TextEncoder().encode(data.keyboard.terminators.when[jj]['@_output']); - } - } - return new TextEncoder().encode("") - }*/ - /*public lookup_11_KeyMapAction__To__KeyIndex(data: any, search: string): number { - for (let kk = 0; kk < data.keyboard.keyMapSet[0].keyMap.length; kk++) { - for (let jj = 0; jj < data.keyboard.keyMapSet[0].keyMap[kk].key.length; jj++) { - if (data.keyboard.keyMapSet[0].keyMap[kk].key[jj]['@_action'] === search) { - return data.keyboard.keyMapSet[0].keyMap[kk]['@_index'] - } - } - } - return 999 - }*/ - // get all entries that result in state 3 - /*public lookup_12_ActionNext__from__ActionState(data: any, search: string): string { - // loop all action - for (let jj = 0; jj < data.keyboard.actions.action.length; jj++) { - // loop all when - for (let kk = 0; kk < data.keyboard.actions.action[jj].when.length; kk++) { - // if next === a´search - if (data.keyboard.actions.action[jj].when[kk]['@_next'] === search) { - // return actionIDName - return data.keyboard.actions.action[jj]['@_id'] - } - } - } - return "" - }*/ - /* - public useAsString(u18ArrayElemnent: Uint8Array[]): string { - let str = "" - for (let i = 0; i < u18ArrayElemnent.length; i++) { - str = str + " " + new TextDecoder().decode(u18ArrayElemnent[i]) - } - return str - }*/ } @@ -1268,6 +1678,26 @@ class Rules { public deadkeys: Uint8Array, public deadkeyables: Uint8Array, public deadkeyed: Uint8Array, + /* ****************************************** */ + + public modifier_prev_deadkey: string, + public prev_deadkey: string, + public prev_deadkeys_Ch: Uint8Array, + public dk_prev: number, + + public modifier_deadkey: string, + public deadkey: string, + public deadkeys_Ch: Uint8Array, + public dk: number, + + public modifier_key: string, + public key: string, + public deadkeyed_Ch: Uint8Array, + + + + + ) { } public getval() { From 958373e310e061ea687880ff68f2c0836986191b Mon Sep 17 00:00:00 2001 From: Sabine Date: Wed, 15 Jan 2025 09:30:25 +0100 Subject: [PATCH 039/251] feat(developer): kmc-convert use object for writing out all rules --- .../test/test-keylayout-to-kmn-converter.ts | 74 +++++++++++-------- 1 file changed, 42 insertions(+), 32 deletions(-) diff --git a/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts index d8c24467ae2..c33c4cc0a59 100644 --- a/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts @@ -7,19 +7,19 @@ cd developer/src/kmc-convert/ import 'mocha'; -import {assert} from 'chai'; -import {compilerTestCallbacks, compilerTestOptions} from './helpers/index.js'; -import {KeylayoutToKmnConverter} from '../src/keylayout-to-kmn/keylayout-to-kmn-converter.js'; +import { assert } from 'chai'; +import { compilerTestCallbacks, compilerTestOptions } from './helpers/index.js'; +import { KeylayoutToKmnConverter } from '../src/keylayout-to-kmn/keylayout-to-kmn-converter.js'; import { makePathToFixture } from './helpers/index.js'; // _S2 my imports -describe('KeylayoutToKmnConverter', function() { +describe('KeylayoutToKmnConverter', function () { - before(function() { - compilerTestCallbacks.clear(); - }); + before(function () { + compilerTestCallbacks.clear(); + }); - // _S2 first test + // _S2 first test /* it('should throw on null inputs', async function () { // const inputFilename = makePathToFixture('file.keylayout'); const converter = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); @@ -34,34 +34,44 @@ describe('KeylayoutToKmnConverter', function() { });*/ - // _S2 My tests... // later throws on NOT all elements loaded - it('should throw on all elements loaded', async function () { + // _S2 My tests... // later throws on NOT all elements loaded + it('should throw on all elements loaded', async function () { - // some keys, no deadkeys - //const inputFilename = makePathToFixture('../data/Mysample.keylayout'); - // all keys, some deadkeys - //const inputFilename = makePathToFixture('../data/US_complete.keylayout'); + // some keys, no deadkeys + //const inputFilename = makePathToFixture('../data/Mysample.keylayout'); - //const inputFilename = makePathToFixture('../data/German_complete.keylayout'); - const inputFilename = makePathToFixture('../data/Italian_copy.keylayout'); - //const inputFilename = makePathToFixture('../data/My_dk_Keyboard.keylayout'); + // all keys, some deadkeys + // copy into C:\Projects\keyman\keyman\developer\src\kmc-convert\test\DATA then they run OK - const outputFilename = makePathToFixture('../data/MyResult.kmn'); - - // TODO check filename if correct - console.log(' inputFilename', inputFilename) - console.log(' outputFilename', outputFilename) + //const inputFilename = makePathToFixture('../data/US_complete.keylayout'); // OK + //const inputFilename = makePathToFixture('../data/German_complete.keylayout'); // OK + const inputFilename = makePathToFixture('../data/Italian_copy.keylayout'); // OK + //const inputFilename = makePathToFixture('../data/German_Standard_copy.keylayout'); //OK + //const inputFilename = makePathToFixture('../data/German_Standard2.keylayout'); //OK + //const inputFilename = makePathToFixture('../data/German_StandardTweaked.keylayout'); //NO C3 + //const inputFilename = makePathToFixture('../data/Spanish_copy.keylayout'); // OK + //const inputFilename = makePathToFixture('../data/Latin_American_copy.keylayout'); // OK + //const inputFilename = makePathToFixture('../data/My_dk_Keyboard.keylayout'); // No + //const inputFilename = makePathToFixture('../data/Swiss_French_copy.keylayout'); // OK + //const inputFilename = makePathToFixture('../data/Swiss_German_copy.keylayout'); // OK + //const inputFilename = makePathToFixture('../data/US_copy.keylayout'); // OK - // _S2 create obj of derived class-> use derived functions - const converter = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const outputFilename = makePathToFixture('../data/MyResult.kmn'); - let threw = false; - try { - await converter.run(inputFilename, outputFilename); - } catch { - threw = true; - } - assert.isTrue(threw); - }); + // TODO check filename if correct + console.log(' inputFilename', inputFilename) + console.log(' outputFilename', outputFilename) + // _S2 create obj of derived class-> use derived functions + const converter = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + + let threw = false; + try { + await converter.run(inputFilename, outputFilename); + } catch { + threw = true; + } + assert.isTrue(threw); }); + +}); From 29d0810710d4fb24ba37cc43323c1c1395d6c27f Mon Sep 17 00:00:00 2001 From: Sabine Date: Wed, 15 Jan 2025 09:33:22 +0100 Subject: [PATCH 040/251] feat(developer): kmc-convert print C0, C1, C2, C4 OK --- .../keylayout-to-kmn-converter.ts | 267 +++++++++++++----- 1 file changed, 194 insertions(+), 73 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 4d0eec971ac..329f99fa108 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -148,16 +148,17 @@ export interface rule_object { prev_deadkey: string, modifier_prev_deadkey: string, prev_deadkeys_Ch: Uint8Array, + dk_prev: number, deadkey: string, modifier_deadkey: string, deadkeys_Ch: Uint8Array, + dk: number, key: string, modifier_key: string, deadkeyed_Ch: Uint8Array, - }; export interface convert_object { @@ -288,7 +289,6 @@ export class KeylayoutToKmnConverter { //TODO need to use export const USVirtualKeyCodes here public write(data_ukelele: convert_object): boolean { console.log("\n###################################################\n") - let data = "\n" data += this.create_KMN_Data(data_ukelele) data += "\n" @@ -655,11 +655,11 @@ export class KeylayoutToKmnConverter { let value_state let value_next - let ContextKeyNr_deadkey - let ContextKeyNr_deadkey1 - let keymapIndexForactionID_2: any[][] + let Key_Block4 + let KeyCode_Block2 + let codeIndexPair_Block4: any[][] //let keymapIndexForactionID - let modifier: string[] + let modifier_Block4_fixed: string[] // get a9 in behavior/key action_id = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] @@ -675,64 +675,71 @@ export class KeylayoutToKmnConverter { // Data of Block Nr 5 .......................................................... /* 5: state =3 */ value_state = jsonObj.keyboard.actions.action[actionIdIndex].when[l]['@_state'] /* 5: next =1 */ value_next = jsonObj.keyboard.actions.action[actionIdIndex].when[l]['@_next'] - /* 5: actioniD = a16 */ const theContextID = jsonObj.keyboard.actions.action[actionIdIndex]['@_id'] // get actionId of that state/next pair (14,20) e.g. actionId a57 //my a16 NNNRRR 5 + /* 5: StateNextID = a16 */ const StateNextID_Block5 = jsonObj.keyboard.actions.action[actionIdIndex]['@_id'] // get actionId of that state/next pair (14,20) e.g. actionId a57 //my a16 NNNRRR 5 // ........................................................................ // Data of Block Nr 4 .......................................................... - /* 4: code = 32 */ ContextKeyNr_deadkey = this.lookup_11_KeyMapAction__To__KeyMapCode(jsonObj, theContextID) // find keyNr of that actionID a57> code=37 // my 32 ( K_U) + /* 4: code = 32 */ Key_Block4 = this.lookup_11_KeyMapAction__To__KeyMapCode(jsonObj, StateNextID_Block5) // find keyNr of that actionID a57> code=37 // my 32 ( K_U) /* 4: K_U */ //first_key_C3_U8_deadkey = new TextEncoder().encode(this.map_UkeleleKC_To_VK(Number(ContextKeyNr_deadkey))) - /* 4: MapIndexArr=[32 3] */ keymapIndexForactionID_2 = this.lookup_14_ActionName__To__MapIndex(jsonObj, String(theContextID)) + /* 4: codeIndexPair=[32 3] */ codeIndexPair_Block4 = this.lookup_14_ActionName__To__MapIndex(jsonObj, String(StateNextID_Block5)) /* 4: MapIndex 3 */ //keymapIndexForactionID = this.lookup_14_ActionName__To__MapIndexSingle(jsonObj, String(theContextID)) - /* [32 3] */ modifier = this.lookup_11_KeyMapIndex__To__Modifier(data_ukelele.ArrayOf_Modifiers, 1) + /* [32 3] FIX Arr[1] */ modifier_Block4_fixed = this.lookup_11_KeyMapIndex__To__Modifier(data_ukelele.ArrayOf_Modifiers, 1) // !! FIXED VALUE HERE!!!! needs to be loop // ........................................................................ + console.log("modifier_Block4_fixed ", modifier_Block4_fixed) + // Data of Block Nr 3 .......................................................... //must be array ??? - /* 3: actioniD = a17 */ const ActionId_prev_dk = this.lookup_5_ActionState__To__ActionNext_str(jsonObj, value_state) + /* 3: actioniD = a17 */ const NoneNextId_Block3 = this.lookup_5_ActionState__To__ActionNext_str(jsonObj, value_state) // ........................................................................ // Data of Block Nr 2 .......................................................... - /* 2: code = 28 */ ContextKeyNr_deadkey1 = this.lookup_11_KeyMapAction__To__KeyMapCode(jsonObj, ActionId_prev_dk) - /* 2: K_8 */ const prev_deadkey = this.map_UkeleleKC_To_VK(Number(ContextKeyNr_deadkey1)) - /* 2 index=3 */ const modificator = this.lookup_14_ActionName__To__MapIndex(jsonObj, String(ActionId_prev_dk)) - /* 2 CAPS*/ const modiInText = this.lookup_11_KeyMapIndex__To__Modifier(data_ukelele.ArrayOf_Modifiers, modificator[0][1]) + /* 2: code = 28 */ KeyCode_Block2 = this.lookup_11_KeyMapAction__To__KeyMapCode(jsonObj, NoneNextId_Block3) + /* 2: K_8 */ const KeyName_Block2 = this.map_UkeleleKC_To_VK(Number(KeyCode_Block2)) + /* 2 index=3 */ const modifier_Block2 = this.lookup_14_ActionName__To__MapIndex(jsonObj, String(NoneNextId_Block3)) + /* 2 RALT */ const ModifierElementBlock2 = this.lookup_11_KeyMapIndex__To__Modifier(data_ukelele.ArrayOf_Modifiers, modifier_Block2[0][1]) // ........................................................................ // Data of Block Nr 6 .......................................................... - /* 6: [ 'a9', '1', 'â' ] */ const stateArray = this.lookup_13_ActionNext__To__AllState(jsonObj, value_next) - /* 6: output = â */ const output_all = this.lookup_17_ActionState__To__ActionOutput(jsonObj, value_next, stateArray[0][0]) + /* 6: [ 'a9', '1', 'â' ] */ const state_Block6_all = this.lookup_13_ActionNext__To__AllState(jsonObj, value_next) + /* 6: output = â FIX */ const output_Block6_fixed = this.lookup_17_ActionState__To__ActionOutput(jsonObj, value_next, state_Block6_all[1][0]) // ........................................................................ - for (let a = 0; a < stateArray.length; a++) { + for (let a = 0; a < state_Block6_all.length; a++) { // Data of Block Nr 1 .......................................................... // todo get all state1´s - /* 2: code = 0 */ const keycode = this.lookup_11_KeyMapAction__To__KeyMapCode(jsonObj, stateArray[a][0]) - /* 2: K_A */ const keyname = this.map_UkeleleKC_To_VK(Number(keycode)) + /* 2: code = 0 */ const keycode_Block1 = this.lookup_11_KeyMapAction__To__KeyMapCode(jsonObj, state_Block6_all[a][0]) + /* 2: K_A */ const keyname_Block1 = this.map_UkeleleKC_To_VK(Number(keycode_Block1)) // ........................................................................ - // a16 hasstate + // a16 has state // field 1: which code has action a0 or a9 or... - const modif = this.lookup_15_KeyMapAction__To__KeyMapIndex_Arr(jsonObj, stateArray[a][0], keycode) + const modif = this.lookup_15_KeyMapAction__To__KeyMapIndex_Arr(jsonObj, state_Block6_all[a][0], keycode_Block1) //console.log("modif ", modif) for (let jj = 0; jj < modif.length; jj++) { - for (let kk = 0; kk < modiInText.length; kk++) { + for (let kk = 0; kk < ModifierElementBlock2.length; kk++) { const modifierText = this.lookup_11_KeyMapIndex__To__Modifier(data_ukelele.ArrayOf_Modifiers, Number(modif[jj][0])) const modiflat = modifierText.flat() const modi = this.create_kmn_modifier(modiflat[0], isCapsused) + console.log("modifierText : array of all modifiers", modifierText) + console.log("modiflat ", modiflat) + console.log("modi only the first mod !!! HERE!!", modi) + console.log(" modifier ", modifier_Block4_fixed) + RuleObj = new Rules( "CX", modi, - keyname, + keyname_Block1, //this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[i][l], isCapsused), "modifier", - this.map_UkeleleKC_To_VK(Number(ContextKeyNr_deadkey)), + this.map_UkeleleKC_To_VK(Number(Key_Block4)), new TextEncoder().encode(""), false, @@ -741,21 +748,21 @@ export class KeylayoutToKmnConverter { new TextEncoder().encode(""), new TextEncoder().encode(""), new TextEncoder().encode(""), -/* ****************************************** */ + /* ****************************************** */ - this.create_kmn_modifier(modiInText[kk],isCapsused), - prev_deadkey, + this.create_kmn_modifier(ModifierElementBlock2[kk], isCapsused), + KeyName_Block2, new TextEncoder().encode(""), dk_counter++, - this.create_kmn_modifier( modifier[0],isCapsused), - this.map_UkeleleKC_To_VK(Number(ContextKeyNr_deadkey)), + this.create_kmn_modifier(modifier_Block4_fixed[0], isCapsused), + this.map_UkeleleKC_To_VK(Number(Key_Block4)), new TextEncoder().encode(""), dk_counter++, modi, - keyname, - new TextEncoder().encode(output_all), + keyname_Block1, + new TextEncoder().encode(output_Block6_fixed), ) ObjectArray.push(RuleObj) console.log("qqqqq C3 RuleObj", RuleObj) @@ -769,14 +776,14 @@ export class KeylayoutToKmnConverter { for (let l = 0; l < data_ukelele.ArrayOf_Modifiers[i].length; l++) { - if (ContextKeyNr_deadkey !== undefined) { + if (Key_Block4 !== undefined) { - for (let kk = 0; kk < data_ukelele.ArrayOf_Modifiers[keymapIndexForactionID_2[0][1]].length; kk++) { + for (let kk = 0; kk < data_ukelele.ArrayOf_Modifiers[codeIndexPair_Block4[0][1]].length; kk++) { //console.log("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ") - for (let jj = 0; jj < modifier.length; jj++) { + for (let jj = 0; jj < modifier_Block4_fixed.length; jj++) { - const first_modifier_text_C3_U8_deadkey = data_ukelele.ArrayOf_Modifiers[keymapIndexForactionID_2[0][1]][kk] + const first_modifier_text_C3_U8_deadkey = data_ukelele.ArrayOf_Modifiers[codeIndexPair_Block4[0][1]][kk] if (this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])) !== "") { console.log("(this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])) ", @@ -793,8 +800,8 @@ export class KeylayoutToKmnConverter { this.create_kmn_modifier(first_modifier_text_C3_U8_deadkey, isCapsused), this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), - modifier[jj], - this.map_UkeleleKC_To_VK(Number(ContextKeyNr_deadkey)), + modifier_Block4_fixed[jj], + this.map_UkeleleKC_To_VK(Number(Key_Block4)), result_C3_U8, false, @@ -804,8 +811,8 @@ export class KeylayoutToKmnConverter { new TextEncoder().encode(""), new TextEncoder().encode(""), - this.create_kmn_modifier(modifier[jj], isCapsused), - this.map_UkeleleKC_To_VK(Number(ContextKeyNr_deadkey)), + this.create_kmn_modifier(modifier_Block4_fixed[jj], isCapsused), + this.map_UkeleleKC_To_VK(Number(Key_Block4)), new TextEncoder().encode(""), 0, @@ -814,8 +821,8 @@ export class KeylayoutToKmnConverter { new TextEncoder().encode(""), 0, - this.create_kmn_modifier(modifier[jj], isCapsused), - this.map_UkeleleKC_To_VK(Number(ContextKeyNr_deadkey)), + this.create_kmn_modifier(modifier_Block4_fixed[jj], isCapsused), + this.map_UkeleleKC_To_VK(Number(Key_Block4)), result_C3_U8 ) ObjectArray.push(RuleObj) @@ -907,30 +914,38 @@ export class KeylayoutToKmnConverter { //--------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------- - +let old_counter=0 console.log("start check ", ObjectArray.length) +console.log("ObjectArray ",ObjectArray.length ) for (let k = 0; k < ObjectArray.length; k++) { -//"ObjectArray: k - console.log("Obj: k ", k, - "\tType: ", (ObjectArray[k].type_C !== "" ? ObjectArray[k].type_C : "--".padEnd(4, " ")), - - "| modi_prev_dk: ", (ObjectArray[k].modifier_prev_deadkey !== "" ? ObjectArray[k].modifier_prev_deadkey.padEnd(23, " ") : "--".padEnd(23, " ")), - "key_prev_dk: ", (ObjectArray[k].prev_deadkey !== "" ? ObjectArray[k].prev_deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), - // "ch_prev_dk: ", (new TextDecoder().decode(ObjectArray[k].prev_deadkeys_Ch) !== "" ? new TextDecoder().decode(ObjectArray[k].prev_deadkeys_Ch).padEnd(10, " ") : "--".padEnd(10, " ")), - "is_prev dk(): ", (ObjectArray[k].dk_prev !== 0 ? ("dk_p(" +String(ObjectArray[k].dk_prev)+")").padEnd(11, " ") : "--".padEnd(11, " ")), - - "| modi_dk: ", (ObjectArray[k].modifier_deadkey !== "" ? ObjectArray[k].modifier_deadkey.padEnd(23, " ") : "--".padEnd(23, " ")), - "key_dk: ", (ObjectArray[k].deadkey !== "" ? ObjectArray[k].deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), - // "ch_dk: ", (new TextDecoder().decode(ObjectArray[k].deadkeys_Ch) !== "" ? new TextDecoder().decode(ObjectArray[k].deadkeys_Ch).padEnd(10, " ") : "--".padEnd(10, " ")), - "is dk(): ", (ObjectArray[k].dk !== 0 ? ("dk(" +String(ObjectArray[k].dk)+")").padEnd(9, " ") : "--".padEnd(9, " ")), - - "| modi: ", (ObjectArray[k].modifier_key !== "" ? ObjectArray[k].modifier_key.padEnd(20, " ") : "--".padEnd(20, " ")), - "key: ", (ObjectArray[k].key !== "" ? ObjectArray[k].key.padEnd(8, " ") : "--".padEnd(8, " ")), - "ch: ", (new TextDecoder().decode(ObjectArray[k].deadkeyed_Ch) !== "" ? new TextDecoder().decode(ObjectArray[k].deadkeyed_Ch).padEnd(10, " ") : "--".padEnd(10, " ")), - "| °°" - ) + + if (/*(ObjectArray[k].type_C === "C3")||*/(ObjectArray[k].type_C === "C2")) { +old_counter++ + console.log("Obj: k ", k, + "\tType: ", (ObjectArray[k].type_C !== "" ? ObjectArray[k].type_C : "--".padEnd(4, " ")), + + /* previous dk*/ + "| modi_prev_dk: ", (ObjectArray[k].modifier_prev_deadkey !== "" ? ObjectArray[k].modifier_prev_deadkey.padEnd(23, " ") : "--".padEnd(23, " ")), + "key_prev_dk: ", (ObjectArray[k].prev_deadkey !== "" ? ObjectArray[k].prev_deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), + "is_prev dk(): ", (ObjectArray[k].dk_prev !== 0 ? ("dk_p(" + String(ObjectArray[k].dk_prev) + ")").padEnd(11, " ") : "--".padEnd(11, " ")), + + /* dk*/ + "| modi_dk: ", (ObjectArray[k].modifier_deadkey !== "" ? ObjectArray[k].modifier_deadkey.padEnd(23, " ") : "--".padEnd(23, " ")), + "key_dk: ", (ObjectArray[k].deadkey !== "" ? ObjectArray[k].deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), + "is dk(): ", (ObjectArray[k].dk !== 0 ? ("dk(" + String(ObjectArray[k].dk) + ")").padEnd(9, " ") : "--".padEnd(9, " ")), + + /* key*/ + "| modi: ", (ObjectArray[k].modifier_key !== "" ? ObjectArray[k].modifier_key.padEnd(20, " ") : "--".padEnd(20, " ")), + "key: ", (ObjectArray[k].key !== "" ? ObjectArray[k].key.padEnd(8, " ") : "--".padEnd(8, " ")), + "ch: ", (new TextDecoder().decode(ObjectArray[k].deadkeyed_Ch) !== "" ? new TextDecoder().decode(ObjectArray[k].deadkeyed_Ch).padEnd(10, " ") : "--".padEnd(10, " ")), + + "| °°" + ) + } } + console.log("old_counter ",old_counter ) + //remove entries that are available in both arrays for (let i = 0; i < (testArray_Ukelele.length); i++) { @@ -1430,10 +1445,30 @@ export class KeylayoutToKmnConverter { return unique; }, []); + const uniqueDeadkeys_all_obj = data_ukelele.ArrayOf_Rules.filter((curr) => { + if (curr.isTerminator === true) { + return curr; + } + return "" + }); - for (let kkk = 0; kkk < uniqueDeadkeys.length; kkk++) { + // remove duplicates + const uniqueDeadkeys_obj = uniqueDeadkeys_all_obj.reduce((unique, o) => { + if (!unique.some((obj: { chars: any; type_C: any; modifier_key: any; key: any }) => + new TextDecoder().decode(obj.chars) === new TextDecoder().decode(o.chars) + && obj.key === o.key + && obj.type_C === o.type_C + && obj.modifier_key === o.modifier_key) + ) { + unique.push(o); + } + return unique; + }, []); + + for (let kkk = 0; kkk < uniqueDeadkeys_obj.length; kkk++) { let line: string = "" - line = "+ [" + uniqueDeadkeys[kkk].modifier_key + " " + uniqueDeadkeys[kkk].key + "] > dk(" + uniqueDeadkeys[kkk].dk_hex + ")" + // line = "+ [" + uniqueDeadkeys[kkk].modifier_key + " " + uniqueDeadkeys[kkk].key + "] > dk(" + uniqueDeadkeys[kkk].dk_hex + ")" + line = "+ [" + uniqueDeadkeys_obj[kkk].modifier_key + " " + uniqueDeadkeys_obj[kkk].key + "] > dxk(" + uniqueDeadkeys_obj[kkk].dk_hex + ")" data += line + '\n' } @@ -1468,7 +1503,7 @@ export class KeylayoutToKmnConverter { // select only lines for deadkeyables ( entries that contain C1, are not K_SPACE and create chars e.g. from 'C1', 'CAPS', 'K_A', 'A' ]) - const deadkeyables_raw = workArray2D.filter((curr) => { + /* const deadkeyables_raw = workArray2D.filter((curr) => { if ((curr.type_C === "C1") && (curr.key !== "K_SPACE") && (new TextDecoder().decode(curr.chars) !== "")) { return curr; } @@ -1479,6 +1514,23 @@ export class KeylayoutToKmnConverter { if ((curr.type_C === "C2") && (curr.key !== "K_SPACE") && (curr.deadkeyed !== "")) { return curr; } + });*/ + + // select only lines for deadkeyables ( entries that contain C1, are not K_SPACE and create chars e.g. from 'C1', 'CAPS', 'K_A', 'A' ]) + const deadkeyables_raw = data_ukelele.ArrayOf_Rules.filter((curr) => { + if ((curr.type_C === "C1") && (curr.key !== "K_SPACE") && (new TextDecoder().decode(curr.chars) !== "")) { + return curr; + } + return "" + }); + + // select only lines for deadkeyed ( entries that contain C2, are not K_SPACE and create a deadkeyed) e.g. from ['C2', 'CAPS', 'K_A', 'K_N', 'Ã' ] + const deadkeyed_raw_multiple = data_ukelele.ArrayOf_Rules.filter((curr) => { + // if ((curr.type_C === "C2") && (curr.key !== "K_SPACE") && (curr.deadkeyed_Ch !== "")) { + if ((curr.type_C === "C2") && (curr.key !== "K_SPACE") ) { + return curr; + } + return "" }); // remove duplicate s @@ -1548,8 +1600,8 @@ export class KeylayoutToKmnConverter { for (let i = 0; i < deadkeyablesElement.length; i++) { data += "\n\ndk: " + deadkeyedElement[i][1] - data += "\ndeadkeyablesArray" + deadkeyablesElement[i][0] - data += "\ndeadkeyedArray " + deadkeyedElement[i][0] + data += "\ndeadkeyablesArray xx" + deadkeyablesElement[i][0] + data += "\ndeadkeyedArray xx " + deadkeyedElement[i][0] } return data } @@ -1559,6 +1611,51 @@ export class KeylayoutToKmnConverter { let data: string = "" let keymarker = "" +console.log("data_ukelele.ArrayOf_Rules ", data_ukelele.ArrayOf_Rules.length,data_ukelele.ArrayOf_Rules[155].key) + + // can I use dataUkeklele /ruledata to get uniqueDeadkeys_all + // select only lines that contain C0 or C1 and create an output. +/* + const uniqueDeadkeys_New = data_ukelele.ArrayOf_Rules.reduce((unique, o) => { + if (!unique.some((obj: { chars: any; type_C: any; modifier_key: any; key: any }) => + new TextDecoder().decode(obj.chars) === new TextDecoder().decode(o.chars) + && obj.key === o.key + && obj.type_C === o.type_C + && obj.modifier_key === o.modifier_key) + ) { + unique.push(o); + } + return unique; + }, []); +let unique_counter=0 + console.log("uniqueDeadkeys_New ",uniqueDeadkeys_New.length ) +console.log("uniqueDeadkeys_New ",uniqueDeadkeys_New.length ,uniqueDeadkeys_New) +for (let k = 0; k < uniqueDeadkeys_New.length; k++) { + + if ((ObjectArray[k].type_C === "C3")||(uniqueDeadkeys_New[k].type_C === "C2")) { + unique_counter++ +console.log("uniqueDeadkeys_New: k ", k, + "\tType: ", (uniqueDeadkeys_New[k].type_C !== "" ? uniqueDeadkeys_New[k].type_C : "--".padEnd(4, " ")), + + "| modi_prev_dk: ", (uniqueDeadkeys_New[k].modifier_prev_deadkey !== "" ? uniqueDeadkeys_New[k].modifier_prev_deadkey.padEnd(23, " ") : "--".padEnd(23, " ")), + "key_prev_dk: ", (uniqueDeadkeys_New[k].prev_deadkey !== "" ? uniqueDeadkeys_New[k].prev_deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), + "is_prev dk(): ", (uniqueDeadkeys_New[k].dk_prev !== 0 ? ("dk_p(" + String(uniqueDeadkeys_New[k].dk_prev) + ")").padEnd(11, " ") : "--".padEnd(11, " ")), + + "| modi_dk: ", (uniqueDeadkeys_New[k].modifier_deadkey !== "" ? uniqueDeadkeys_New[k].modifier_deadkey.padEnd(23, " ") : "--".padEnd(23, " ")), + "key_dk: ", (uniqueDeadkeys_New[k].deadkey !== "" ? uniqueDeadkeys_New[k].deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), + "is dk(): ", (uniqueDeadkeys_New[k].dk !== 0 ? ("dk(" + String(uniqueDeadkeys_New[k].dk) + ")").padEnd(9, " ") : "--".padEnd(9, " ")), + + "| modi: ", (uniqueDeadkeys_New[k].modifier_key !== "" ? uniqueDeadkeys_New[k].modifier_key.padEnd(20, " ") : "--".padEnd(20, " ")), + "key: ", (uniqueDeadkeys_New[k].key !== "" ? uniqueDeadkeys_New[k].key.padEnd(8, " ") : "--".padEnd(8, " ")), + "ch: ", (new TextDecoder().decode(uniqueDeadkeys_New[k].deadkeyed_Ch) !== "" ? new TextDecoder().decode(uniqueDeadkeys_New[k].deadkeyed_Ch).padEnd(10, " ") : "--".padEnd(10, " ")), + + "| °°" +) + + }} +console.log("unique_counter ",unique_counter ) + +*/ // can I use dataUkeklele /ruledata to get uniqueDeadkeys_all // select only lines that contain C0 or C1 and create an output. const uniqueDeadkeys_all = workArray2D.filter((curr) => { @@ -1581,6 +1678,29 @@ export class KeylayoutToKmnConverter { return unique; }, []); + const uniqueDeadkeys_all_obj = data_ukelele.ArrayOf_Rules.filter((curr) => { + if ((curr.chars !== new TextEncoder().encode("") || curr.chars !== undefined) + && (curr.type_C === "C0") || (curr.type_C === "C1")) { + return curr; + } + else return "" + }); + + // Also remove duplicates + const uniqueDeadkeys_obj = uniqueDeadkeys_all_obj.reduce((unique, o) => { + if (!unique.some((obj: { chars: any; type_C: any; modifier_key: any; key: any }) => + new TextDecoder().decode(obj.chars) === new TextDecoder().decode(o.chars) + && obj.key === o.key + && obj.type_C === o.type_C + && obj.modifier_key === o.modifier_key) + ) { + unique.push(o); + } + return unique; + }, []); + +console.log("uniqueDeadkeys_obj ", uniqueDeadkeys_obj) + for (let kkk = 0; kkk < uniqueDeadkeys.length; kkk++) { // lookup key nr of the key that is being processed @@ -1601,7 +1721,10 @@ export class KeylayoutToKmnConverter { data += '\n' // write rule - data += keyNr + "-(modif:" + uniqueDeadkeys[kkk].type_C + "-" + "i" + `) + [` + (uniqueDeadkeys[kkk].modifier_key + ' ' + uniqueDeadkeys[kkk].key).trim() + `] > \'` + new TextDecoder().decode(uniqueDeadkeys[kkk].chars) + '\'\n' + + //data += keyNr + "-(modif:" + uniqueDeadkeys[kkk].type_C + "-" + "i" + `) + [` + (uniqueDeadkeys[kkk].modifier_key + ' ' + uniqueDeadkeys[kkk].key).trim() + `] > \'` + new TextDecoder().decode(uniqueDeadkeys[kkk].chars) + '\'\n' + + data += keyNr + "-(modif:"+uniqueDeadkeys_obj[kkk].type_C + "-" + "i" + `) + [` + (uniqueDeadkeys_obj[kkk].modifier_key + ' ' + uniqueDeadkeys_obj[kkk].key).trim() + `] > \'` + new TextDecoder().decode(uniqueDeadkeys_obj[kkk].chars) + '\'\n' keymarker = uniqueDeadkeys[kkk].key } @@ -1694,13 +1817,11 @@ class Rules { public key: string, public deadkeyed_Ch: Uint8Array, - - - - ) { } +/* + public get_key() { return this.key } public getval() { return `blabla ${this.isTerminator} blub: ${this.type_C}...` - } + }9*/ } From 95a951e4e77537c33a39bd472d111e24f1ffed09 Mon Sep 17 00:00:00 2001 From: Sabine Date: Wed, 15 Jan 2025 19:12:37 +0100 Subject: [PATCH 041/251] feat(developer): remove RuleObject elements --- .../keylayout-to-kmn-converter.ts | 992 ++++++------------ 1 file changed, 343 insertions(+), 649 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 329f99fa108..1349336a6dd 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -142,7 +142,6 @@ export interface rule_object { deadkeyables: Uint8Array, /* characters that can use a deadkey (e.g. a,e,i,o,u )*/ deadkeyed: Uint8Array, // deadkeys+deadkeyables (e.g. â,ê,î,ô,û) - /* ****************************************** */ prev_deadkey: string, @@ -158,7 +157,6 @@ export interface rule_object { key: string, modifier_key: string, deadkeyed_Ch: Uint8Array, - }; export interface convert_object { @@ -290,7 +288,16 @@ export class KeylayoutToKmnConverter { public write(data_ukelele: convert_object): boolean { console.log("\n###################################################\n") let data = "\n" - data += this.create_KMN_Data(data_ukelele) + + // add top part of kmn file: STORES + data += this.createData_Stores(data_ukelele) + + // add middle part of kmn file: RULES + data += this.createData_Rules(data_ukelele) + + // add bottom part of kmn file: DEADKEYS + data += this.createData_Deadkeys(data_ukelele) + data += "\n" /*writeFileSync("data/MyResult.kmn", data, { flag: "w" })*/ @@ -301,8 +308,6 @@ export class KeylayoutToKmnConverter { return true; else return false - - data += '\n' } // TODO move outside of class? @@ -313,7 +318,7 @@ export class KeylayoutToKmnConverter { const ObjectArray: any[] = [] let dk_counter = 0 - // start Tests v ToDo remove + // start Tests v ToDo remove...................................... const testArray_Ukelele: string[] = [] let testArray_Ukelele_count = 0 const testArray_Ukelele_action: string[] = [] @@ -346,7 +351,7 @@ export class KeylayoutToKmnConverter { } } } - // End Tests ToDo remove ^ + // End Tests ToDo remove ^....................................... let action_id @@ -362,114 +367,66 @@ export class KeylayoutToKmnConverter { // ...................................................................................................... // case C0: output ...................................................................................... - /*// a key is mapped to a character directly ( code-> output) ............................................. + // a key is mapped to a character directly ( code-> output) ............................................. // ...............e. g. ...................................................... // ...................................................................................................... - // in keys at top for code 1 (K_S) take output ("s") [italian copy] - // get modifiers [modifer of Keymap index 0] - // write [modifer-of-Keymap-index-0 K_S] > s - - [ key code="1" -> output="s" ] - - - - */ - // ...................................................................................................... + let RuleObj - let out_ch = "" - // if this is an output tag + if ((jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] !== undefined)) { testArray_kmn.push(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output']) testArray_kmn_count++ - if (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] !== "") - out_ch = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] + if (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] !== "") { - // loop modifier combinations - for (let l = 0; l < data_ukelele.ArrayOf_Modifiers[i].length; l++) { - if (this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']))) { - RuleObj = new Rules( - "C0", - this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[i][l], isCapsused), - this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), - "", - "", - new TextEncoder().encode(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output']), - false, - "", - new TextEncoder().encode(""), - new TextEncoder().encode(""), - new TextEncoder().encode(""), - new TextEncoder().encode(""), - - "", - "", - new TextEncoder().encode(""), - 0, - - "", - "", - new TextEncoder().encode(""), - 0, - - this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[i][l], isCapsused), - this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), - new TextEncoder().encode(out_ch), - ) - ObjectArray.push(RuleObj) + // loop modifier combinations + for (let l = 0; l < data_ukelele.ArrayOf_Modifiers[i].length; l++) { + if (this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']))) { + + RuleObj = new Rules( + "C0", + false, + + "", + "", + new TextEncoder().encode(""), + 0, + + "", + "", + new TextEncoder().encode(""), + 0, + + this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[i][l], isCapsused), + this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), + new TextEncoder().encode(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output']), + ) + ObjectArray.push(RuleObj) + //console.log("RuleObj shtj ",new TextDecoder().decode(RuleObj.deadkeyed_Ch)=== new TextDecoder().decode(RuleObj.deadkeyed_Ch),l, RuleObj.deadkeyed_Ch, RuleObj.deadkeyed_Ch ) + } } } } - // if this is an action tag + else if (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] !== undefined) { // ...................................................................................................... // case C1: action + state none + output ................................................................ // a key is mapped to an action and then to an output ................................................... - // code->action->action(none)->action(output) ........................................................... + // KeyMap:code->KeyMap:action->action:action_state(none)->action_output ................................. // ...............e. g. a - /* - - /* [key code="0" -> action="a9" -> action id="a9" -> state="none" -> output="a" ] - - - - ... - - - - */ - // ...................................................................................................... action_id = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] // loop modifiers for (let l = 0; l < data_ukelele.ArrayOf_Modifiers[i].length; l++) { - const none_output = this.lookup_6_ActionNone__To__ActionOutput(jsonObj, action_id) + if (this.get_Action2ID_NoneOutput__From__ActionID_Id(jsonObj, action_id) !== undefined) { - if (none_output !== undefined) { RuleObj = new Rules( "C1", - this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[i][l], isCapsused), - this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), - "", - "", - new TextEncoder().encode(none_output), false, - "", - new TextEncoder().encode(""), - new TextEncoder().encode(""), - new TextEncoder().encode(""), - new TextEncoder().encode(""), - /* ****************************************** */ "", "", new TextEncoder().encode(""), @@ -482,7 +439,7 @@ export class KeylayoutToKmnConverter { this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[i][l], isCapsused), this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), - new TextEncoder().encode(none_output) + new TextEncoder().encode(this.get_Action2ID_NoneOutput__From__ActionID_Id(jsonObj, action_id)) ) ObjectArray.push(RuleObj) } @@ -491,44 +448,16 @@ export class KeylayoutToKmnConverter { // case C2: action + state Nr + output .................................................................. // a key is mapped to an action, then to an state+output ................................................ // replace state x with all rules that result in x (action->action(none) + state-> output) ......................................................... + // Action:actionId -> KeyMap:action -> KeyMap:Code -> KeyName............................................ + // Action:next -> Action:state -> action:output ......................................................... // ...............e. g. .................................................... // ...................................................................................................... - // in keys at top for code 0 (K_A) take actions id (a9) [italian copy] - // get modifiers [modifer of Keymap index 0] - // loop all actions and look for next="2" (state="none" => next="2") (=>action id = a8) - // get action id of this row (id = a8) - // look for a8 in keymap-keys action at the top - // take code = 25 and map keycode to VK (VK= K_9) - // get second modifiers [modifer of Keymap index 3] (=anyOption) - // [modifer of Keymap index 3] + K_A + K_9 > à - // write: [modifer-of-Keymap-index-0 K_A] > dk(dk1) ; dk(dk1) + [second modifiers K_9] > à - - /* [ key code="0" -> action="a9" -> action id="a9" -> state="1" -> output="â ] - - - - - - - - [state="1" ≙ next="1" <- state="none" <- action id="a18 <- key code="24" <- keyMap index="3"] - - - - - - - - */ - // ...................................................................................................... - let result_C2: string let nextVal: string[] = [] // find the nth action id e.g. id a9 ->id nr 20 action_id = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] - const indexOfActions = this.lookup_10_ActionId__To__ActioIndex(jsonObj, action_id) + const indexOfActions = this.get_ActionID_Index__From__ActionID_Id(jsonObj, action_id) // loop through all actionh/when find state and get action id ( 20-> state = 1) for (let jj = 0; jj < jsonObj.keyboard.actions.action[indexOfActions].when.length; jj++) { @@ -544,51 +473,37 @@ export class KeylayoutToKmnConverter { // if there is a state defined, collect all cases which result in that state ( e.g. which action id contains next = 1) if (stateVal !== undefined) { - // get output - result_C2 = jsonObj.keyboard.actions.action[indexOfActions].when[jj]['@_output'] - // console.log(" typeof(result_C2",typeof(result_C2),typeof( new TextEncoder().encode(result_C2)),typeof(new TextDecoder().decode( (new TextEncoder().encode(result_C2))))) // get all cases which result in state 3 - nextVal = this.lookup_5_ActionState__To__ActionNext_none(jsonObj, stateVal) + nextVal = this.get_ActionID_array__From__ActionID_NoneNext(jsonObj, stateVal) // for all modifier combinations for (let l = 0; l < data_ukelele.ArrayOf_Modifiers[i].length; l++) { for (let k = 0; k < nextVal.length; k++) { - if (result_C2 !== undefined) { - const KeymapIndey = this.lookup_15_KeyMapAction__To__KeyMapIndex(jsonObj, nextVal[k]) + if (jsonObj.keyboard.actions.action[indexOfActions].when[jj]['@_output'] !== undefined) { + const KeymapIndex = this.get_KeyMap_Index__From__KeyMap_Action(jsonObj, nextVal[k]) - for (let zz = 0; zz < data_ukelele.ArrayOf_Modifiers[KeymapIndey].length; zz++) { + for (let zz = 0; zz < data_ukelele.ArrayOf_Modifiers[KeymapIndex].length; zz++) { RuleObj = new Rules( "C2", - this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[i][l], isCapsused), - this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), - this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[KeymapIndey][zz], isCapsused), - this.map_UkeleleKC_To_VK(Number(this.lookup_11_KeyMapAction__To__KeyMapCode(jsonObj, nextVal[k]))), - new TextEncoder().encode(""), false, - "", - new TextEncoder().encode(""), - new TextEncoder().encode(""), - new TextEncoder().encode(""), - new TextEncoder().encode(result_C2), "", "", new TextEncoder().encode(""), 0, - this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[KeymapIndey][zz], isCapsused), - this.map_UkeleleKC_To_VK(Number(this.lookup_11_KeyMapAction__To__KeyMapCode(jsonObj, nextVal[k]))), + this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[KeymapIndex][zz], isCapsused), + this.map_UkeleleKC_To_VK(Number(this.get_KeyMap_Code__From__KeyMap_Action(jsonObj, nextVal[k]))), new TextEncoder().encode(""), dk_counter++, this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[i][l], isCapsused), this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), - new TextEncoder().encode(result_C2) + new TextEncoder().encode(jsonObj.keyboard.actions.action[indexOfActions].when[jj]['@_output']) ) ObjectArray.push(RuleObj) - // console.log("RuleObj", RuleObj) } } } @@ -602,68 +517,22 @@ export class KeylayoutToKmnConverter { // replace state x with all rules that result in 14 (action->action(state)->action(next)->terminator(output) ........................................ - // ...................................................................................................... - // in keys at top for code 10 (=K_BACKQUOTE) take actions id (a57) [German standard copy] - // code 10 = K_BACKQUOTE (or another key 93) - // get modifiers [modifer of Keymap index 0] - // goto action id a57 and find 14 in - // find all rules that result in 14 (next="14" - there might be several) - // get actionsId and of that rule (a80 ) - // look at top for a80 and find key Code (code 40 = K_K) - // get modifiers Index of that key (code 40) [modifer of Keymap index 3] - // lookup modifier names from modifiers Index - // take 20 ( of next="20") and look for state = 20 in terminators ("next" points to terminators) - // get output ("̭") - // [first modifier + K_K] > dk(dk1) ; dk(dk1) + [second modifier K_BKQUOTE] > "̭" - /* - - [ key code="10" -> action="a57" -> action id="a57" -> state="14" -> next="20 -> state="20" -> output="̭" ] - - - - - - - - - - - - - - [ action="a57" -> action id="a57" -> state="14" -> next="20 -> state="20" -> action id="a40" -> key code="37" ] - - - - - - [state="14" ≙ next="14" <- action id="a80 <- key code="40" <- keyMap index="3"] - - - - - - - - - - - - - */ - // ...................................................................................................... + // Action:state -> Action:state -> Action:id -> KeyMap:action -> keyMap:code (first dk) ................. + // Action:id -> KeyMap:action -> keyMap:code (second dk) ................................................ + // Action:next -> Action:state -> action:output ......................................................... + // Action:id -> KeyMap:action -> keyMap:code (key) ...................................................... + // ...................................................................................................... let value_state let value_next let Key_Block4 let KeyCode_Block2 - let codeIndexPair_Block4: any[][] - //let keymapIndexForactionID + //let codeIndexPair_Block4: any[][] let modifier_Block4_fixed: string[] // get a9 in behavior/key action_id = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] - const actionIdIndex = this.lookup_10_ActionId__To__ActioIndex(jsonObj, action_id) + const actionIdIndex = this.get_ActionID_Index__From__ActionID_Id(jsonObj, action_id) // loop all action-when and find state-next-pair for (let l = 0; l < jsonObj.keyboard.actions.action[actionIdIndex].when.length; l++) { @@ -679,76 +548,53 @@ export class KeylayoutToKmnConverter { // ........................................................................ // Data of Block Nr 4 .......................................................... - /* 4: code = 32 */ Key_Block4 = this.lookup_11_KeyMapAction__To__KeyMapCode(jsonObj, StateNextID_Block5) // find keyNr of that actionID a57> code=37 // my 32 ( K_U) + /* 4: code = 32 */ Key_Block4 = this.get_KeyMap_Code__From__KeyMap_Action(jsonObj, StateNextID_Block5) // find keyNr of that actionID a57> code=37 // my 32 ( K_U) /* 4: K_U */ //first_key_C3_U8_deadkey = new TextEncoder().encode(this.map_UkeleleKC_To_VK(Number(ContextKeyNr_deadkey))) - /* 4: codeIndexPair=[32 3] */ codeIndexPair_Block4 = this.lookup_14_ActionName__To__MapIndex(jsonObj, String(StateNextID_Block5)) + /* 4: codeIndexPair=[32 3] */ //codeIndexPair_Block4 = this.get_KeyMap_Code_array__From__ActionID_Action(jsonObj, String(StateNextID_Block5)) /* 4: MapIndex 3 */ //keymapIndexForactionID = this.lookup_14_ActionName__To__MapIndexSingle(jsonObj, String(theContextID)) - /* [32 3] FIX Arr[1] */ modifier_Block4_fixed = this.lookup_11_KeyMapIndex__To__Modifier(data_ukelele.ArrayOf_Modifiers, 1) // !! FIXED VALUE HERE!!!! needs to be loop + /* [32 3] FIX Arr[1] */ modifier_Block4_fixed = this.get_dataArray__From__KeyMap_Modifier_Index(data_ukelele.ArrayOf_Modifiers, 1) // !! FIXED VALUE HERE!!!! needs to be loop // ........................................................................ - console.log("modifier_Block4_fixed ", modifier_Block4_fixed) - // Data of Block Nr 3 .......................................................... //must be array ??? - /* 3: actioniD = a17 */ const NoneNextId_Block3 = this.lookup_5_ActionState__To__ActionNext_str(jsonObj, value_state) + /* 3: actioniD = a17 */ const NoneNextId_Block3 = this.get_ActionID_Id__From__ActionID_next(jsonObj, value_state) // ........................................................................ // Data of Block Nr 2 .......................................................... - /* 2: code = 28 */ KeyCode_Block2 = this.lookup_11_KeyMapAction__To__KeyMapCode(jsonObj, NoneNextId_Block3) + /* 2: code = 28 */ KeyCode_Block2 = this.get_KeyMap_Code__From__KeyMap_Action(jsonObj, NoneNextId_Block3) /* 2: K_8 */ const KeyName_Block2 = this.map_UkeleleKC_To_VK(Number(KeyCode_Block2)) - /* 2 index=3 */ const modifier_Block2 = this.lookup_14_ActionName__To__MapIndex(jsonObj, String(NoneNextId_Block3)) - /* 2 RALT */ const ModifierElementBlock2 = this.lookup_11_KeyMapIndex__To__Modifier(data_ukelele.ArrayOf_Modifiers, modifier_Block2[0][1]) + /* 2 index=3 */ const modifier_Block2 = this.get_KeyMap_Code_array__From__ActionID_Action(jsonObj, String(NoneNextId_Block3)) + /* 2 RALT */ const ModifierElementBlock2 = this.get_dataArray__From__KeyMap_Modifier_Index(data_ukelele.ArrayOf_Modifiers, modifier_Block2[0][1]) // ........................................................................ // Data of Block Nr 6 .......................................................... - /* 6: [ 'a9', '1', 'â' ] */ const state_Block6_all = this.lookup_13_ActionNext__To__AllState(jsonObj, value_next) - /* 6: output = â FIX */ const output_Block6_fixed = this.lookup_17_ActionState__To__ActionOutput(jsonObj, value_next, state_Block6_all[1][0]) + /* 6: [ 'a9', '1', 'â' ] */ const state_Block6_all = this.get_ActionID_Output_array__From__ActionID_State(jsonObj, value_next) + /* 6: output = â FIX */ const output_Block6_fixed = this.get_ActionID_Output__From__ActionID_State(jsonObj, value_next, state_Block6_all[1][0]) // ........................................................................ for (let a = 0; a < state_Block6_all.length; a++) { // Data of Block Nr 1 .......................................................... // todo get all state1´s - /* 2: code = 0 */ const keycode_Block1 = this.lookup_11_KeyMapAction__To__KeyMapCode(jsonObj, state_Block6_all[a][0]) + /* 2: code = 0 */ const keycode_Block1 = this.get_KeyMap_Code__From__KeyMap_Action(jsonObj, state_Block6_all[a][0]) /* 2: K_A */ const keyname_Block1 = this.map_UkeleleKC_To_VK(Number(keycode_Block1)) // ........................................................................ // a16 has state // field 1: which code has action a0 or a9 or... - const modif = this.lookup_15_KeyMapAction__To__KeyMapIndex_Arr(jsonObj, state_Block6_all[a][0], keycode_Block1) - //console.log("modif ", modif) + const modif = this.get_KeyMap_IndexCodeAction_array__From__KeyMap_Action(jsonObj, state_Block6_all[a][0], keycode_Block1) for (let jj = 0; jj < modif.length; jj++) { for (let kk = 0; kk < ModifierElementBlock2.length; kk++) { - const modifierText = this.lookup_11_KeyMapIndex__To__Modifier(data_ukelele.ArrayOf_Modifiers, Number(modif[jj][0])) + const modifierText = this.get_dataArray__From__KeyMap_Modifier_Index(data_ukelele.ArrayOf_Modifiers, Number(modif[jj][0])) const modiflat = modifierText.flat() const modi = this.create_kmn_modifier(modiflat[0], isCapsused) - console.log("modifierText : array of all modifiers", modifierText) - console.log("modiflat ", modiflat) - console.log("modi only the first mod !!! HERE!!", modi) - console.log(" modifier ", modifier_Block4_fixed) - RuleObj = new Rules( - "CX", - - modi, - keyname_Block1, - - //this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[i][l], isCapsused), - "modifier", - this.map_UkeleleKC_To_VK(Number(Key_Block4)), - - new TextEncoder().encode(""), + "C3", false, - "", - new TextEncoder().encode(""), - new TextEncoder().encode(""), - new TextEncoder().encode(""), - new TextEncoder().encode(""), - /* ****************************************** */ this.create_kmn_modifier(ModifierElementBlock2[kk], isCapsused), KeyName_Block2, @@ -765,69 +611,6 @@ export class KeylayoutToKmnConverter { new TextEncoder().encode(output_Block6_fixed), ) ObjectArray.push(RuleObj) - console.log("qqqqq C3 RuleObj", RuleObj) - - - } - } - } - } - const result_C3_U8 = new TextEncoder().encode(this.lookup_9_TerminatorState__To__TerminatorOutput_str(jsonObj, value_next)) - - for (let l = 0; l < data_ukelele.ArrayOf_Modifiers[i].length; l++) { - - if (Key_Block4 !== undefined) { - - for (let kk = 0; kk < data_ukelele.ArrayOf_Modifiers[codeIndexPair_Block4[0][1]].length; kk++) { - //console.log("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ") - - for (let jj = 0; jj < modifier_Block4_fixed.length; jj++) { - - const first_modifier_text_C3_U8_deadkey = data_ukelele.ArrayOf_Modifiers[codeIndexPair_Block4[0][1]][kk] - - if (this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])) !== "") { - console.log("(this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])) ", - (this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])))) - - console.log(" ",) - console.log(" ",) - console.log("this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])) ", this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']))) - - // ToDo is C3 this really neccessary? - I think no! ) - RuleObj = new Rules( - "C3", - - this.create_kmn_modifier(first_modifier_text_C3_U8_deadkey, isCapsused), - this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), - - modifier_Block4_fixed[jj], - this.map_UkeleleKC_To_VK(Number(Key_Block4)), - - result_C3_U8, - false, - "", - new TextEncoder().encode(""), - result_C3_U8, - new TextEncoder().encode(""), - new TextEncoder().encode(""), - - this.create_kmn_modifier(modifier_Block4_fixed[jj], isCapsused), - this.map_UkeleleKC_To_VK(Number(Key_Block4)), - new TextEncoder().encode(""), - 0, - - this.create_kmn_modifier(first_modifier_text_C3_U8_deadkey, isCapsused), - this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), - new TextEncoder().encode(""), - 0, - - this.create_kmn_modifier(modifier_Block4_fixed[jj], isCapsused), - this.map_UkeleleKC_To_VK(Number(Key_Block4)), - result_C3_U8 - ) - ObjectArray.push(RuleObj) - console.log("qqqqq C3 RuleObj", RuleObj) - } } } } @@ -837,51 +620,22 @@ export class KeylayoutToKmnConverter { // case C4: action + state none + Next .................................................................. // ...............e. g. ................................................... // a key is mapped to an action and then to a terminator ................................................ - // code->action->action(none)->action(next)->terminator(output) ......................................... + // action:state(none) -> action:next -> terminators:output .............................................. + // action:id -> keyMap:action -> keyMap:code ( dk ) ..................................................... + // action:id -> keyMap:action -> keyMap:code ( key) ..................................................... // ...................................................................................................... - // in keys for code 32 (K_U) at top find actions id a16 [italian copy] - // get modifiers [modifer of Keymap index 3] - // in actions a16 () find state "none" and get next (=4) - // in terminators ( ) find the state (=4) and get output ("¨") - // write [modifer of Keymap index 3 + K_U] -> "¨" - /* - [ action="a16" -> action id="a16" -> state="none" -> next="4 -> state="4" -> output="¨" ] - - - - - - - - - - - - */ - action_id = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] - const next_id = this.lookup_3_ActionNone__To__ActionNext(jsonObj, action_id) - const result_C4 = new TextEncoder().encode(this.lookup_9_TerminatorState__To__TerminatorOutput_str(jsonObj, next_id)) + const next_id = this.get_ActionID_Next__From__ActionID_None(jsonObj, action_id) for (let l = 0; l < data_ukelele.ArrayOf_Modifiers[i].length; l++) { - if (result_C4.length !== 0) { + if (new TextEncoder().encode(this.get_Terminator_Output__From__Terminator_State(jsonObj, next_id)).length !== 0) { RuleObj = new Rules( "C4", - this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[i][l], isCapsused), - this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), - "", - "", - new TextEncoder().encode(this.lookup_9_TerminatorState__To__TerminatorOutput_str(jsonObj, next_id)), true, - this.getHexFromChar(new TextDecoder().decode(result_C4)), - new TextEncoder().encode(this.getHexFromChar(new TextDecoder().decode(result_C4))), - result_C4, /* todo which one to use???*/ - result_C4, - result_C4, "", "", @@ -895,7 +649,7 @@ export class KeylayoutToKmnConverter { this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[i][l], isCapsused), this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), - result_C4 + new TextEncoder().encode(this.get_Terminator_Output__From__Terminator_State(jsonObj, next_id)) ) } ObjectArray.push(RuleObj) @@ -914,14 +668,14 @@ export class KeylayoutToKmnConverter { //--------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------- -let old_counter=0 + let old_counter = 0 console.log("start check ", ObjectArray.length) -console.log("ObjectArray ",ObjectArray.length ) + console.log("ObjectArray ", ObjectArray.length) for (let k = 0; k < ObjectArray.length; k++) { if (/*(ObjectArray[k].type_C === "C3")||*/(ObjectArray[k].type_C === "C2")) { -old_counter++ + old_counter++ console.log("Obj: k ", k, "\tType: ", (ObjectArray[k].type_C !== "" ? ObjectArray[k].type_C : "--".padEnd(4, " ")), @@ -944,7 +698,7 @@ old_counter++ ) } } - console.log("old_counter ",old_counter ) + console.log("old_counter ", old_counter) //remove entries that are available in both arrays @@ -966,7 +720,6 @@ old_counter++ console.log("####### SAME AMOUNTS :)) ", "testArray_kmn_filter:", testArray_kmn_filter, "testArray_Ukelele_filter:", testArray_Ukelele_filter) - //****************************************************************************************** */ const testArray_Ukelele_action_uni: string[] = testArray_Ukelele_action.filter(function (item, pos, self) { return self.indexOf(item) == pos; }) @@ -998,84 +751,67 @@ old_counter++ //--------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------- - - data_ukelele.ArrayOf_Rules = ObjectArray return data_ukelele } - - - - - public lookup_3_ActionNone__To__ActionNext(data: any, search: string): string { - for (let jj = 0; jj < data.keyboard.actions.action.length; jj++) { - if (data.keyboard.actions.action[jj]['@_id'] === search) { - for (let kk = 0; kk < data.keyboard.actions.action[jj].when.length; kk++) { - if (data.keyboard.actions.action[jj].when[kk]['@_state'] === "none") - return data.keyboard.actions.action[jj].when[kk]['@_next'] + public get_ActionID_Next__From__ActionID_None(data: any, search: string): string { + for (let i = 0; i < data.keyboard.actions.action.length; i++) { + if (data.keyboard.actions.action[i]['@_id'] === search) { + for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { + if (data.keyboard.actions.action[i].when[j]['@_state'] === "none") + return data.keyboard.actions.action[i].when[j]['@_next'] } } } return "" } - public lookup_5_ActionState__To__ActionNext(data: any, action_idName: string): string[] { + public get_ActionID_Id_array__From__ActionID_next(data: any, search: string): string[] { const returnarray: string[] = [] - // e.g. action_idName = 3 - if (action_idName !== "none") { - // loop all action/when - for (let k = 0; k < data.keyboard.actions.action.length; k++) { - for (let j = 0; j < data.keyboard.actions.action[k].when.length; j++) { - // find attribute next === 3 - if (data.keyboard.actions.action[k].when[j]['@_next'] === action_idName) { - returnarray.push(data.keyboard.actions.action[k]['@_id']) + if (search !== "none") { + for (let i = 0; i < data.keyboard.actions.action.length; i++) { + for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { + if (data.keyboard.actions.action[i].when[j]['@_next'] === search) { + returnarray.push(data.keyboard.actions.action[i]['@_id']) } } } } return returnarray } - public lookup_5_ActionState__To__ActionNext_str(data: any, action_idName: string): string { - // e.g. action_idName = 3 - if (action_idName !== "none") { - // loop all action/when - for (let k = 0; k < data.keyboard.actions.action.length; k++) { - for (let j = 0; j < data.keyboard.actions.action[k].when.length; j++) { - // find attribute next === 3 - if (data.keyboard.actions.action[k].when[j]['@_next'] === action_idName) { - return data.keyboard.actions.action[k]['@_id'] + public get_ActionID_Id__From__ActionID_next(data: any, search: string): string { + if (search !== "none") { + for (let i = 0; i < data.keyboard.actions.action.length; i++) { + for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { + if (data.keyboard.actions.action[i].when[j]['@_next'] === search) { + return data.keyboard.actions.action[i]['@_id'] } } } } return "" } - public lookup_5_ActionState__To__ActionNext_none(data: any, action_idName: string): string[] { + public get_ActionID_array__From__ActionID_NoneNext(data: any, search: string): string[] { const returnarray: string[] = [] - // e.g. action_idName = 3 - if (action_idName !== "none") { - // loop all action/when - for (let k = 0; k < data.keyboard.actions.action.length; k++) { - for (let j = 0; j < data.keyboard.actions.action[k].when.length; j++) { - // find attribute next === 3 - if (data.keyboard.actions.action[k].when[j]['@_next'] === action_idName) { - if (data.keyboard.actions.action[k].when[j]['@_state'] === "none") - returnarray.push(data.keyboard.actions.action[k]['@_id']) + if (search !== "none") { + for (let i = 0; i < data.keyboard.actions.action.length; i++) { + for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { + if (data.keyboard.actions.action[i].when[j]['@_next'] === search) { + if (data.keyboard.actions.action[i].when[j]['@_state'] === "none") + returnarray.push(data.keyboard.actions.action[i]['@_id']) } } } } return returnarray } - public lookup_6_ActionNone__To__ActionOutput(data: any, search: any): any { - // a16-> id ==a16 ->4 - //todo what if duplicate value?? + public get_Action2ID_NoneOutput__From__ActionID_Id(data: any, search: any): any { let OutputValue = "" - for (let jj = 0; jj < data.keyboard.actions.action.length; jj++) { - if (data.keyboard.actions.action[jj]['@_id'] === search) { - for (let kk = 0; kk < data.keyboard.actions.action[jj].when.length; kk++) { - if (data.keyboard.actions.action[jj].when[kk]['@_state'] === "none") { - OutputValue = data.keyboard.actions.action[jj].when[kk]['@_output'] + for (let i = 0; i < data.keyboard.actions.action.length; i++) { + if (data.keyboard.actions.action[i]['@_id'] === search) { + for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { + if (data.keyboard.actions.action[i].when[j]['@_state'] === "none") { + OutputValue = data.keyboard.actions.action[i].when[j]['@_output'] } } } @@ -1083,42 +819,40 @@ old_counter++ return OutputValue } // get all entries for state= and a given action id - public lookup_6_Action__To__State_Array(data: any, search: any): any[] { + public get_Action2ID_State_arrayState_Array__From__ActionID_Id(data: any, search: any): any[] { const returnarray: string[] = [] - for (let jj = 0; jj < data.keyboard.actions.action.length; jj++) { - if (data.keyboard.actions.action[jj]['@_id'] === search) { - for (let kk = 0; kk < data.keyboard.actions.action[jj].when.length; kk++) { - if (data.keyboard.actions.action[jj].when[kk]['@_state'] !== "none") { - returnarray.push(data.keyboard.actions.action[jj].when[kk]['@_state']) + for (let i = 0; i < data.keyboard.actions.action.length; i++) { + if (data.keyboard.actions.action[i]['@_id'] === search) { + for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { + if (data.keyboard.actions.action[i].when[j]['@_state'] !== "none") { + returnarray.push(data.keyboard.actions.action[i].when[j]['@_state']) } } } } return returnarray } - // get all entries for state= and a given action id - public lookup_6_State__From__Next_Array(data: any, search: any): string[] { + public get_ActionID_Id_arrayNext_Array__From__ActionID_StateNext(data: any, search: any): string[] { const returnarray: string[] = [] - for (let jj = 0; jj < data.keyboard.actions.action.length; jj++) { - for (let kk = 0; kk < data.keyboard.actions.action[jj].when.length; kk++) { - if ((data.keyboard.actions.action[jj].when[kk]['@_next'] === search) && (data.keyboard.actions.action[jj].when[kk]['@_state'] !== "none")) { - returnarray.push(data.keyboard.actions.action[jj]['@_id']) + for (let i = 0; i < data.keyboard.actions.action.length; i++) { + for (let kk = 0; kk < data.keyboard.actions.action[i].when.length; kk++) { + if ((data.keyboard.actions.action[i].when[kk]['@_next'] === search) && (data.keyboard.actions.action[i].when[kk]['@_state'] !== "none")) { + returnarray.push(data.keyboard.actions.action[i]['@_id']) } } } return returnarray } - - public lookup_13_ActionNext__To__AllState(data: any, search: string) { + public get_ActionID_Output_array__From__ActionID_State(data: any, search: string) { const returnarray2D: string[][] = [] - for (let ll = 0; ll < data.keyboard.actions.action.length; ll++) { - for (let mm = 0; mm < data.keyboard.actions.action[ll].when.length; mm++) { + for (let i = 0; i < data.keyboard.actions.action.length; i++) { + for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { const returnarray: string[] = [] - if ((data.keyboard.actions.action[ll].when[mm]['@_state'] === search)) { - returnarray.push(data.keyboard.actions.action[ll]['@_id']) - returnarray.push(data.keyboard.actions.action[ll].when[mm]['@_state']) - returnarray.push(data.keyboard.actions.action[ll].when[mm]['@_output']) + if ((data.keyboard.actions.action[i].when[j]['@_state'] === search)) { + returnarray.push(data.keyboard.actions.action[i]['@_id']) + returnarray.push(data.keyboard.actions.action[i].when[j]['@_state']) + returnarray.push(data.keyboard.actions.action[i].when[j]['@_output']) } if (returnarray.length > 0) returnarray2D.push(returnarray) @@ -1126,53 +860,50 @@ old_counter++ } return returnarray2D } - - - public lookup_9_TerminatorState__To__TerminatorOutput_str(data: any, search: string): string { - let OutputValue = "" - for (let jj = 0; jj < data.keyboard.terminators.when.length; jj++) { - if (data.keyboard.terminators.when[jj]['@_state'] === search) { - OutputValue = data.keyboard.terminators.when[jj]['@_output'] + public get_Terminator_Output__From__Terminator_State(data: any, search: string): string { + for (let i = 0; i < data.keyboard.terminators.when.length; i++) { + if (data.keyboard.terminators.when[i]['@_state'] === search) { + return data.keyboard.terminators.when[i]['@_output'] } } - return OutputValue + return "" } - public lookup_10_ActionId__To__ActioIndex(data: any, search: string): number { - for (let k = 0; k < data.keyboard.actions.action.length; k++) { - if (data.keyboard.actions.action[k]['@_id'] === search) - return k + public get_ActionID_Index__From__ActionID_Id(data: any, search: string): number { + for (let i = 0; i < data.keyboard.actions.action.length; i++) { + if (data.keyboard.actions.action[i]['@_id'] === search) + return i } return 0 } - public lookup_11_KeyMapAction__To__KeyMapCode(data: any, search: string): number { - for (let kk = 0; kk < data.keyboard.keyMapSet[0].keyMap.length; kk++) { - for (let jj = 0; jj < data.keyboard.keyMapSet[0].keyMap[kk].key.length; jj++) { - if (data.keyboard.keyMapSet[0].keyMap[kk].key[jj]['@_action'] === search) { - return data.keyboard.keyMapSet[0].keyMap[kk].key[jj]['@_code'] + public get_KeyMap_Code__From__KeyMap_Action(data: any, search: string): number { + for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { + for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { + if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { + return data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'] } } } return -1 } - public lookup_13_ActionNext__To__ActionID(data: any, search: string) { - for (let ll = 0; ll < data.keyboard.actions.action.length; ll++) { - for (let mm = 0; mm < data.keyboard.actions.action[ll].when.length; mm++) { - if ((data.keyboard.actions.action[ll].when[mm]['@_next'] === search)) { - return data.keyboard.actions.action[ll]['@_id'] + public get_ActionID_Id__From__ActionID_Next(data: any, search: string) { + for (let i = 0; i < data.keyboard.actions.action.length; i++) { + for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { + if ((data.keyboard.actions.action[i].when[j]['@_next'] === search)) { + return data.keyboard.actions.action[i]['@_id'] } } } return "" } - public lookup_14_ActionName__To__MapIndex(data: any, search: string): number[][] { + public get_KeyMap_Code_array__From__ActionID_Action(data: any, search: string): number[][] { const mapIndexArray_max: number[][] = [] - for (let kk = 0; kk < data.keyboard.keyMapSet[0].keyMap.length; kk++) { - for (let jj = 0; jj < data.keyboard.keyMapSet[0].keyMap[kk].key.length; jj++) { + for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { + for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { const mapIndexArrayperKey: number[] = [] - if (data.keyboard.keyMapSet[0].keyMap[kk].key[jj]['@_action'] === search) { - mapIndexArrayperKey.push(data.keyboard.keyMapSet[0].keyMap[kk].key[jj]['@_code']) - mapIndexArrayperKey.push(kk) + if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { + mapIndexArrayperKey.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']) + mapIndexArrayperKey.push(i) } if (mapIndexArrayperKey.length > 0) mapIndexArray_max.push(mapIndexArrayperKey) @@ -1180,15 +911,15 @@ old_counter++ } return mapIndexArray_max } - public lookup_14_ActionName__To__MapIndexSingle(data: any, search: string): number { + public get_KeyMap_Code__From__ActionID_Action(data: any, search: string): number { const mapIndexArray_max: number[][] = [] - for (let kk = 0; kk < data.keyboard.keyMapSet[0].keyMap.length; kk++) { - for (let jj = 0; jj < data.keyboard.keyMapSet[0].keyMap[kk].key.length; jj++) { + for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { + for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { const mapIndexArrayperKey: number[] = [] - if (data.keyboard.keyMapSet[0].keyMap[kk].key[jj]['@_action'] === search) { - mapIndexArrayperKey.push(data.keyboard.keyMapSet[0].keyMap[kk].key[jj]['@_code']) - mapIndexArrayperKey.push(kk) + if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { + mapIndexArrayperKey.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']) + mapIndexArrayperKey.push(i) } if (mapIndexArrayperKey.length > 0) mapIndexArray_max.push(mapIndexArrayperKey) @@ -1196,74 +927,56 @@ old_counter++ } return mapIndexArray_max[0][1] } - public lookup_15_KeyMapAction__To__State(data: any, search: string): string { - // todo loop - for (let k = 0; k < data.keyboard.actions.action.length; k++) { - if ((data.keyboard.actions.action[k]['@_id'] === search)) - // for (let l = 0; l < data.keyboard.actions.action[l].length; l++) { - for (let j = 0; j < data.keyboard.actions.action.when.length; j++) { - return "" - //return data.keyboard.actions.action[k].when[j]['@_state'] - } - //} - } - return "" - } - public lookup_15_KeyMapAction__To__Next(data: any, search: string): string { - for (let k = 0; k < data.keyboard.actions.action.length; k++) { - if ((data.keyboard.actions.action[k]['@_id'] === search)) - return data.keyboard.actions.action[k].when[1]['@_next'] + public get_ActionID_Next__From__ActionID_Id(data: any, search: string): string { + for (let i = 0; i < data.keyboard.actions.action.length; i++) { + if ((data.keyboard.actions.action[i]['@_id'] === search)) + return data.keyboard.actions.action[i].when[1]['@_next'] } return "" } - - public lookup_15_KeyMapAction__To__KeyMapIndex(data: any, search: string): number { - for (let kk = 0; kk < data.keyboard.keyMapSet[0].keyMap.length; kk++) { - for (let jj = 0; jj < data.keyboard.keyMapSet[0].keyMap[kk].key.length; jj++) { - if (data.keyboard.keyMapSet[0].keyMap[kk].key[jj]['@_action'] === search) { - return data.keyboard.keyMapSet[0].keyMap[kk]['@_index'] + public get_KeyMap_Index__From__KeyMap_Action(data: any, search: string): number { + for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { + for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { + if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { + return data.keyboard.keyMapSet[0].keyMap[i]['@_index'] } } } return -1 } - public lookup_15_KeyMapAction__To__KeyMapIndex_Arr(data: any, search: string, keycode: number): string[][] { + public get_KeyMap_IndexCodeAction_array__From__KeyMap_Action(data: any, search: string, keycode: number): string[][] { const returnarray2D: string[][] = [] - for (let kk = 0; kk < data.keyboard.keyMapSet[0].keyMap.length; kk++) { - for (let jj = 0; jj < data.keyboard.keyMapSet[0].keyMap[kk].key.length; jj++) { + for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { + for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { const returnarray: string[] = [] - if (data.keyboard.keyMapSet[0].keyMap[kk].key[jj]['@_action'] === search) { - returnarray.push(data.keyboard.keyMapSet[0].keyMap[kk]['@_index']) - returnarray.push(data.keyboard.keyMapSet[0].keyMap[kk].key[jj]['@_code']) - returnarray.push(data.keyboard.keyMapSet[0].keyMap[kk].key[jj]['@_action']) + if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { + returnarray.push(data.keyboard.keyMapSet[0].keyMap[i]['@_index']) + returnarray.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']) + returnarray.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action']) } if (returnarray.length > 0) { returnarray2D.push(returnarray) } } } - return returnarray2D } - - public lookup_11_KeyMapIndex__To__Modifier(data: any, search: number): string[] { - return data[search] - } - public lookup_11_KeyMapIndex__To__Modifier2(data: any, search: number): string[] { - return data.ArrayOf_Modifiers[search] - //return data[search] - } - - public lookup_17_ActionState__To__ActionOutput(data: any, search: string, nextval: string): string { - for (let k = 0; k < data.keyboard.actions.action.length; k++) { - for (let j = 0; j < data.keyboard.actions.action[k].when.length; j++) { - if ((data.keyboard.actions.action[k].when[j]['@_state'] === search) && (data.keyboard.actions.action[k]['@_id'] === nextval)) { - return data.keyboard.actions.action[k].when[j]['@_output'] + public get_ActionID_Output__From__ActionID_State(data: any, search: string, nextval: string): string { + for (let i = 0; i < data.keyboard.actions.action.length; i++) { + for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { + if ((data.keyboard.actions.action[i].when[j]['@_state'] === search) && (data.keyboard.actions.action[i]['@_id'] === nextval)) { + return data.keyboard.actions.action[i].when[j]['@_output'] } } } return "" } + public get_KeyMap_Modifier_aray__From__KeyMap_Index(data: any, search: number): string[] { + return data.ArrayOf_Modifiers[search] + } + public get_dataArray__From__KeyMap_Modifier_Index(data: any, search: number): string[] { + return data[search] + } /** * @brief member function to return the unicode value of a character @@ -1274,7 +987,6 @@ old_counter++ return character.charCodeAt(0).toString(16).slice(-4).toUpperCase().padStart(4, "0") } - // TODO if the first in the list does not contain caps but later entries do contain caps-> no NCAPS is added(Todo check if caps/NCAPS are there after all entries are completed) /** * @brief member function to create a string of modifiers in kmn-style from the modifierMap section of .keylayout-file * @param keylayout_modifier the modifier value used in the .keylayout-file @@ -1417,35 +1129,14 @@ old_counter++ //---------------------------------------------------------------------------------------------------- - public createData_Deadkeys(data_ukelele: convert_object, workArray2D: any[]): string { + public createData_Deadkeys(data_ukelele: convert_object): string { let data: string = "" // filter for dk values data += '\########## OK #################################################################\n' data += '\nNOW MY C4 RULES **ccc ********* (only to get 02C6 ect) *********************\n\n' - // ToDo in 1 func - // select only lines twhere isTerminator=true - const uniqueDeadkeys_all = workArray2D.filter((curr) => { - if (curr.isTerminator === true) { - return curr; - } - }); - - // remove duplicates - const uniqueDeadkeys = uniqueDeadkeys_all.reduce((unique, o) => { - if (!unique.some((obj: { chars: any; type_C: any; modifier_key: any; key: any }) => - new TextDecoder().decode(obj.chars) === new TextDecoder().decode(o.chars) - && obj.key === o.key - && obj.type_C === o.type_C - && obj.modifier_key === o.modifier_key) - ) { - unique.push(o); - } - return unique; - }, []); - - const uniqueDeadkeys_all_obj = data_ukelele.ArrayOf_Rules.filter((curr) => { + const DeadkeyRules = data_ukelele.ArrayOf_Rules.filter((curr) => { if (curr.isTerminator === true) { return curr; } @@ -1453,9 +1144,9 @@ old_counter++ }); // remove duplicates - const uniqueDeadkeys_obj = uniqueDeadkeys_all_obj.reduce((unique, o) => { - if (!unique.some((obj: { chars: any; type_C: any; modifier_key: any; key: any }) => - new TextDecoder().decode(obj.chars) === new TextDecoder().decode(o.chars) + const uniqueDeadkeyRules = DeadkeyRules.reduce((unique, o) => { + if (!unique.some((obj: { deadkeyed_Ch: any; type_C: any; modifier_key: any; key: any }) => + new TextDecoder().decode(obj.deadkeyed_Ch) === new TextDecoder().decode(o.deadkeyed_Ch) && obj.key === o.key && obj.type_C === o.type_C && obj.modifier_key === o.modifier_key) @@ -1465,15 +1156,14 @@ old_counter++ return unique; }, []); - for (let kkk = 0; kkk < uniqueDeadkeys_obj.length; kkk++) { + for (let i = 0; i < uniqueDeadkeyRules.length; i++) { let line: string = "" - // line = "+ [" + uniqueDeadkeys[kkk].modifier_key + " " + uniqueDeadkeys[kkk].key + "] > dk(" + uniqueDeadkeys[kkk].dk_hex + ")" - line = "+ [" + uniqueDeadkeys_obj[kkk].modifier_key + " " + uniqueDeadkeys_obj[kkk].key + "] > dxk(" + uniqueDeadkeys_obj[kkk].dk_hex + ")" + line = "+ [" + uniqueDeadkeyRules[i].modifier_key + " " + uniqueDeadkeyRules[i].key + "] > dxk(" + this.getHexFromChar(new TextDecoder().decode(uniqueDeadkeyRules[i].deadkeyed_Ch)) + ")" data += line + '\n' } - + //*************************************************************************************************** */ /* - How to create rules from keylayout data ffrom data_ukelele.ArrayOf_processed_RuleData: + How to create rules from keylayout data from data_ukelele.ArrayOf_processed_RuleData: There are 6 different types of data entries (C0-C4) in data_ukelele.ArrayOf_processed_RuleData e.g. that contain all data to retrieve deadkeys, deadkeyables and deadkeyed characters: @@ -1502,23 +1192,9 @@ old_counter++ */ - // select only lines for deadkeyables ( entries that contain C1, are not K_SPACE and create chars e.g. from 'C1', 'CAPS', 'K_A', 'A' ]) - /* const deadkeyables_raw = workArray2D.filter((curr) => { - if ((curr.type_C === "C1") && (curr.key !== "K_SPACE") && (new TextDecoder().decode(curr.chars) !== "")) { - return curr; - } - }); - - // select only lines for deadkeyed ( entries that contain C2, are not K_SPACE and create a deadkeyed) e.g. from ['C2', 'CAPS', 'K_A', 'K_N', 'Ã' ] - const deadkeyed_raw_multiple = workArray2D.filter((curr) => { - if ((curr.type_C === "C2") && (curr.key !== "K_SPACE") && (curr.deadkeyed !== "")) { - return curr; - } - });*/ - // select only lines for deadkeyables ( entries that contain C1, are not K_SPACE and create chars e.g. from 'C1', 'CAPS', 'K_A', 'A' ]) const deadkeyables_raw = data_ukelele.ArrayOf_Rules.filter((curr) => { - if ((curr.type_C === "C1") && (curr.key !== "K_SPACE") && (new TextDecoder().decode(curr.chars) !== "")) { + if ((curr.type_C === "C1") && (curr.key !== "K_SPACE") && (new TextDecoder().decode(curr.deadkeyed_Ch) !== "")) { return curr; } return "" @@ -1526,17 +1202,18 @@ old_counter++ // select only lines for deadkeyed ( entries that contain C2, are not K_SPACE and create a deadkeyed) e.g. from ['C2', 'CAPS', 'K_A', 'K_N', 'Ã' ] const deadkeyed_raw_multiple = data_ukelele.ArrayOf_Rules.filter((curr) => { - // if ((curr.type_C === "C2") && (curr.key !== "K_SPACE") && (curr.deadkeyed_Ch !== "")) { - if ((curr.type_C === "C2") && (curr.key !== "K_SPACE") ) { + // if ((curr.type_C === "C2") && (curr.key !== "K_SPACE") && (new TextDecoder().decode(curr.deadkeyed_Ch) !== "")) { + // if ((curr.type_C === "C2") && (curr.key !== "K_SPACE")) { + if ((curr.type_C === "C2")) { return curr; } return "" }); - // remove duplicate s + // remove duplicates const deadkeyed_raw = deadkeyed_raw_multiple.reduce((unique, o) => { - if (!unique.some((obj: { chars: any; type_C: any; modifier_key: any; key: any; deadkeyed: any }) => - new TextDecoder().decode(obj.deadkeyed) === new TextDecoder().decode(o.deadkeyed) + if (!unique.some((obj: { chars: any; type_C: any; modifier_key: any; key: any; deadkeyed_Ch: any }) => + new TextDecoder().decode(obj.deadkeyed_Ch) === new TextDecoder().decode(o.deadkeyed_Ch) && obj.key === o.key && obj.type_C === o.type_C && obj.modifier_key === o.modifier_key) @@ -1557,9 +1234,9 @@ old_counter++ if ((deadkeyables_raw[rr].modifier_key === deadkeyed_raw[ss].modifier_key) && ((deadkeyables_raw[rr].key === deadkeyed_raw[ss].key))) { - dk_array.push(new TextDecoder().decode(deadkeyables_raw[rr].chars)) // deadkeyable e.g. A - dk_array.push(deadkeyed_raw[ss].key_second) // Keyname dk e.g. K_N - dk_array.push(new TextDecoder().decode(deadkeyed_raw[ss].deadkeyed)) // deadkeyed e.g. Ã + dk_array.push(new TextDecoder().decode(deadkeyables_raw[rr].deadkeyed_Ch)) // deadkeyable e.g. A + dk_array.push(deadkeyed_raw[ss].deadkey) // Keyname dk e.g. K_N + dk_array.push(new TextDecoder().decode(deadkeyed_raw[ss].deadkeyed_Ch)) // deadkeyed e.g. Ã } if (dk_array.length > 0) dk_array_comlpete.push(dk_array) @@ -1576,21 +1253,94 @@ old_counter++ }, [[], new Set()], ); - const deadkeyedElement: string[][] = Array.from({ length: uniqueDeadkeys.length }, () => new Array(2).fill('')); - const deadkeyablesElement: string[][] = Array.from({ length: uniqueDeadkeys.length }, () => new Array(1).fill('')); + // print + for (let i = 0; i < deadkeyables_raw.length; i++) { + console.log("deadkeyables_raw ", i, "\t", + deadkeyables_raw[i].type_C, "--", + deadkeyables_raw[i].modifier_key.padEnd(28, " "), "--", + deadkeyables_raw[i].key.padEnd(10, " "), "--", + new TextDecoder().decode(deadkeyables_raw[i].deadkeyed_Ch), + "°°",) + } + + for (let i = 0; i < deadkeyed_raw.length; i++) { + console.log("deadkeyed_raw ", i, "\t", + deadkeyed_raw[i].type_C, "--", + deadkeyed_raw[i].modifier_key.padEnd(28, " "), "--", + deadkeyed_raw[i].key.padEnd(10, " "), "--", + new TextDecoder().decode(deadkeyed_raw[i].deadkeyed_Ch).padEnd(5, " "), + + deadkeyed_raw[i].modifier_deadkey.padEnd(28, " "), "--", + deadkeyed_raw[i].deadkey.padEnd(10, " "), "--", + new TextDecoder().decode(deadkeyed_raw[i].deadkeys_Ch), "--", + deadkeyed_raw[i].dk, "--xx", + + + new TextDecoder().decode(deadkeyed_raw[i].deadkeys).padEnd(5, " "), "--", + new TextDecoder().decode(deadkeyed_raw[i].deadkeyables).padEnd(5, " "), "--", + new TextDecoder().decode(deadkeyed_raw[i].deadkeyed_Ch).padEnd(5, " "), + + "°°",) + } + //console.log("dk_array_comlpete ", dk_array_comlpete) + //console.log("unique_dk_array_comlpete ", unique_dk_array_comlpete) + + const deadkeyedElement: string[][] = Array.from({ length: uniqueDeadkeyRules.length }, () => new Array(2).fill('')); + const deadkeyablesElement: string[][] = Array.from({ length: uniqueDeadkeyRules.length }, () => new Array(1).fill('')); // why is there a set entry???? deadkeyables_raw[0] - for (let i = 0; i < uniqueDeadkeys.length; i++) { + for (let i = 0; i < uniqueDeadkeyRules.length; i++) { for (let j = 0; j < unique_dk_array_comlpete[0].length; j++) { - if (uniqueDeadkeys[i].key === unique_dk_array_comlpete[0][j][1]) { + if (uniqueDeadkeyRules[i].key === unique_dk_array_comlpete[0][j][1]) { deadkeyablesElement[i][0] = deadkeyablesElement[i][0] + "\'" + unique_dk_array_comlpete[0][j][0] + "\' " deadkeyedElement[i][0] = deadkeyedElement[i][0] + "\'" + unique_dk_array_comlpete[0][j][2] + "\' " } - deadkeyedElement[i][1] = uniqueDeadkeys[i].dk_hex + deadkeyedElement[i][1] = this.getHexFromChar(new TextDecoder().decode(uniqueDeadkeyRules[i].deadkeyed_Ch)) + } + } + // console.log("deadkeyedElement ", deadkeyedElement) + // console.log("deadkeyablesElement ", deadkeyablesElement) + + + /*const newAA: string[][] = [] + let merker = "" + for (let i = 0; i < deadkeyedElement.length; i++) { + if (deadkeyedElement[i][1] !== merker) { + const newA: string[] = [] + newA.push(deadkeyedElement[i][1]) + newA.push(deadkeyablesElement[i][0]) + newA.push(deadkeyedElement[i][0]) + newAA.push(newA) + merker = deadkeyedElement[i][1] } } + console.log("newAA ", newAA)*/ + /* + const newAA: string[][] = [] + let merker = "" + for (let i = 0; i < deadkeyedElement.length; i++) { + merker = deadkeyedElement[i][1] + for (let j = 0; j < newAA.length; j++) { + if (newAA[j][0] === deadkeyedElement[i][0]) { + } + } + + + + + if (deadkeyedElement[i][1] !== merker) { + const newA: string[] = [] + newA.push(deadkeyedElement[i][1]) + newA.push(deadkeyablesElement[i][0]) + newA.push(deadkeyedElement[i][0]) + newAA.push(newA) + } + } + console.log("newAA ", newAA)*/ + + data += "\n" data += '\########## OK #################################################################\n' @@ -1598,77 +1348,38 @@ old_counter++ data += '\nmatch > use(deadkeys)\n\n' data += '\ngroup(deadkeys)\n\n' + //for (let i = 0; i < newAA.length; i++) { for (let i = 0; i < deadkeyablesElement.length; i++) { data += "\n\ndk: " + deadkeyedElement[i][1] data += "\ndeadkeyablesArray xx" + deadkeyablesElement[i][0] - data += "\ndeadkeyedArray xx " + deadkeyedElement[i][0] + data += "\ndeadkeyedArray xx " + deadkeyedElement[i][0] + /*data += "\n\ndk: " + newAA[i][0] + data += "\ndeadkeyablesArray xx" + newAA[i][1] + data += "\ndeadkeyedArray xx " + newAA[i][2]*/ } return data } - public createData_Rules(data_ukelele: convert_object, workArray2D: any[]): string { + public createData_Rules(data_ukelele: convert_object): string { const maxkey = 50 let data: string = "" let keymarker = "" -console.log("data_ukelele.ArrayOf_Rules ", data_ukelele.ArrayOf_Rules.length,data_ukelele.ArrayOf_Rules[155].key) - - // can I use dataUkeklele /ruledata to get uniqueDeadkeys_all - // select only lines that contain C0 or C1 and create an output. -/* - const uniqueDeadkeys_New = data_ukelele.ArrayOf_Rules.reduce((unique, o) => { - if (!unique.some((obj: { chars: any; type_C: any; modifier_key: any; key: any }) => - new TextDecoder().decode(obj.chars) === new TextDecoder().decode(o.chars) - && obj.key === o.key - && obj.type_C === o.type_C - && obj.modifier_key === o.modifier_key) - ) { - unique.push(o); - } - return unique; - }, []); -let unique_counter=0 - console.log("uniqueDeadkeys_New ",uniqueDeadkeys_New.length ) -console.log("uniqueDeadkeys_New ",uniqueDeadkeys_New.length ,uniqueDeadkeys_New) -for (let k = 0; k < uniqueDeadkeys_New.length; k++) { - - if ((ObjectArray[k].type_C === "C3")||(uniqueDeadkeys_New[k].type_C === "C2")) { - unique_counter++ -console.log("uniqueDeadkeys_New: k ", k, - "\tType: ", (uniqueDeadkeys_New[k].type_C !== "" ? uniqueDeadkeys_New[k].type_C : "--".padEnd(4, " ")), + //console.log("data_ukelele.ArrayOf_Rules ", data_ukelele.ArrayOf_Rules.length, data_ukelele.ArrayOf_Rules[155].key) - "| modi_prev_dk: ", (uniqueDeadkeys_New[k].modifier_prev_deadkey !== "" ? uniqueDeadkeys_New[k].modifier_prev_deadkey.padEnd(23, " ") : "--".padEnd(23, " ")), - "key_prev_dk: ", (uniqueDeadkeys_New[k].prev_deadkey !== "" ? uniqueDeadkeys_New[k].prev_deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), - "is_prev dk(): ", (uniqueDeadkeys_New[k].dk_prev !== 0 ? ("dk_p(" + String(uniqueDeadkeys_New[k].dk_prev) + ")").padEnd(11, " ") : "--".padEnd(11, " ")), - - "| modi_dk: ", (uniqueDeadkeys_New[k].modifier_deadkey !== "" ? uniqueDeadkeys_New[k].modifier_deadkey.padEnd(23, " ") : "--".padEnd(23, " ")), - "key_dk: ", (uniqueDeadkeys_New[k].deadkey !== "" ? uniqueDeadkeys_New[k].deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), - "is dk(): ", (uniqueDeadkeys_New[k].dk !== 0 ? ("dk(" + String(uniqueDeadkeys_New[k].dk) + ")").padEnd(9, " ") : "--".padEnd(9, " ")), - - "| modi: ", (uniqueDeadkeys_New[k].modifier_key !== "" ? uniqueDeadkeys_New[k].modifier_key.padEnd(20, " ") : "--".padEnd(20, " ")), - "key: ", (uniqueDeadkeys_New[k].key !== "" ? uniqueDeadkeys_New[k].key.padEnd(8, " ") : "--".padEnd(8, " ")), - "ch: ", (new TextDecoder().decode(uniqueDeadkeys_New[k].deadkeyed_Ch) !== "" ? new TextDecoder().decode(uniqueDeadkeys_New[k].deadkeyed_Ch).padEnd(10, " ") : "--".padEnd(10, " ")), - - "| °°" -) - - }} -console.log("unique_counter ",unique_counter ) - -*/ - // can I use dataUkeklele /ruledata to get uniqueDeadkeys_all // select only lines that contain C0 or C1 and create an output. - const uniqueDeadkeys_all = workArray2D.filter((curr) => { - if ((curr.chars !== new TextEncoder().encode("") || curr.chars !== undefined) + const data_C0_C1 = data_ukelele.ArrayOf_Rules.filter((curr) => { + if ((curr.deadkeyed_Ch !== new TextEncoder().encode("") || curr.deadkeyed_Ch !== undefined) && (curr.type_C === "C0") || (curr.type_C === "C1")) { return curr; } + else return "" }); // Also remove duplicates - const uniqueDeadkeys = uniqueDeadkeys_all.reduce((unique, o) => { - if (!unique.some((obj: { chars: any; type_C: any; modifier_key: any; key: any }) => - new TextDecoder().decode(obj.chars) === new TextDecoder().decode(o.chars) + const uniqueDeadkeyRules = data_C0_C1.reduce((unique, o) => { + if (!unique.some((obj: { deadkeyed_Ch: any; type_C: any; modifier_key: any; key: any }) => + new TextDecoder().decode(obj.deadkeyed_Ch) === new TextDecoder().decode(o.deadkeyed_Ch) && obj.key === o.key && obj.type_C === o.type_C && obj.modifier_key === o.modifier_key) @@ -1678,18 +1389,20 @@ console.log("unique_counter ",unique_counter ) return unique; }, []); - const uniqueDeadkeys_all_obj = data_ukelele.ArrayOf_Rules.filter((curr) => { - if ((curr.chars !== new TextEncoder().encode("") || curr.chars !== undefined) - && (curr.type_C === "C0") || (curr.type_C === "C1")) { + // console.log("uniqueDeadkeyRules ", uniqueDeadkeyRules) + + const data_C2_C3 = data_ukelele.ArrayOf_Rules.filter((curr) => { + if ((curr.deadkeyed_Ch !== new TextEncoder().encode("") || curr.deadkeyed_Ch !== undefined) + && (curr.type_C === "C2") || (curr.type_C === "C3")) { return curr; } else return "" }); // Also remove duplicates - const uniqueDeadkeys_obj = uniqueDeadkeys_all_obj.reduce((unique, o) => { - if (!unique.some((obj: { chars: any; type_C: any; modifier_key: any; key: any }) => - new TextDecoder().decode(obj.chars) === new TextDecoder().decode(o.chars) + const uniqueDeadkeys_obj_C2_C3 = data_C2_C3.reduce((unique, o) => { + if (!unique.some((obj: { deadkeyed_Ch: any; type_C: any; modifier_key: any; key: any }) => + new TextDecoder().decode(obj.deadkeyed_Ch) === new TextDecoder().decode(o.deadkeyed_Ch) && obj.key === o.key && obj.type_C === o.type_C && obj.modifier_key === o.modifier_key) @@ -1699,38 +1412,56 @@ console.log("unique_counter ",unique_counter ) return unique; }, []); -console.log("uniqueDeadkeys_obj ", uniqueDeadkeys_obj) + let old_c = 0 + //console.log("uniqueDeadkeys_obj_C2_C3 ", uniqueDeadkeys_obj_C2_C3.length, uniqueDeadkeys_obj_C2_C3) + for (let k = 0; k < uniqueDeadkeys_obj_C2_C3.length; k++) { + if (/*(ObjectArray[k].type_C === "C3")||*/(uniqueDeadkeys_obj_C2_C3[k].type_C === "C2")) { + old_c++ + console.log("Obj: k ", k, + "\tType: ", (uniqueDeadkeys_obj_C2_C3[k].type_C !== "" ? uniqueDeadkeys_obj_C2_C3[k].type_C : "--".padEnd(4, " ")), - for (let kkk = 0; kkk < uniqueDeadkeys.length; kkk++) { - // lookup key nr of the key that is being processed + "| modi_prev_dk: ", (uniqueDeadkeys_obj_C2_C3[k].modifier_prev_deadkey !== "" ? uniqueDeadkeys_obj_C2_C3[k].modifier_prev_deadkey.padEnd(23, " ") : "--".padEnd(23, " ")), + "key_prev_dk: ", (uniqueDeadkeys_obj_C2_C3[k].prev_deadkey !== "" ? uniqueDeadkeys_obj_C2_C3[k].prev_deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), + "is_prev dk(): ", (uniqueDeadkeys_obj_C2_C3[k].dk_prev !== 0 ? ("dk_p(" + String(uniqueDeadkeys_obj_C2_C3[k].dk_prev) + ")").padEnd(11, " ") : "--".padEnd(11, " ")), + "| modi_dk: ", (uniqueDeadkeys_obj_C2_C3[k].modifier_deadkey !== "" ? uniqueDeadkeys_obj_C2_C3[k].modifier_deadkey.padEnd(23, " ") : "--".padEnd(23, " ")), + "key_dk: ", (uniqueDeadkeys_obj_C2_C3[k].deadkey !== "" ? uniqueDeadkeys_obj_C2_C3[k].deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), + "is dk(): ", (uniqueDeadkeys_obj_C2_C3[k].dk !== 0 ? ("dk(" + String(uniqueDeadkeys_obj_C2_C3[k].dk) + ")").padEnd(9, " ") : "--".padEnd(9, " ")), + + "| modi: ", (uniqueDeadkeys_obj_C2_C3[k].modifier_key !== "" ? uniqueDeadkeys_obj_C2_C3[k].modifier_key.padEnd(20, " ") : "--".padEnd(20, " ")), + "key: ", (uniqueDeadkeys_obj_C2_C3[k].key !== "" ? uniqueDeadkeys_obj_C2_C3[k].key.padEnd(8, " ") : "--".padEnd(8, " ")), + "ch: ", (new TextDecoder().decode(uniqueDeadkeys_obj_C2_C3[k].deadkeyed_Ch) !== "" ? new TextDecoder().decode(uniqueDeadkeys_obj_C2_C3[k].deadkeyed_Ch).padEnd(10, " ") : "--".padEnd(10, " ")), + + "| °°" + ) + } + } + console.log("old_c ", old_c) + + for (let i = 0; i < uniqueDeadkeyRules.length; i++) { + + // lookup key nr of the key that is being processed let keyNr = 0; - for (let pp = 0; pp < maxkey; pp++) { - if (this.map_UkeleleKC_To_VK(pp) === uniqueDeadkeys[kkk].key) - keyNr = pp + for (let j = 0; j < maxkey; j++) { + if (this.map_UkeleleKC_To_VK(j) === uniqueDeadkeyRules[i].key) + keyNr = j } - // todo wrong output: writes 49 with no K_ and 0 with space ???? // skip keyNr 48 ( TAB ) if (keyNr === 48) continue // add a line after rules of each key - if (uniqueDeadkeys[kkk].key !== keymarker) + if (uniqueDeadkeyRules[i].key !== keymarker) data += '\n' // write rule - - //data += keyNr + "-(modif:" + uniqueDeadkeys[kkk].type_C + "-" + "i" + `) + [` + (uniqueDeadkeys[kkk].modifier_key + ' ' + uniqueDeadkeys[kkk].key).trim() + `] > \'` + new TextDecoder().decode(uniqueDeadkeys[kkk].chars) + '\'\n' - - data += keyNr + "-(modif:"+uniqueDeadkeys_obj[kkk].type_C + "-" + "i" + `) + [` + (uniqueDeadkeys_obj[kkk].modifier_key + ' ' + uniqueDeadkeys_obj[kkk].key).trim() + `] > \'` + new TextDecoder().decode(uniqueDeadkeys_obj[kkk].chars) + '\'\n' - keymarker = uniqueDeadkeys[kkk].key + data += keyNr + "-(modif:" + uniqueDeadkeyRules[i].type_C + "-" + "i" + `) + [` + (uniqueDeadkeyRules[i].modifier_key + ' ' + uniqueDeadkeyRules[i].key).trim() + `] > \'` + new TextDecoder().decode(uniqueDeadkeyRules[i].deadkeyed_Ch) + '\'\n' + keymarker = uniqueDeadkeyRules[i].key } data += '\n' - // console.log("data ", data) - return data } @@ -1762,24 +1493,6 @@ console.log("uniqueDeadkeys_obj ", uniqueDeadkeys_obj) return data } - public create_KMN_Data(data_ukelele: convert_object): string { - - // create an array to work with ................................................ - const workArray2D: any[] = [] - for (let k = 0; k < data_ukelele.ArrayOf_Rules.length; k++) { - workArray2D.push(data_ukelele.ArrayOf_Rules[k]) - } - - let data: string = "" - // add top part of kmn file: STORES - data += this.createData_Stores(data_ukelele) - // add middle part of kmn file: Rules - data += this.createData_Rules(data_ukelele, workArray2D) - // add bottom part of kmn file: DEADKEYS - data += this.createData_Deadkeys(data_ukelele, workArray2D) - - return data - } } @@ -1787,21 +1500,7 @@ class Rules { constructor( public type_C: string, - public modifiers_first: string, - public key_first: string, - - public modifiers_second: string, - public key_second: string, - - public chars: Uint8Array, public isTerminator: boolean, - public dk_hex: string, - public dk_char: Uint8Array, //todo needed? - - public deadkeys: Uint8Array, - public deadkeyables: Uint8Array, - public deadkeyed: Uint8Array, - /* ****************************************** */ public modifier_prev_deadkey: string, public prev_deadkey: string, @@ -1818,10 +1517,5 @@ class Rules { public deadkeyed_Ch: Uint8Array, ) { } -/* - public get_key() { return this.key } - public getval() { - return `blabla ${this.isTerminator} blub: ${this.type_C}...` - }9*/ } From 6311c033a0e1604e23dbe0c8e83bdc7bc3d0970b Mon Sep 17 00:00:00 2001 From: Sabine Date: Fri, 17 Jan 2025 19:50:10 +0100 Subject: [PATCH 042/251] feat(developer): kmc-convert complex multidimensional (C3) rules can be read --- .../keylayout-to-kmn-converter.ts | 421 ++++++++++++++---- 1 file changed, 333 insertions(+), 88 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 1349336a6dd..2cd166290ac 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -126,7 +126,7 @@ function boxArrays_S(source: any) { } export interface rule_object { - type_C: string, /* rule type C0-C4 */ + rule_type: string, /* rule type C0-C4 */ modifiers_first: string, /* string of modifiers for the first key (e.g. "NCAPS RALT CTRL") */ key_first: string, /* name of the first key (e.g. K_U) */ @@ -317,6 +317,7 @@ export class KeylayoutToKmnConverter { public createRuleData(data_ukelele: convert_object, jsonObj: any): convert_object { const ObjectArray: any[] = [] let dk_counter = 0 + let dk_counter_X = 0 // start Tests v ToDo remove...................................... const testArray_Ukelele: string[] = [] @@ -402,7 +403,6 @@ export class KeylayoutToKmnConverter { new TextEncoder().encode(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output']), ) ObjectArray.push(RuleObj) - //console.log("RuleObj shtj ",new TextDecoder().decode(RuleObj.deadkeyed_Ch)=== new TextDecoder().decode(RuleObj.deadkeyed_Ch),l, RuleObj.deadkeyed_Ch, RuleObj.deadkeyed_Ch ) } } } @@ -527,7 +527,6 @@ export class KeylayoutToKmnConverter { let value_next let Key_Block4 let KeyCode_Block2 - //let codeIndexPair_Block4: any[][] let modifier_Block4_fixed: string[] // get a9 in behavior/key @@ -545,39 +544,39 @@ export class KeylayoutToKmnConverter { /* 5: state =3 */ value_state = jsonObj.keyboard.actions.action[actionIdIndex].when[l]['@_state'] /* 5: next =1 */ value_next = jsonObj.keyboard.actions.action[actionIdIndex].when[l]['@_next'] /* 5: StateNextID = a16 */ const StateNextID_Block5 = jsonObj.keyboard.actions.action[actionIdIndex]['@_id'] // get actionId of that state/next pair (14,20) e.g. actionId a57 //my a16 NNNRRR 5 + // ........................................................................ // Data of Block Nr 4 .......................................................... - /* 4: code = 32 */ Key_Block4 = this.get_KeyMap_Code__From__KeyMap_Action(jsonObj, StateNextID_Block5) // find keyNr of that actionID a57> code=37 // my 32 ( K_U) - /* 4: K_U */ //first_key_C3_U8_deadkey = new TextEncoder().encode(this.map_UkeleleKC_To_VK(Number(ContextKeyNr_deadkey))) - /* 4: codeIndexPair=[32 3] */ //codeIndexPair_Block4 = this.get_KeyMap_Code_array__From__ActionID_Action(jsonObj, String(StateNextID_Block5)) - /* 4: MapIndex 3 */ //keymapIndexForactionID = this.lookup_14_ActionName__To__MapIndexSingle(jsonObj, String(theContextID)) - /* [32 3] FIX Arr[1] */ modifier_Block4_fixed = this.get_dataArray__From__KeyMap_Modifier_Index(data_ukelele.ArrayOf_Modifiers, 1) // !! FIXED VALUE HERE!!!! needs to be loop + /* 4: code = 32 */ Key_Block4 = this.get_KeyMap_Code__From__KeyMap_Action(jsonObj, StateNextID_Block5) // find keyNr of that actionID a57> code=37 // my 32 ( K_U) + /* [32 3] FIX Arr[1] */ modifier_Block4_fixed = this.get_data_From__KeyMap_Modifier_Index(data_ukelele.ArrayOf_Modifiers, 1) // !! FIXED VALUE HERE!!!! needs to be loop + // ........................................................................ // Data of Block Nr 3 .......................................................... //must be array ??? - /* 3: actioniD = a17 */ const NoneNextId_Block3 = this.get_ActionID_Id__From__ActionID_next(jsonObj, value_state) + /* 3: actioniD = a17 */ const NoneNextId_Block3 = this.get_ActionID_Id__From__ActionID_next(jsonObj, value_state) // ........................................................................ // Data of Block Nr 2 .......................................................... - /* 2: code = 28 */ KeyCode_Block2 = this.get_KeyMap_Code__From__KeyMap_Action(jsonObj, NoneNextId_Block3) - /* 2: K_8 */ const KeyName_Block2 = this.map_UkeleleKC_To_VK(Number(KeyCode_Block2)) - /* 2 index=3 */ const modifier_Block2 = this.get_KeyMap_Code_array__From__ActionID_Action(jsonObj, String(NoneNextId_Block3)) - /* 2 RALT */ const ModifierElementBlock2 = this.get_dataArray__From__KeyMap_Modifier_Index(data_ukelele.ArrayOf_Modifiers, modifier_Block2[0][1]) + /* 2: code = 28 */ KeyCode_Block2 = this.get_KeyMap_Code__From__KeyMap_Action(jsonObj, NoneNextId_Block3) + /* 2: K_8 */ const KeyName_Block2 = this.map_UkeleleKC_To_VK(Number(KeyCode_Block2)) + /* 2 index=3 */ const modifier_Block2 = this.get_KeyMap_Code_array__From__ActionID_Action(jsonObj, String(NoneNextId_Block3)) + /* 2 RALT */ const ModifierElementBlock2 = this.get_data_From__KeyMap_Modifier_Index(data_ukelele.ArrayOf_Modifiers, modifier_Block2[0][1]) // ........................................................................ // Data of Block Nr 6 .......................................................... - /* 6: [ 'a9', '1', 'â' ] */ const state_Block6_all = this.get_ActionID_Output_array__From__ActionID_State(jsonObj, value_next) - /* 6: output = â FIX */ const output_Block6_fixed = this.get_ActionID_Output__From__ActionID_State(jsonObj, value_next, state_Block6_all[1][0]) + /* 6: [ 'a9', '1', 'â' ] */ const state_Block6_all = this.get_ActionID_Output_array__From__ActionID_State(jsonObj, value_next) + /* 6: output = â FIX */ const output_Block6_fixed = this.get_ActionID_Output__From__ActionID_State(jsonObj, value_next, state_Block6_all[1][0]) + // ........................................................................ for (let a = 0; a < state_Block6_all.length; a++) { // Data of Block Nr 1 .......................................................... - // todo get all state1´s - /* 2: code = 0 */ const keycode_Block1 = this.get_KeyMap_Code__From__KeyMap_Action(jsonObj, state_Block6_all[a][0]) - /* 2: K_A */ const keyname_Block1 = this.map_UkeleleKC_To_VK(Number(keycode_Block1)) + /* 2: code = 0 */ const keycode_Block1 = this.get_KeyMap_Code__From__KeyMap_Action(jsonObj, state_Block6_all[a][0]) + /* 2: K_A */ const keyname_Block1 = this.map_UkeleleKC_To_VK(Number(keycode_Block1)) + // ........................................................................ // a16 has state @@ -588,7 +587,7 @@ export class KeylayoutToKmnConverter { for (let kk = 0; kk < ModifierElementBlock2.length; kk++) { - const modifierText = this.get_dataArray__From__KeyMap_Modifier_Index(data_ukelele.ArrayOf_Modifiers, Number(modif[jj][0])) + const modifierText = this.get_data_From__KeyMap_Modifier_Index(data_ukelele.ArrayOf_Modifiers, Number(modif[jj][0])) const modiflat = modifierText.flat() const modi = this.create_kmn_modifier(modiflat[0], isCapsused) @@ -614,6 +613,88 @@ export class KeylayoutToKmnConverter { } } } + + // testobject CX for all combin************************************************************************** + // testobject CX for all combin************************************************************************** + // testobject CX for all combin************************************************************************** + // testobject CX for all combin************************************************************************** + // testobject CX for all combin************************************************************************** + + // Data of Block Nr 5 .......................................................... + /* eg: state = 3 */ const b5_value_state = jsonObj.keyboard.actions.action[actionIdIndex].when[l]['@_state'] + /* eg: next = 1 */ const b5_value_next = jsonObj.keyboard.actions.action[actionIdIndex].when[l]['@_next'] + /* eg: StateNextID = a16 */ const b5_actionId = jsonObj.keyboard.actions.action[actionIdIndex]['@_id'] + // ............................................................................. + + // Data of Block Nr 4 .......................................................... + /* eg: [ '6', '31', '32' ]*/ const b4_code_arr = this.get_KeyMap_Code_array__From__KeyMap_Action(jsonObj, b5_actionId) + /* eg: 0 */ const b4_behaviourId = this.get_KeyMap_Index__From__KeyMap_Action(jsonObj, b5_actionId) + /* eg: ['CAPS', 'RALT'] */ const b4_modifier_arr = this.get_data_From__KeyMap_Modifier_Index(data_ukelele.ArrayOf_Modifiers, b4_behaviourId) + // ............................................................................. + + // Data of Block Nr 3 .......................................................... + /* eg: actioniD = a17 */ const b3_actionId = this.get_ActionID_Id__From__ActionID_next(jsonObj, b5_value_state) + // ............................................................................. + + // Data of Block Nr 2 .......................................................... + /* eg: ['K_8', 'K_M] */ const b2_keyname_arr = this.get_KecCode_arr__From__ActionId(jsonObj, b3_actionId) + /* eg: index=3 */ const b2_keyBehaviour_arr = this.get_KeyMap_Code_array__From__ActionID_Action(jsonObj, String(b3_actionId)) + /* e.g. [[ '0','1shift? caps?']]*/ const b2_modifier_arr_all = this.get_KeyMap_Modifier_array__From__behaviour_arr(data_ukelele.ArrayOf_Modifiers, b2_keyBehaviour_arr) + // ............................................................................. + + // Data of Block Nr 6 .......................................................... + /* eg: [ 'a9','1','â'] */ const b6_actionId_arr = this.get_ActionID_Output_array__From__ActionID_State(jsonObj, b5_value_next) + // ............................................................................. + + // Data of Block Nr 1 .......................................................... + /* eg: ['49','K_SPACE','a0','0'] */ const b1_keycode_arr = this.get_KeyMap_Code_array__From__KeyMap_Action_array2D(jsonObj, b6_actionId_arr) + // ............................................................................. + + for (let n1 = 0; n1 < b6_actionId_arr.length; n1++) { + for (let n2 = 0; n2 < b1_keycode_arr.length; n2++) { + if (b6_actionId_arr[n1][0] === b1_keycode_arr[n2][2]) { + for (let n3 = 0; n3 < data_ukelele.ArrayOf_Modifiers[Number(b1_keycode_arr[n2][3])].length; n3++) { + for (let n4 = 0; n4 < b4_modifier_arr.length; n4++) { + for (let x5 = 0; x5 < b2_modifier_arr_all.length; x5++) { + for (let n6 = 0; n6 < b2_modifier_arr_all[x5].length; n6++) { + for (let n7 = 0; n7 < b4_code_arr.length; n7++) { + for (let n8 = 0; n8 < b2_keyname_arr.length; n8++) { + + RuleObj = new Rules( + /* OK rule_type */ "CX", + /* OK isTerminator */ false, + + /* OK modifier_prev_deadkey*/ b2_modifier_arr_all[x5][n6], + /* OK prev_deadkey */ b2_keyname_arr[n8], + /* prev_deadkeys_Ch*/ new TextEncoder().encode(""), + /* OK dk_prev */ dk_counter_X++, + + /* OK modifier_deadkey */ b4_modifier_arr[n4], + /* OK deadkey */ this.map_UkeleleKC_To_VK(Number(b4_code_arr[n7])), + /* deadkeys_Ch */ new TextEncoder().encode(""), + /* OK dk*/ dk_counter_X++, + + /* OK modifier_key*/ data_ukelele.ArrayOf_Modifiers[Number(b1_keycode_arr[n2][3])][n3], + /* OK key */ b1_keycode_arr[n2][1], + /* OK deadkeyed_Ch */ new TextEncoder().encode(b6_actionId_arr[n1][2]) + ) + ObjectArray.push(RuleObj) + } + } + } + } + } + } + } + } + } + + + // testobject CX for all combin************************************************************************** + // testobject CX for all combin************************************************************************** + // testobject CX for all combin************************************************************************** + // testobject CX for all combin************************************************************************** + // testobject CX for all combin************************************************************************** } } // ...................................................................................................... @@ -671,26 +752,25 @@ export class KeylayoutToKmnConverter { let old_counter = 0 console.log("start check ", ObjectArray.length) - console.log("ObjectArray ", ObjectArray.length) for (let k = 0; k < ObjectArray.length; k++) { - if (/*(ObjectArray[k].type_C === "C3")||*/(ObjectArray[k].type_C === "C2")) { + if (/*(ObjectArray[k].rule_type === "C3")||*/(ObjectArray[k].rule_type === "CX")) { old_counter++ - console.log("Obj: k ", k, - "\tType: ", (ObjectArray[k].type_C !== "" ? ObjectArray[k].type_C : "--".padEnd(4, " ")), + console.log("2Obj: k ", k, + "\tType: ", (ObjectArray[k].rule_type !== "" ? ObjectArray[k].rule_type : "--".padEnd(4, " ")), /* previous dk*/ - "| modi_prev_dk: ", (ObjectArray[k].modifier_prev_deadkey !== "" ? ObjectArray[k].modifier_prev_deadkey.padEnd(23, " ") : "--".padEnd(23, " ")), + "| modi_prev_dk: ", (ObjectArray[k].modifier_prev_deadkey !== "" ? ObjectArray[k].modifier_prev_deadkey.padEnd(33, " ") : "--".padEnd(33, " ")), "key_prev_dk: ", (ObjectArray[k].prev_deadkey !== "" ? ObjectArray[k].prev_deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), "is_prev dk(): ", (ObjectArray[k].dk_prev !== 0 ? ("dk_p(" + String(ObjectArray[k].dk_prev) + ")").padEnd(11, " ") : "--".padEnd(11, " ")), /* dk*/ - "| modi_dk: ", (ObjectArray[k].modifier_deadkey !== "" ? ObjectArray[k].modifier_deadkey.padEnd(23, " ") : "--".padEnd(23, " ")), + "| modi_dk: ", (ObjectArray[k].modifier_deadkey !== "" ? ObjectArray[k].modifier_deadkey.padEnd(30, " ") : "--".padEnd(30, " ")), "key_dk: ", (ObjectArray[k].deadkey !== "" ? ObjectArray[k].deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), "is dk(): ", (ObjectArray[k].dk !== 0 ? ("dk(" + String(ObjectArray[k].dk) + ")").padEnd(9, " ") : "--".padEnd(9, " ")), /* key*/ - "| modi: ", (ObjectArray[k].modifier_key !== "" ? ObjectArray[k].modifier_key.padEnd(20, " ") : "--".padEnd(20, " ")), + "| modi: ", (ObjectArray[k].modifier_key !== "" ? ObjectArray[k].modifier_key.padEnd(40, " ") : "--".padEnd(40, " ")), "key: ", (ObjectArray[k].key !== "" ? ObjectArray[k].key.padEnd(8, " ") : "--".padEnd(8, " ")), "ch: ", (new TextDecoder().decode(ObjectArray[k].deadkeyed_Ch) !== "" ? new TextDecoder().decode(ObjectArray[k].deadkeyed_Ch).padEnd(10, " ") : "--".padEnd(10, " ")), @@ -766,18 +846,21 @@ export class KeylayoutToKmnConverter { } return "" } - public get_ActionID_Id_array__From__ActionID_next(data: any, search: string): string[] { - const returnarray: string[] = [] + public get_ActionID_Id_array__From__ActionID_next(data: any, search: string): string[][] { + const returnarray2D: string[][] = [] if (search !== "none") { for (let i = 0; i < data.keyboard.actions.action.length; i++) { + const returnarray: string[] = [] for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { if (data.keyboard.actions.action[i].when[j]['@_next'] === search) { returnarray.push(data.keyboard.actions.action[i]['@_id']) } } + if (returnarray.length > 0) + returnarray2D.push(returnarray) } } - return returnarray + return returnarray2D } public get_ActionID_Id__From__ActionID_next(data: any, search: string): string { if (search !== "none") { @@ -885,6 +968,130 @@ export class KeylayoutToKmnConverter { } return -1 } + public get_KecCode_arr__From__ActionId(data: any, search: string): string[] { + const returnarray: string[] = [] + for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { + for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { + if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { + returnarray.push(this.map_UkeleleKC_To_VK(Number(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']))) + } + } + } + return returnarray + } + + + + public get_KeyMap_Code_array__From__KeyMap_Action(data: any, search: string[]): string[] { + const returnarray: string[] = [] + for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { + for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { + if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { + returnarray.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']) + } + } + } + return returnarray + } + + public get_KeyMap_Code_array__From__KeyMap_Action_array2D(data: any, search: string[][]): string[][] { + const returnarray2D: string[][] = [] + for (let k = 0; k < search.length; k++) { + for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { + for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { + const returnarray: string[] = [] + if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search[k][0]) { + returnarray.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']) + returnarray.push(this.map_UkeleleKC_To_VK(Number(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']))) + returnarray.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action']) + returnarray.push(data.keyboard.keyMapSet[0].keyMap[i]['@_index']) + } + if (returnarray.length > 0) + returnarray2D.push(returnarray) + } + } + } + return returnarray2D + } + public get_ActionID_Output__From__ActionID_IdState(data: any, search_id: string, search_state: string): Uint8Array { + for (let i = 0; i < data.keyboard.actions.action.length; i++) { + for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { + if ((data.keyboard.actions.action[i]['@_id'] === search_id) && + (data.keyboard.actions.action[i].when[j]['@_state'] === search_state)) { + return new TextEncoder().encode(data.keyboard.actions.action[i].when[j]['@_output']) + } + } + } + return new TextEncoder().encode("") + } + + + public get_ActionID_Keyt__From__ActionID_IdState(data: any, search_id: string, search_state: string): Uint8Array { + for (let i = 0; i < data.keyboard.actions.action.length; i++) { + for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { + if ((data.keyboard.actions.action[i]['@_id'] === search_id) && + (data.keyboard.actions.action[i].when[j]['@_state'] === search_state)) { + return new TextEncoder().encode(data.keyboard.actions.action[i].when[j]['@_output']) + } + } + } + return new TextEncoder().encode("") + } + + public get_KeyMap_Code_array__From__KeyMap_Action_array(data: any, search: string[][]): string[] { + const returnarray: string[] = [] + for (let k = 0; k < search.length; k++) { + for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { + for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { + if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search[k][0]) { + returnarray.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']) + } + } + } + } + return returnarray + } + + public get_KeyMap_Keymaparray__From__KeyMap_Code_array(data: any, search: string[]): string[][] { + const returnarray: string[][] = [] + for (let k = 0; k < search.length; k++) { + const returnarray1D: string[] = [] + for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { + for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { + if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'] === search[k]) { + returnarray1D.push(search[k]) + returnarray1D.push(data.keyboard.keyMapSet[0].keyMap[i]['@_index']) + } + } + } + returnarray.push(returnarray1D) + } + return returnarray + } + public get_KeyMap_Keymaparray__From__KeyMap_Action(data: any, search: string): string[] { + const returnarray: string[] = [] + for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { + for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { + if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { + returnarray.push(data.keyboard.keyMapSet[0].keyMap[i]['@_index']) + } + } + } + return returnarray + } + + public map_UkeleleKC_To_VK_array(search: string[]): string[] { + const returnarray: string[] = [] + + + for (let i = 0; i < search.length; i++) { + returnarray.push(this.map_UkeleleKC_To_VK(Number(search[i]))) + } + + + return returnarray + } + public get_ActionID_Id__From__ActionID_Next(data: any, search: string) { for (let i = 0; i < data.keyboard.actions.action.length; i++) { for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { @@ -911,6 +1118,28 @@ export class KeylayoutToKmnConverter { } return mapIndexArray_max } + public get_KeyMap_Modifier_array__From__behaviour_arr(data: any, search: number[][]): string[] { + const mapIndexArray_max: string[] = [] + for (let j = 0; j < search.length; j++) { + mapIndexArray_max.push(data[search[j][1]]) + } + return mapIndexArray_max + } + + + public get_Modifier_Text__From__Modifier_Index(data: any, search: string): string[] { + const mapIndexArray_max: string[] = [] + const mapIndexArrayperKey: string[] = [] + for (let j = 0; j < data[search].length; j++) { + mapIndexArrayperKey.push((data[search][j])) + } + for (let j = 0; j < data[search].length; j++) { + mapIndexArray_max.push(data[search][j]) + } + return mapIndexArray_max + } + + public get_KeyMap_Code__From__ActionID_Action(data: any, search: string): number { const mapIndexArray_max: number[][] = [] for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { @@ -927,6 +1156,24 @@ export class KeylayoutToKmnConverter { } return mapIndexArray_max[0][1] } + + + public get_KeyMap_Code__From__ActionID_Action2(data: any, search: string): number { + const mapIndexArray_max: number[][] = [] + for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { + for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { + const mapIndexArrayperKey: number[] = [] + + if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { + mapIndexArrayperKey.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']) + mapIndexArrayperKey.push(i) + } + if (mapIndexArrayperKey.length > 0) + mapIndexArray_max.push(mapIndexArrayperKey) + } + } + return mapIndexArray_max[0][1] + } public get_ActionID_Next__From__ActionID_Id(data: any, search: string): string { for (let i = 0; i < data.keyboard.actions.action.length; i++) { if ((data.keyboard.actions.action[i]['@_id'] === search)) @@ -961,6 +1208,24 @@ export class KeylayoutToKmnConverter { } return returnarray2D } + public get_KeyMap_ModiIndex_array__From__KeyMap_Action(data: any, search_code: string, search_action: string): string[][] { + const returnarray2D: string[][] = [] + for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { + for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { + const returnarray: string[] = [] + if ((data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search_action) && + (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'] === search_code)) { + returnarray.push(data.keyboard.keyMapSet[0].keyMap[i]['@_index']) + returnarray.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']) + returnarray.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action']) + } + if (returnarray.length > 0) { + returnarray2D.push(returnarray) + } + } + } + return returnarray2D + } public get_ActionID_Output__From__ActionID_State(data: any, search: string, nextval: string): string { for (let i = 0; i < data.keyboard.actions.action.length; i++) { for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { @@ -971,13 +1236,29 @@ export class KeylayoutToKmnConverter { } return "" } + + + + + + + public get_KeyMap_Modifier_aray__From__KeyMap_Index(data: any, search: number): string[] { return data.ArrayOf_Modifiers[search] } - public get_dataArray__From__KeyMap_Modifier_Index(data: any, search: number): string[] { + public get_data_From__KeyMap_Modifier_Index(data: any, search: number): string[] { return data[search] } + + public get_dataArray2D__From__KeyMap_Modifier_Index(data: any, search: string[]): string[][] { + const returnarray: string[][] = [] + for (let i = 0; i < search.length; i++) { + returnarray.push(data[search[i]]) + } + return returnarray + } + /** * @brief member function to return the unicode value of a character * @param character the value that will converted @@ -1145,10 +1426,10 @@ export class KeylayoutToKmnConverter { // remove duplicates const uniqueDeadkeyRules = DeadkeyRules.reduce((unique, o) => { - if (!unique.some((obj: { deadkeyed_Ch: any; type_C: any; modifier_key: any; key: any }) => + if (!unique.some((obj: { deadkeyed_Ch: any; rule_type: any; modifier_key: any; key: any }) => new TextDecoder().decode(obj.deadkeyed_Ch) === new TextDecoder().decode(o.deadkeyed_Ch) && obj.key === o.key - && obj.type_C === o.type_C + && obj.rule_type === o.rule_type && obj.modifier_key === o.modifier_key) ) { unique.push(o); @@ -1164,9 +1445,9 @@ export class KeylayoutToKmnConverter { //*************************************************************************************************** */ /* How to create rules from keylayout data from data_ukelele.ArrayOf_processed_RuleData: - + There are 6 different types of data entries (C0-C4) in data_ukelele.ArrayOf_processed_RuleData e.g. that contain all data to retrieve deadkeys, deadkeyables and deadkeyed characters: - + C0: (size: 4) ['C0', 'RIGHTSHIFT ', 'K_S', 'S' ] C1: (size: 4) ['C1', 'CAPS', 'K_A', 'A' ], C2: (size: 5) ['C2', 'CAPS', 'K_A', 'K_N', 'Ã' ], use 2.(K_A) and 4.('Ã') to get name and DEADKEYED @@ -1177,7 +1458,7 @@ export class KeylayoutToKmnConverter { To Find a DEADKEY e.g. ^ 1) look in modifier_C4 with 'isTerminator' included (n = 7) 2) get 7th entry ===> DEADKEY (e.g. 02DC) - + To Find a DEADKEYABLE ( a character that can be converted to a deadkey e.g. A (-> Ã) ): 1) C1 CAPS K_A A 2) C2 CAPS K_A K_N Ã @@ -1194,7 +1475,7 @@ export class KeylayoutToKmnConverter { // select only lines for deadkeyables ( entries that contain C1, are not K_SPACE and create chars e.g. from 'C1', 'CAPS', 'K_A', 'A' ]) const deadkeyables_raw = data_ukelele.ArrayOf_Rules.filter((curr) => { - if ((curr.type_C === "C1") && (curr.key !== "K_SPACE") && (new TextDecoder().decode(curr.deadkeyed_Ch) !== "")) { + if ((curr.rule_type === "C1") && (curr.key !== "K_SPACE") && (new TextDecoder().decode(curr.deadkeyed_Ch) !== "")) { return curr; } return "" @@ -1202,9 +1483,9 @@ export class KeylayoutToKmnConverter { // select only lines for deadkeyed ( entries that contain C2, are not K_SPACE and create a deadkeyed) e.g. from ['C2', 'CAPS', 'K_A', 'K_N', 'Ã' ] const deadkeyed_raw_multiple = data_ukelele.ArrayOf_Rules.filter((curr) => { - // if ((curr.type_C === "C2") && (curr.key !== "K_SPACE") && (new TextDecoder().decode(curr.deadkeyed_Ch) !== "")) { - // if ((curr.type_C === "C2") && (curr.key !== "K_SPACE")) { - if ((curr.type_C === "C2")) { + // if ((curr.rule_type === "C2") && (curr.key !== "K_SPACE") && (new TextDecoder().decode(curr.deadkeyed_Ch) !== "")) { + // if ((curr.rule_type === "C2") && (curr.key !== "K_SPACE")) { + if ((curr.rule_type === "C2")) { return curr; } return "" @@ -1212,10 +1493,10 @@ export class KeylayoutToKmnConverter { // remove duplicates const deadkeyed_raw = deadkeyed_raw_multiple.reduce((unique, o) => { - if (!unique.some((obj: { chars: any; type_C: any; modifier_key: any; key: any; deadkeyed_Ch: any }) => + if (!unique.some((obj: { chars: any; rule_type: any; modifier_key: any; key: any; deadkeyed_Ch: any }) => new TextDecoder().decode(obj.deadkeyed_Ch) === new TextDecoder().decode(o.deadkeyed_Ch) && obj.key === o.key - && obj.type_C === o.type_C + && obj.rule_type === o.rule_type && obj.modifier_key === o.modifier_key) ) { unique.push(o); @@ -1253,37 +1534,6 @@ export class KeylayoutToKmnConverter { }, [[], new Set()], ); - // print - for (let i = 0; i < deadkeyables_raw.length; i++) { - console.log("deadkeyables_raw ", i, "\t", - deadkeyables_raw[i].type_C, "--", - deadkeyables_raw[i].modifier_key.padEnd(28, " "), "--", - deadkeyables_raw[i].key.padEnd(10, " "), "--", - new TextDecoder().decode(deadkeyables_raw[i].deadkeyed_Ch), - "°°",) - } - - for (let i = 0; i < deadkeyed_raw.length; i++) { - console.log("deadkeyed_raw ", i, "\t", - deadkeyed_raw[i].type_C, "--", - deadkeyed_raw[i].modifier_key.padEnd(28, " "), "--", - deadkeyed_raw[i].key.padEnd(10, " "), "--", - new TextDecoder().decode(deadkeyed_raw[i].deadkeyed_Ch).padEnd(5, " "), - - deadkeyed_raw[i].modifier_deadkey.padEnd(28, " "), "--", - deadkeyed_raw[i].deadkey.padEnd(10, " "), "--", - new TextDecoder().decode(deadkeyed_raw[i].deadkeys_Ch), "--", - deadkeyed_raw[i].dk, "--xx", - - - new TextDecoder().decode(deadkeyed_raw[i].deadkeys).padEnd(5, " "), "--", - new TextDecoder().decode(deadkeyed_raw[i].deadkeyables).padEnd(5, " "), "--", - new TextDecoder().decode(deadkeyed_raw[i].deadkeyed_Ch).padEnd(5, " "), - - "°°",) - } - //console.log("dk_array_comlpete ", dk_array_comlpete) - //console.log("unique_dk_array_comlpete ", unique_dk_array_comlpete) const deadkeyedElement: string[][] = Array.from({ length: uniqueDeadkeyRules.length }, () => new Array(2).fill('')); const deadkeyablesElement: string[][] = Array.from({ length: uniqueDeadkeyRules.length }, () => new Array(1).fill('')); @@ -1300,8 +1550,6 @@ export class KeylayoutToKmnConverter { deadkeyedElement[i][1] = this.getHexFromChar(new TextDecoder().decode(uniqueDeadkeyRules[i].deadkeyed_Ch)) } } - // console.log("deadkeyedElement ", deadkeyedElement) - // console.log("deadkeyablesElement ", deadkeyablesElement) /*const newAA: string[][] = [] @@ -1365,12 +1613,11 @@ export class KeylayoutToKmnConverter { let data: string = "" let keymarker = "" - //console.log("data_ukelele.ArrayOf_Rules ", data_ukelele.ArrayOf_Rules.length, data_ukelele.ArrayOf_Rules[155].key) // select only lines that contain C0 or C1 and create an output. const data_C0_C1 = data_ukelele.ArrayOf_Rules.filter((curr) => { if ((curr.deadkeyed_Ch !== new TextEncoder().encode("") || curr.deadkeyed_Ch !== undefined) - && (curr.type_C === "C0") || (curr.type_C === "C1")) { + && (curr.rule_type === "C0") || (curr.rule_type === "C1")) { return curr; } else return "" @@ -1378,10 +1625,10 @@ export class KeylayoutToKmnConverter { // Also remove duplicates const uniqueDeadkeyRules = data_C0_C1.reduce((unique, o) => { - if (!unique.some((obj: { deadkeyed_Ch: any; type_C: any; modifier_key: any; key: any }) => + if (!unique.some((obj: { deadkeyed_Ch: any; rule_type: any; modifier_key: any; key: any }) => new TextDecoder().decode(obj.deadkeyed_Ch) === new TextDecoder().decode(o.deadkeyed_Ch) && obj.key === o.key - && obj.type_C === o.type_C + && obj.rule_type === o.rule_type && obj.modifier_key === o.modifier_key) ) { unique.push(o); @@ -1389,11 +1636,10 @@ export class KeylayoutToKmnConverter { return unique; }, []); - // console.log("uniqueDeadkeyRules ", uniqueDeadkeyRules) const data_C2_C3 = data_ukelele.ArrayOf_Rules.filter((curr) => { if ((curr.deadkeyed_Ch !== new TextEncoder().encode("") || curr.deadkeyed_Ch !== undefined) - && (curr.type_C === "C2") || (curr.type_C === "C3")) { + && (curr.rule_type === "CX") || (curr.rule_type === "CX")) { return curr; } else return "" @@ -1401,10 +1647,10 @@ export class KeylayoutToKmnConverter { // Also remove duplicates const uniqueDeadkeys_obj_C2_C3 = data_C2_C3.reduce((unique, o) => { - if (!unique.some((obj: { deadkeyed_Ch: any; type_C: any; modifier_key: any; key: any }) => + if (!unique.some((obj: { deadkeyed_Ch: any; rule_type: any; modifier_key: any; key: any }) => new TextDecoder().decode(obj.deadkeyed_Ch) === new TextDecoder().decode(o.deadkeyed_Ch) && obj.key === o.key - && obj.type_C === o.type_C + && obj.rule_type === o.rule_type && obj.modifier_key === o.modifier_key) ) { unique.push(o); @@ -1413,13 +1659,12 @@ export class KeylayoutToKmnConverter { }, []); let old_c = 0 - //console.log("uniqueDeadkeys_obj_C2_C3 ", uniqueDeadkeys_obj_C2_C3.length, uniqueDeadkeys_obj_C2_C3) for (let k = 0; k < uniqueDeadkeys_obj_C2_C3.length; k++) { - if (/*(ObjectArray[k].type_C === "C3")||*/(uniqueDeadkeys_obj_C2_C3[k].type_C === "C2")) { + if (/*(ObjectArray[k].rule_type === "C3")||*/(uniqueDeadkeys_obj_C2_C3[k].rule_type === "CX")) { old_c++ - console.log("Obj: k ", k, - "\tType: ", (uniqueDeadkeys_obj_C2_C3[k].type_C !== "" ? uniqueDeadkeys_obj_C2_C3[k].type_C : "--".padEnd(4, " ")), + console.log("1Obj: k ", k, + "\tType: ", (uniqueDeadkeys_obj_C2_C3[k].rule_type !== "" ? uniqueDeadkeys_obj_C2_C3[k].rule_type : "--".padEnd(4, " ")), "| modi_prev_dk: ", (uniqueDeadkeys_obj_C2_C3[k].modifier_prev_deadkey !== "" ? uniqueDeadkeys_obj_C2_C3[k].modifier_prev_deadkey.padEnd(23, " ") : "--".padEnd(23, " ")), "key_prev_dk: ", (uniqueDeadkeys_obj_C2_C3[k].prev_deadkey !== "" ? uniqueDeadkeys_obj_C2_C3[k].prev_deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), @@ -1457,7 +1702,7 @@ export class KeylayoutToKmnConverter { data += '\n' // write rule - data += keyNr + "-(modif:" + uniqueDeadkeyRules[i].type_C + "-" + "i" + `) + [` + (uniqueDeadkeyRules[i].modifier_key + ' ' + uniqueDeadkeyRules[i].key).trim() + `] > \'` + new TextDecoder().decode(uniqueDeadkeyRules[i].deadkeyed_Ch) + '\'\n' + data += keyNr + "-(modif:" + uniqueDeadkeyRules[i].rule_type + "-" + "i" + `) + [` + (uniqueDeadkeyRules[i].modifier_key + ' ' + uniqueDeadkeyRules[i].key).trim() + `] > \'` + new TextDecoder().decode(uniqueDeadkeyRules[i].deadkeyed_Ch) + '\'\n' keymarker = uniqueDeadkeyRules[i].key } @@ -1499,7 +1744,7 @@ export class KeylayoutToKmnConverter { class Rules { constructor( - public type_C: string, + public rule_type: string, public isTerminator: boolean, public modifier_prev_deadkey: string, From aeaa66c74adef043ff1b5ece894c2fdc6b57b1f3 Mon Sep 17 00:00:00 2001 From: Sabine Date: Fri, 24 Jan 2025 16:24:54 +0100 Subject: [PATCH 043/251] feat(developer): kmc-convert: produce Warnings for duplicate/ambiguous/altered/unavailable kmn rules --- .../keylayout-to-kmn-converter.ts | 1482 ++++++++++++----- 1 file changed, 1035 insertions(+), 447 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 2cd166290ac..ca488348796 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -47,7 +47,7 @@ import boxXmlArray = util.boxXmlArray;*/ // use length to clear array instead of defining evetry time new (modifierMap_ONE_InKeymapSelect.length=0 // naming of for-loop var i,j,k?... // warning if contrADICTING RULES E:G: [ 'modifier_C0', 'SHIFT NCAPS', 'K_C', 'c'], vs [ 'modifier_C0', 'SHIFT NCAPS', 'K_C', 'C' ], - // print NCAPS as the first of the modifiers in create_kmn_modifier + // OK print NCAPS as the first of the modifiers in create_kmn_modifier // use boxXmlArray from codebase instead of my own // where are rules for action+none ( a, e, u, etc) // order of object member var @@ -104,8 +104,7 @@ if(source?.keyboard3?.AAA) { } */ -// need to specify all elements!!! -// source = jsonObj.keyboard +// todo use from elsewhere function boxArrays_S(source: any) { // parent tag child-tag boxXmlArray_S(source.layouts, 'layout'); @@ -126,37 +125,22 @@ function boxArrays_S(source: any) { } export interface rule_object { - rule_type: string, /* rule type C0-C4 */ - modifiers_first: string, /* string of modifiers for the first key (e.g. "NCAPS RALT CTRL") */ - key_first: string, /* name of the first key (e.g. K_U) */ - - modifiers_second: string, /* string of modifiers for the second key */ - key_second: string, /* name of the second key */ - - chars: Uint8Array, /* the output character */ - isTerminator: boolean, /* is this a terminator rule */ - dk_hex: string, /* deadkey in hex notation (e.g. 00B4 for "´" )*/ - dk_char: Uint8Array, //todo needed?/* */ - - deadkeys: Uint8Array, /* deadkeys to add to a character (e.g. ^,´,`,~ ) */ - deadkeyables: Uint8Array, /* characters that can use a deadkey (e.g. a,e,i,o,u )*/ - deadkeyed: Uint8Array, // deadkeys+deadkeyables (e.g. â,ê,î,ô,û) - - /* ****************************************** */ - - prev_deadkey: string, - modifier_prev_deadkey: string, - prev_deadkeys_Ch: Uint8Array, - dk_prev: number, - - deadkey: string, - modifier_deadkey: string, - deadkeys_Ch: Uint8Array, - dk: number, - - key: string, - modifier_key: string, - deadkeyed_Ch: Uint8Array, + rule_type: string, /* rule type C0-C4 */ + isTerminator: boolean, /* is this a terminator rule */ + + modifier_prev_deadkey: string, /* string of modifiers for the first key (e.g. "NCAPS RALT CTRL") */ + prev_deadkey: string, /* name of the first key (e.g. K_U) */ + prev_deadkeys_Ch: Uint8Array, /* Todo needed?*/ + dk_prev: number, /* Todo needed?*/ + + modifier_deadkey: string, /* string of modifiers for the second key (e.g. "NCAPS RALT CTRL") */ + deadkey: string, /* name of the second key */ + deadkeys_Ch: Uint8Array, /* Todo needed?*/ + dk: number, /* Todo needed?*/ + + modifier_key: string, /* string of modifiers for the third key (e.g. "NCAPS RALT CTRL") */ + key: string, /* name of the third key (e.g. K_U) */ + deadkeyed_Ch: Uint8Array, /* the output character */ }; export interface convert_object { @@ -169,6 +153,9 @@ export class KeylayoutToKmnConverter { static readonly INPUT_FILE_EXTENSION = '.keylayout'; static readonly OUTPUT_FILE_EXTENSION = '.kmn'; + //Todo remove print_draft + static print_draft = true + // TODO use callbacks what about /*private*/ for options //constructor(/*private*/ _callbacks: CompilerCallbacks, /*private*/ _options: CompilerOptions) { constructor(private callbacks: CompilerCallbacks, options: CompilerOptions) { @@ -236,7 +223,7 @@ export class KeylayoutToKmnConverter { attributeNamePrefix: '@_' // to access the attribute }; - + // Todo files/path !!! console.log("xmlFile_name", (process.cwd() + "\\data" + filename.substring(filename.lastIndexOf("\\"))).replace(" ", "")) //const xmlFile = readFileSync(`${process.cwd()}/data/MySample.keylayout`, 'utf8') const xmlFile = readFileSync((process.cwd() + "\\data" + filename.substring(filename.lastIndexOf("\\"))).replace(" ", ""), 'utf8'); @@ -316,8 +303,9 @@ export class KeylayoutToKmnConverter { public createRuleData(data_ukelele: convert_object, jsonObj: any): convert_object { const ObjectArray: any[] = [] - let dk_counter = 0 - let dk_counter_X = 0 + let dk_counter_C3_A = 0 + let dk_counter_C3_B = 0 + let dk_counter_C2 = 0 // start Tests v ToDo remove...................................... const testArray_Ukelele: string[] = [] @@ -326,10 +314,10 @@ export class KeylayoutToKmnConverter { let testArray_Ukelele_action_count = 0 const testArray_kmn: string[] = [] - const testArray_kmn_action: string[] = [] - let testArray_kmn_action1: string[] = [] + // const testArray_kmn_action: string[] = [] + const testArray_kmn_action1: string[] = [] let testArray_kmn_count = 0 - let testArray_kmn_action_count = 0 + // let testArray_kmn_action_count = 0 // loop behaviors ( in ukelele it is possible to define multiple modifier combinations that behave in the same) @@ -397,6 +385,7 @@ export class KeylayoutToKmnConverter { "", new TextEncoder().encode(""), 0, + 0, this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[i][l], isCapsused), this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), @@ -436,6 +425,7 @@ export class KeylayoutToKmnConverter { "", new TextEncoder().encode(""), 0, + 0, this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[i][l], isCapsused), this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), @@ -453,6 +443,7 @@ export class KeylayoutToKmnConverter { // ...............e. g. .................................................... // ...................................................................................................... + /* oldcase C2 let nextVal: string[] = [] // find the nth action id e.g. id a9 ->id nr 20 @@ -496,13 +487,13 @@ export class KeylayoutToKmnConverter { this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[KeymapIndex][zz], isCapsused), this.map_UkeleleKC_To_VK(Number(this.get_KeyMap_Code__From__KeyMap_Action(jsonObj, nextVal[k]))), new TextEncoder().encode(""), - dk_counter++, + 0, + dk_counter_C2++, this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[i][l], isCapsused), this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), new TextEncoder().encode(jsonObj.keyboard.actions.action[indexOfActions].when[jj]['@_output']) ) - ObjectArray.push(RuleObj) } } @@ -510,9 +501,10 @@ export class KeylayoutToKmnConverter { } } } + */ // ...................................................................................................... - // case C3: action + state Nr + Next .................................................................... + // case C2 NEW : action + state Nr + Next .................................................................... // ...............e. g. ..................................................... // replace state x with all rules that result in 14 ( KeyMap:action -> keyMap:code (key) ...................................................... // ...................................................................................................... - let value_state - let value_next - let Key_Block4 - let KeyCode_Block2 - let modifier_Block4_fixed: string[] // get a9 in behavior/key action_id = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] - const actionIdIndex = this.get_ActionID_Index__From__ActionID_Id(jsonObj, action_id) + const actionIdIndexC2 = this.get_ActionID_Index__From__ActionID_Id(jsonObj, action_id) // loop all action-when and find state-next-pair - for (let l = 0; l < jsonObj.keyboard.actions.action[actionIdIndex].when.length; l++) { + for (let l = 0; l < jsonObj.keyboard.actions.action[actionIdIndexC2].when.length; l++) { + + // state_none data + if ((jsonObj.keyboard.actions.action[actionIdIndexC2].when[l]['@_state'] === "none") + && (jsonObj.keyboard.actions.action[actionIdIndexC2].when[l]['@_next'] !== undefined)) { - // state_next data - if ((jsonObj.keyboard.actions.action[actionIdIndex].when[l]['@_state'] !== "none") - && (jsonObj.keyboard.actions.action[actionIdIndex].when[l]['@_next'] !== undefined)) { // Data of Block Nr 5 .......................................................... - /* 5: state =3 */ value_state = jsonObj.keyboard.actions.action[actionIdIndex].when[l]['@_state'] - /* 5: next =1 */ value_next = jsonObj.keyboard.actions.action[actionIdIndex].when[l]['@_next'] - /* 5: StateNextID = a16 */ const StateNextID_Block5 = jsonObj.keyboard.actions.action[actionIdIndex]['@_id'] // get actionId of that state/next pair (14,20) e.g. actionId a57 //my a16 NNNRRR 5 + /* eg: state = 3 */ // const b5_value_state = jsonObj.keyboard.actions.action[actionIdIndexC2].when[l]['@_state'] + /* eg: next = 1 */ const b5_value_next = jsonObj.keyboard.actions.action[actionIdIndexC2].when[l]['@_next'] + /* eg: StateNextID = a16 */ const b5_actionId = jsonObj.keyboard.actions.action[actionIdIndexC2]['@_id'] + // ............................................................................. +console.log(" action_id", action_id) - // ........................................................................ + console.log("b5_value_next ",b5_value_next ) +console.log(" b5_actionId", b5_actionId) // Data of Block Nr 4 .......................................................... - /* 4: code = 32 */ Key_Block4 = this.get_KeyMap_Code__From__KeyMap_Action(jsonObj, StateNextID_Block5) // find keyNr of that actionID a57> code=37 // my 32 ( K_U) - /* [32 3] FIX Arr[1] */ modifier_Block4_fixed = this.get_data_From__KeyMap_Modifier_Index(data_ukelele.ArrayOf_Modifiers, 1) // !! FIXED VALUE HERE!!!! needs to be loop - - // ........................................................................ + /* eg: [ '6', '31', '32' ]*/ const b4_code_arr = this.get_KeyMap_Code_array__From__KeyMap_Action(jsonObj, b5_actionId) + /* eg: 0 */ const b4_behaviourId = this.get_KeyMap_Index__From__KeyMap_Action(jsonObj, b5_actionId) + /* eg: ['CAPS', 'RALT'] */ const b4_modifier_arr = this.get_data_From__KeyMap_Modifier_Index(data_ukelele.ArrayOf_Modifiers, b4_behaviourId) + // ............................................................................. // Data of Block Nr 3 .......................................................... - //must be array ??? - /* 3: actioniD = a17 */ const NoneNextId_Block3 = this.get_ActionID_Id__From__ActionID_next(jsonObj, value_state) - // ........................................................................ + /* eg: actioniD = a17 */ //const b3_actionId = this.get_ActionID_Id__From__ActionID_next(jsonObj, b5_value_state) + // ............................................................................. // Data of Block Nr 2 .......................................................... - /* 2: code = 28 */ KeyCode_Block2 = this.get_KeyMap_Code__From__KeyMap_Action(jsonObj, NoneNextId_Block3) - /* 2: K_8 */ const KeyName_Block2 = this.map_UkeleleKC_To_VK(Number(KeyCode_Block2)) - /* 2 index=3 */ const modifier_Block2 = this.get_KeyMap_Code_array__From__ActionID_Action(jsonObj, String(NoneNextId_Block3)) - /* 2 RALT */ const ModifierElementBlock2 = this.get_data_From__KeyMap_Modifier_Index(data_ukelele.ArrayOf_Modifiers, modifier_Block2[0][1]) - // ........................................................................ + /* eg: ['K_8', 'K_M] */ //const b2_keyname_arr = this.get_KecCode_arr__From__ActionId(jsonObj, b3_actionId) + /* eg: index=3 */ // const b2_keyBehaviour_arr = this.get_KeyMap_Code_array__From__ActionID_Action(jsonObj, String(b3_actionId)) + /* e.g. [[ '0','1shift? caps?']]*/ // const b2_modifier_arr_all = this.get_KeyMap_Modifier_array__From__behaviour_arr(data_ukelele.ArrayOf_Modifiers, b2_keyBehaviour_arr) + // ............................................................................. // Data of Block Nr 6 .......................................................... - /* 6: [ 'a9', '1', 'â' ] */ const state_Block6_all = this.get_ActionID_Output_array__From__ActionID_State(jsonObj, value_next) - /* 6: output = â FIX */ const output_Block6_fixed = this.get_ActionID_Output__From__ActionID_State(jsonObj, value_next, state_Block6_all[1][0]) - - // ........................................................................ - - for (let a = 0; a < state_Block6_all.length; a++) { - - // Data of Block Nr 1 .......................................................... - /* 2: code = 0 */ const keycode_Block1 = this.get_KeyMap_Code__From__KeyMap_Action(jsonObj, state_Block6_all[a][0]) - /* 2: K_A */ const keyname_Block1 = this.map_UkeleleKC_To_VK(Number(keycode_Block1)) - - // ........................................................................ - - // a16 has state - // field 1: which code has action a0 or a9 or... - const modif = this.get_KeyMap_IndexCodeAction_array__From__KeyMap_Action(jsonObj, state_Block6_all[a][0], keycode_Block1) - - for (let jj = 0; jj < modif.length; jj++) { + /* eg: [ 'a9','1','â'] */ const b6_actionId_arr = this.get_ActionID_Output_array__From__ActionID_State(jsonObj, b5_value_next) + // ............................................................................. - for (let kk = 0; kk < ModifierElementBlock2.length; kk++) { + // Data of Block Nr 1 .......................................................... + /* eg: ['49','K_SPACE','a0','0'] */ const b1_keycode_arr = this.get_KeyMap_Code_array__From__KeyMap_Action_array2D(jsonObj, b6_actionId_arr) + // ............................................................................. - const modifierText = this.get_data_From__KeyMap_Modifier_Index(data_ukelele.ArrayOf_Modifiers, Number(modif[jj][0])) - const modiflat = modifierText.flat() - const modi = this.create_kmn_modifier(modiflat[0], isCapsused) + for (let n1 = 0; n1 < b6_actionId_arr.length; n1++) { + for (let n2 = 0; n2 < b1_keycode_arr.length; n2++) { + if (b6_actionId_arr[n1][0] === b1_keycode_arr[n2][2]) { + for (let n3 = 0; n3 < data_ukelele.ArrayOf_Modifiers[Number(b1_keycode_arr[n2][3])].length; n3++) { + for (let n4 = 0; n4 < b4_modifier_arr.length; n4++) { + // for (let x5 = 0; x5 < b2_modifier_arr_all.length; x5++) { + // for (let n6 = 0; n6 < b2_modifier_arr_all[x5].length; n6++) { + for (let n7 = 0; n7 < b4_code_arr.length; n7++) { + // for (let n8 = 0; n8 < b2_keyname_arr.length; n8++) { - RuleObj = new Rules( - "C3", - false, + RuleObj = new Rules( + /* OK rule_type */ "C2", + /* OK isTerminator */ false, - this.create_kmn_modifier(ModifierElementBlock2[kk], isCapsused), - KeyName_Block2, - new TextEncoder().encode(""), - dk_counter++, + /* OK modifier_prev_deadkey*/ "", + /* OK prev_deadkey */ "", + /* prev_deadkeys_Ch*/ new TextEncoder().encode(""), + /* OK dk_prev */ 0, - this.create_kmn_modifier(modifier_Block4_fixed[0], isCapsused), - this.map_UkeleleKC_To_VK(Number(Key_Block4)), - new TextEncoder().encode(""), - dk_counter++, + /* OK modifier_deadkey */ b4_modifier_arr[n4], + /* OK deadkey */ this.map_UkeleleKC_To_VK(Number(b4_code_arr[n7])), + /* deadkeys_Ch */ new TextEncoder().encode(""), + /* OK dk*/ dk_counter_C2++, + /* OK dk for C2*/ 0, - modi, - keyname_Block1, - new TextEncoder().encode(output_Block6_fixed), - ) - ObjectArray.push(RuleObj) + /* OK modifier_key*/ data_ukelele.ArrayOf_Modifiers[Number(b1_keycode_arr[n2][3])][n3], + /* OK key */ b1_keycode_arr[n2][1], + /* OK deadkeyed_Ch */ new TextEncoder().encode(b6_actionId_arr[n1][2]) + ) + ObjectArray.push(RuleObj) + } + } + // } + // } + // } + } } } } + } + } + // ...................................................................................................... + // case C3: action + state Nr + Next .................................................................... + // ...............e. g. ..................................................... + // replace state x with all rules that result in 14 (action->action(state)->action(next)->terminator(output) ........................................ + // Action:state -> Action:state -> Action:id -> KeyMap:action -> keyMap:code (first dk) ................. + // Action:id -> KeyMap:action -> keyMap:code (second dk) ................................................ + // Action:next -> Action:state -> action:output ......................................................... + // Action:id -> KeyMap:action -> keyMap:code (key) ...................................................... + // ...................................................................................................... + + // get a9 in behavior/key + action_id = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] + const actionIdIndex = this.get_ActionID_Index__From__ActionID_Id(jsonObj, action_id) + + // loop all action-when and find state-next-pair + for (let l = 0; l < jsonObj.keyboard.actions.action[actionIdIndex].when.length; l++) { - // testobject CX for all combin************************************************************************** - // testobject CX for all combin************************************************************************** - // testobject CX for all combin************************************************************************** - // testobject CX for all combin************************************************************************** - // testobject CX for all combin************************************************************************** + // state_next data + if ((jsonObj.keyboard.actions.action[actionIdIndex].when[l]['@_state'] !== "none") + && (jsonObj.keyboard.actions.action[actionIdIndex].when[l]['@_next'] !== undefined)) { // Data of Block Nr 5 .......................................................... /* eg: state = 3 */ const b5_value_state = jsonObj.keyboard.actions.action[actionIdIndex].when[l]['@_state'] @@ -661,18 +667,19 @@ export class KeylayoutToKmnConverter { for (let n8 = 0; n8 < b2_keyname_arr.length; n8++) { RuleObj = new Rules( - /* OK rule_type */ "CX", + /* OK rule_type */ "C3", /* OK isTerminator */ false, /* OK modifier_prev_deadkey*/ b2_modifier_arr_all[x5][n6], /* OK prev_deadkey */ b2_keyname_arr[n8], /* prev_deadkeys_Ch*/ new TextEncoder().encode(""), - /* OK dk_prev */ dk_counter_X++, + /* OK dk_prev */ dk_counter_C3_A++, /* OK modifier_deadkey */ b4_modifier_arr[n4], /* OK deadkey */ this.map_UkeleleKC_To_VK(Number(b4_code_arr[n7])), /* deadkeys_Ch */ new TextEncoder().encode(""), - /* OK dk*/ dk_counter_X++, + /* OK dk*/ dk_counter_C3_B++, + /* OK dk for C2*/ 0, /* OK modifier_key*/ data_ukelele.ArrayOf_Modifiers[Number(b1_keycode_arr[n2][3])][n3], /* OK key */ b1_keycode_arr[n2][1], @@ -688,13 +695,6 @@ export class KeylayoutToKmnConverter { } } } - - - // testobject CX for all combin************************************************************************** - // testobject CX for all combin************************************************************************** - // testobject CX for all combin************************************************************************** - // testobject CX for all combin************************************************************************** - // testobject CX for all combin************************************************************************** } } // ...................................................................................................... @@ -727,6 +727,7 @@ export class KeylayoutToKmnConverter { "", new TextEncoder().encode(""), 0, + 0, this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[i][l], isCapsused), this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), @@ -749,38 +750,6 @@ export class KeylayoutToKmnConverter { //--------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------- - let old_counter = 0 - console.log("start check ", ObjectArray.length) - - for (let k = 0; k < ObjectArray.length; k++) { - - if (/*(ObjectArray[k].rule_type === "C3")||*/(ObjectArray[k].rule_type === "CX")) { - old_counter++ - console.log("2Obj: k ", k, - "\tType: ", (ObjectArray[k].rule_type !== "" ? ObjectArray[k].rule_type : "--".padEnd(4, " ")), - - /* previous dk*/ - "| modi_prev_dk: ", (ObjectArray[k].modifier_prev_deadkey !== "" ? ObjectArray[k].modifier_prev_deadkey.padEnd(33, " ") : "--".padEnd(33, " ")), - "key_prev_dk: ", (ObjectArray[k].prev_deadkey !== "" ? ObjectArray[k].prev_deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), - "is_prev dk(): ", (ObjectArray[k].dk_prev !== 0 ? ("dk_p(" + String(ObjectArray[k].dk_prev) + ")").padEnd(11, " ") : "--".padEnd(11, " ")), - - /* dk*/ - "| modi_dk: ", (ObjectArray[k].modifier_deadkey !== "" ? ObjectArray[k].modifier_deadkey.padEnd(30, " ") : "--".padEnd(30, " ")), - "key_dk: ", (ObjectArray[k].deadkey !== "" ? ObjectArray[k].deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), - "is dk(): ", (ObjectArray[k].dk !== 0 ? ("dk(" + String(ObjectArray[k].dk) + ")").padEnd(9, " ") : "--".padEnd(9, " ")), - - /* key*/ - "| modi: ", (ObjectArray[k].modifier_key !== "" ? ObjectArray[k].modifier_key.padEnd(40, " ") : "--".padEnd(40, " ")), - "key: ", (ObjectArray[k].key !== "" ? ObjectArray[k].key.padEnd(8, " ") : "--".padEnd(8, " ")), - "ch: ", (new TextDecoder().decode(ObjectArray[k].deadkeyed_Ch) !== "" ? new TextDecoder().decode(ObjectArray[k].deadkeyed_Ch).padEnd(10, " ") : "--".padEnd(10, " ")), - - "| °°" - ) - } - } - console.log("old_counter ", old_counter) - - //remove entries that are available in both arrays for (let i = 0; i < (testArray_Ukelele.length); i++) { for (let j = 0; j < (testArray_kmn.length); j++) { @@ -823,6 +792,107 @@ export class KeylayoutToKmnConverter { else console.log("OOOOHHHH DIFFERENT AMOUNTS ") + + + // test modifiers + + if (this.create_kmn_modifier("", true) === "NCAPS") console.log("testNr 1 OK "); else console.log("testNr 1 NOT OK - ", (this.create_kmn_modifier("", true))) + if (this.create_kmn_modifier("", false) === "") console.log("testNr 2 OK "); else console.log("testNr 2 NOT OK - ", (this.create_kmn_modifier("", false))) + if (this.create_kmn_modifier("caps", true) === "CAPS") console.log("testNr 5 OK "); else console.log("testNr 5 NOT OK - ", (this.create_kmn_modifier("caps", true))) + if (this.create_kmn_modifier("6caps", true) === "CAPS") console.log("testNr 6 OK "); else console.log("testNr 6 NOT OK - ", (this.create_kmn_modifier("6caps", true))) + if (this.create_kmn_modifier("rightControl", false) === "CTRL") console.log("testNr 13 OK "); else console.log("testNr 13 NOT OK - ", (this.create_kmn_modifier("rightControl", false))) + if (this.create_kmn_modifier("command", false) === "command") console.log("testNr 16 OK "); else console.log("testNr 16 NOT OK - ", (this.create_kmn_modifier("command", false))) + if (this.create_kmn_modifier("ComMand", false) === "ComMand") console.log("testNr 26 OK "); else console.log("testNr 26 NOT OK - ", (this.create_kmn_modifier("ComMand", false))) + if (this.create_kmn_modifier("rshift?", false) === "") console.log("testNr 19 OK "); else console.log("testNr 19 NOT OK - ", (this.create_kmn_modifier("Shift?", false))) + if (this.create_kmn_modifier("rshift?", true) === "NCAPS") console.log("testNr 20 OK "); else console.log("testNr 20 NOT OK - ", (this.create_kmn_modifier("Shift?", true))) + if (this.create_kmn_modifier("rshift", false) === "SHIFT") console.log("testNr 8 OK "); else console.log("testNr 8 NOT OK - ", (this.create_kmn_modifier("rshift", false))) + if (this.create_kmn_modifier("rightshift", false) === "SHIFT") console.log("testNr 9 OK "); else console.log("testNr 9 NOT OK - ", (this.create_kmn_modifier("rshift", false))) + if (this.create_kmn_modifier("anyOption", false) === "RALT") console.log("testNr 4 OK "); else console.log("testNr 4 NOT OK - ", (this.create_kmn_modifier("anyOption", false))) + if (this.create_kmn_modifier("anyShift", false) === "SHIFT") console.log("testNr 7 OK "); else console.log("testNr 7NOT OK - ", (this.create_kmn_modifier("anyShift", false))) + if (this.create_kmn_modifier("rightShift? rightOption", false) === "RALT") console.log("testNr 17 OK "); else console.log("testNr 17 NOT OK - ", (this.create_kmn_modifier("rightShift? rightOption", false))) + if (this.create_kmn_modifier("option", false) === "RALT") console.log("testNr 15 OK "); else console.log("testNr 15 NOT OK - ", (this.create_kmn_modifier("option", false))) + if (this.create_kmn_modifier("rightOption", false) === "RALT") console.log("testNr 10 OK "); else console.log("testNr 10 NOT OK - ", (this.create_kmn_modifier("rightOption", false))) + if (this.create_kmn_modifier("anyOption", true) === "NCAPS RALT") console.log("testNr 3 OK "); else console.log("testNr 3 NOT OK - ", (this.create_kmn_modifier("anyOption", true))) + if (this.create_kmn_modifier("shift? caps", true) === "CAPS") console.log("testNr 21 OK "); else console.log("testNr 21 NOT OK - ", (this.create_kmn_modifier("shift? caps", true))) + if (this.create_kmn_modifier("caps?", false) === "") console.log("testNr 11 OK "); else console.log("testNr 11 NOT OK - ", (this.create_kmn_modifier("caps?", false))) + if (this.create_kmn_modifier("caps?", false) === "") console.log("testNr 22 OK "); else console.log("testNr 22 NOT OK - ", (this.create_kmn_modifier("caps?", false))) + if (this.create_kmn_modifier("caps?", true) === "NCAPS") console.log("testNr 12 OK "); else console.log("testNr 12 NOT OK - ", (this.create_kmn_modifier("caps?", true))) + if (this.create_kmn_modifier("shift? caps", true) === "CAPS") console.log("testNr 23 OK "); else console.log("testNr 23 NOT OK - ", (this.create_kmn_modifier("shift? caps", true))) + if (this.create_kmn_modifier("shift? caps", false) === "CAPS") console.log("testNr 24 OK "); else console.log("testNr 24 NOT OK - ", (this.create_kmn_modifier("shift? caps", false))) + if (this.create_kmn_modifier("shift caps?", true) === "SHIFT NCAPS") console.log("testNr 28 OK "); else console.log("testNr 28 NOT OK - ", (this.create_kmn_modifier("shift caps?", true))) + if (this.create_kmn_modifier("shift", true) === "NCAPS SHIFT") console.log("testNr 29 OK "); else console.log("testNr 29 NOT OK - ", (this.create_kmn_modifier("shift", true))) + if (this.create_kmn_modifier("shift", true) === "NCAPS SHIFT") console.log("testNr 30 OK "); else console.log("testNr 30 NOT OK - ", (this.create_kmn_modifier("shift", true))) + if (this.create_kmn_modifier("shift caps?", true) === "SHIFT NCAPS") console.log("testNr 27 OK "); else console.log("testNr 27 NOT OK - ", (this.create_kmn_modifier("shift caps?", true))) + if (this.create_kmn_modifier("rightShift anyOption", false) === "SHIFT RALT") console.log("testNr 18 OK "); else console.log("testNr 18 NOT OK - ", (this.create_kmn_modifier("rightShift anyOption", false))) + if (this.create_kmn_modifier("rightControl", true) === "NCAPS CTRL") console.log("testNr 14 OK "); else console.log("testNr 14 NOT OK - ", (this.create_kmn_modifier("rightControl", true))) + if (this.create_kmn_modifier("Caps", true) === "CAPS") console.log("testNr 28 OK "); else console.log("testNr 28 NOT OK - ", (this.create_kmn_modifier("Caps", true))) + if (this.create_kmn_modifier("caps", true) === "CAPS") console.log("testNr 31 OK "); else console.log("testNr 31 NOT OK - ", (this.create_kmn_modifier("Caps", true))) + if (this.create_kmn_modifier("anyOption", true) === "NCAPS RALT") console.log("testNr 32 OK "); else console.log("testNr 32 NOT OK - ", (this.create_kmn_modifier("anyOption", true))) + if (this.create_kmn_modifier("anyOption", false) === "RALT") console.log("testNr 32 OK "); else console.log("testNr 32 NOT OK - ", (this.create_kmn_modifier("anyOption", false))) + if (this.create_kmn_modifier("Caps", true) === "CAPS") console.log("testNr 33 OK "); else console.log("testNr 33 NOT OK - ", (this.create_kmn_modifier("Caps", true))) + if (this.create_kmn_modifier("caps", false) === "CAPS") console.log("testNr 34 OK "); else console.log("testNr 34 NOT OK - ", (this.create_kmn_modifier("Caps", false))) + if (this.create_kmn_modifier("shift rightShift", false) === "SHIFT") console.log("testNr 25 OK "); else console.log("testNr 25 NOT OK - ", (this.create_kmn_modifier("shift rightShift", false))) + + if (this.create_kmn_modifier("shift? caps?", true) === "NCAPS") console.log("testNr 18 OK "); else console.log("testNr 18 NOT OK - ", (this.create_kmn_modifier("shift? caps?", true))) + if (this.create_kmn_modifier("shift? caps?", false) === "") console.log("testNr 18a OK "); else console.log("testNr 18a NOT OK - ", (this.create_kmn_modifier("shift? caps?", false))) + + if (this.create_kmn_modifier("", true) === "NCAPS") console.log("testNr 40 OK "); else console.log("testNr 40 NOT OK - ", (this.create_kmn_modifier("", true))) + if (this.create_kmn_modifier("shift? caps? ", true) === "NCAPS") console.log("testNr 41 OK "); else console.log("testNr 41 NOT OK - ", (this.create_kmn_modifier("shift? caps? ", true))) + if (this.create_kmn_modifier("anyShift caps?", true) === "SHIFT NCAPS") console.log("testNr 42 OK "); else console.log("testNr 42 NOT OK - ", (this.create_kmn_modifier("anyShift caps?", true))) + if (this.create_kmn_modifier("shift? rightShift caps?", true) === "SHIFT NCAPS") console.log("testNr 44 OK "); else console.log("testNr 44 NOT OK - ", (this.create_kmn_modifier("shift? rightShift caps?", true))) + if (this.create_kmn_modifier("shift? leftShift caps?", true) === "SHIFT NCAPS") console.log("testNr 45 OK "); else console.log("testNr 45 NOT OK - ", (this.create_kmn_modifier("shift? leftShift caps?", true))) + if (this.create_kmn_modifier("shift leftShift caps ", true) === "SHIFT CAPS") console.log("testNr 46 OK "); else console.log("testNr 46 NOT OK - ", (this.create_kmn_modifier("shift leftShift caps ", true))) + if (this.create_kmn_modifier("caps", true) === "CAPS") console.log("testNr 47 OK "); else console.log("testNr 47 NOT OK - ", (this.create_kmn_modifier("caps", true))) + if (this.create_kmn_modifier("anyOption", true) === "NCAPS RALT") console.log("testNr 48 OK "); else console.log("testNr 48 NOT OK - ", (this.create_kmn_modifier("anyOption", true))) + if (this.create_kmn_modifier("Caps", true) === "CAPS") console.log("testNr 49 OK "); else console.log("testNr 49 NOT OK - ", (this.create_kmn_modifier("Caps", true))) + if (this.create_kmn_modifier("anyShift caps? anyOption ?", true) === "SHIFT NCAPS RALT") console.log("testNr 50 OK "); else console.log("testNr 50 NOT OK - ", (this.create_kmn_modifier("anyShift caps? anyOption ?", true))) + if (this.create_kmn_modifier("caps anyOption ?", true) === "CAPS RALT") console.log("testNr 51 OK "); else console.log("testNr 51 NOT OK - ", (this.create_kmn_modifier("caps anyOption ?", true))) + if (this.create_kmn_modifier("anyShift? caps? anyOption? anyControl", true) === "NCAPS CTRL") console.log("testNr 52 OK "); else console.log("testNr 52 NOT OK - ", (this.create_kmn_modifier("anyShift? caps? anyOption? anyControl", true))) + if (this.create_kmn_modifier("anyShift? caps? anyOption anyControl", true) === "NCAPS RALT CTRL") console.log("testNr 53 OK "); else console.log("testNr 53 NOT OK - ", (this.create_kmn_modifier("anyShift? caps? anyOption anyControl", true))) + + + if (this.create_kmn_modifier("", false) === "") console.log("testNr 40 OK "); else console.log("testNr 40 NOT OK - ", (this.create_kmn_modifier("", false))) + if (this.create_kmn_modifier("shift? caps? ", false) === "") console.log("testNr 41 OK "); else console.log("testNr 41 NOT OK - ", (this.create_kmn_modifier("shift? caps? ", false))) + if (this.create_kmn_modifier("anyShift caps?", false) === "SHIFT") console.log("testNr 42 OK "); else console.log("testNr 42 NOT OK - ", (this.create_kmn_modifier("anyShift caps?", false))) + if (this.create_kmn_modifier("shift? rightShift caps?", false) === "SHIFT") console.log("testNr 44 OK "); else console.log("testNr 44 NOT OK - ", (this.create_kmn_modifier("shift? rightShift caps?", false))) + if (this.create_kmn_modifier("shift? leftShift caps?", false) === "SHIFT") console.log("testNr 45 OK "); else console.log("testNr 45 NOT OK - ", (this.create_kmn_modifier("shift? leftShift caps?", false))) + if (this.create_kmn_modifier("shift leftShift caps ", false) === "SHIFT CAPS") console.log("testNr 46 OK "); else console.log("testNr 46 NOT OK - ", (this.create_kmn_modifier("shift leftShift caps ", false))) + if (this.create_kmn_modifier("caps", false) === "CAPS") console.log("testNr 47 OK "); else console.log("testNr 47 NOT OK - ", (this.create_kmn_modifier("caps", false))) + if (this.create_kmn_modifier("anyOption", false) === "RALT") console.log("testNr 48 OK "); else console.log("testNr 48 NOT OK - ", (this.create_kmn_modifier("anyOption", false))) + if (this.create_kmn_modifier("Caps", false) === "CAPS") console.log("testNr 49 OK "); else console.log("testNr 49 NOT OK - ", (this.create_kmn_modifier("Caps", false))) + if (this.create_kmn_modifier("anyShift caps? anyOption ?", false) === "SHIFT RALT") console.log("testNr 50 OK "); else console.log("testNr 50 NOT OK - ", (this.create_kmn_modifier("anyShift caps? anyOption ?", false))) + if (this.create_kmn_modifier("caps anyOption ?", false) === "CAPS RALT") console.log("testNr 51 OK "); else console.log("testNr 51 NOT OK - ", (this.create_kmn_modifier("caps anyOption ?", false))) + if (this.create_kmn_modifier("anyShift? caps? anyOption? anyControl", false) === "CTRL") console.log("testNr 52 OK "); else console.log("testNr 52 NOT OK - ", (this.create_kmn_modifier("anyShift? caps? anyOption? anyControl", false))) + if (this.create_kmn_modifier("anyShift? caps? anyOption anyControl", false) === "RALT CTRL") console.log("testNr 53 OK "); else console.log("testNr 53 NOT OK - ", (this.create_kmn_modifier("anyShift? caps? anyOption anyControl", false))) + + + + + console.log("------------------ ") + + if (this.isAcceptableKeymanModifier("SHIFT CAPS") === true) console.log("testNr A 1 OK "); else console.log("testNr A 1 NOT OK - ", (this.isAcceptableKeymanModifier("SHIFT CAPS"))) + if (this.isAcceptableKeymanModifier("SHIFT") === true) console.log("testNr A 2 OK "); else console.log("testNr A 2 NOT OK - ", (this.isAcceptableKeymanModifier("SHIFT"))) + if (this.isAcceptableKeymanModifier("shift") === true) console.log("testNr A 12 OK "); else console.log("testNr A 12 NOT OK - ", (this.isAcceptableKeymanModifier("shift"))) + if (this.isAcceptableKeymanModifier("SHIFT ") === true) console.log("testNr A 3 OK "); else console.log("testNr A 3 NOT OK - ", (this.isAcceptableKeymanModifier("SHIFT "))) + if (this.isAcceptableKeymanModifier(" SHIFT ") === true) console.log("testNr A 10 OK "); else console.log("testNr A 10 NOT OK - ", (this.isAcceptableKeymanModifier(" SHIFT "))) + if (this.isAcceptableKeymanModifier(" SHIFT") === true) console.log("testNr A 11 OK "); else console.log("testNr A 11 NOT OK - ", (this.isAcceptableKeymanModifier(" SHIFT"))) + if (this.isAcceptableKeymanModifier("rightshift") === false) console.log("testNr A 4 OK "); else console.log("testNr A 4 NOT OK - ", (this.isAcceptableKeymanModifier("rightshift"))) + if (this.isAcceptableKeymanModifier("rightshift ") === false) console.log("testNr A 5 OK "); else console.log("testNr A 5 NOT OK - ", (this.isAcceptableKeymanModifier("rightshift "))) + if (this.isAcceptableKeymanModifier(" ") === true) console.log("testNr A 6 OK "); else console.log("testNr A 6 NOT OK - ", (this.isAcceptableKeymanModifier(" "))) + if (this.isAcceptableKeymanModifier("") === true) console.log("testNr A 7 OK "); else console.log("testNr A 7 NOT OK - ", (this.isAcceptableKeymanModifier(""))) + if (this.isAcceptableKeymanModifier("rightoption") === false) console.log("testNr A 8 OK "); else console.log("testNr A 8 NOT OK - ", (this.isAcceptableKeymanModifier("rightoption"))) + if (this.isAcceptableKeymanModifier("abc") === false) console.log("testNr A 9 OK "); else console.log("testNr A 9 NOT OK - ", (this.isAcceptableKeymanModifier("abc"))) + if (this.isAcceptableKeymanModifier("ralt") === true) console.log("testNr A 13 OK "); else console.log("testNr A 13 NOT OK - ", (this.isAcceptableKeymanModifier("ralt"))) + /* + if (this.replaceModifier("rightshift") === "SHIFT") console.log("testNr B 1 OK "); else console.log("testNr B 1 NOT OK - ", this.replaceModifier("rightshift")) + if (this.replaceModifier("rightshift SHIFT") === "SHIFT") console.log("testNr B 2 OK "); else console.log("testNr B 2 NOT OK - ", this.replaceModifier("rightshift SHIFT")) + if (this.replaceModifier("lshift") === "SHIFT") console.log("testNr B 3 OK "); else console.log("testNr B 3 NOT OK - ", this.replaceModifier("lshift")) + if (this.replaceModifier("lcontrol") === "CTRL") console.log("testNr B 4 OK "); else console.log("testNr B 4 NOT OK - ", this.replaceModifier("lcontrol")) + if (this.replaceModifier("RIGHTOPTION") === "RALT") console.log("testNr B 5 OK "); else console.log("testNr B 5 NOT OK - ", this.replaceModifier("RIGHTOPTION")) + */ + + + //--------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------- @@ -835,93 +905,109 @@ export class KeylayoutToKmnConverter { return data_ukelele } - public get_ActionID_Next__From__ActionID_None(data: any, search: string): string { - for (let i = 0; i < data.keyboard.actions.action.length; i++) { - if (data.keyboard.actions.action[i]['@_id'] === search) { - for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { - if (data.keyboard.actions.action[i].when[j]['@_state'] === "none") - return data.keyboard.actions.action[i].when[j]['@_next'] + public get_KecCode_arr__From__ActionId(data: any, search: string): string[] { + const returnarray: string[] = [] + for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { + for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { + if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { + returnarray.push(this.map_UkeleleKC_To_VK(Number(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']))) } } } - return "" + return returnarray } - public get_ActionID_Id_array__From__ActionID_next(data: any, search: string): string[][] { - const returnarray2D: string[][] = [] - if (search !== "none") { - for (let i = 0; i < data.keyboard.actions.action.length; i++) { - const returnarray: string[] = [] - for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { - if (data.keyboard.actions.action[i].when[j]['@_next'] === search) { - returnarray.push(data.keyboard.actions.action[i]['@_id']) - } + public get_KeyMap_Code__From__KeyMap_Action(data: any, search: string): number { + for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { + for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { + if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { + return data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'] } - if (returnarray.length > 0) - returnarray2D.push(returnarray) } } - return returnarray2D + return -1 } - public get_ActionID_Id__From__ActionID_next(data: any, search: string): string { - if (search !== "none") { - for (let i = 0; i < data.keyboard.actions.action.length; i++) { - for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { - if (data.keyboard.actions.action[i].when[j]['@_next'] === search) { - return data.keyboard.actions.action[i]['@_id'] - } + public get_KeyMap_Code_array__From__KeyMap_Action(data: any, search: string[]): string[] { + const returnarray: string[] = [] + for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { + for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { + if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { + returnarray.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']) } } } - return "" + return returnarray } - public get_ActionID_array__From__ActionID_NoneNext(data: any, search: string): string[] { + public get_KeyMap_Code_array__From__KeyMap_Action_array(data: any, search: string[][]): string[] { const returnarray: string[] = [] - if (search !== "none") { - for (let i = 0; i < data.keyboard.actions.action.length; i++) { - for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { - if (data.keyboard.actions.action[i].when[j]['@_next'] === search) { - if (data.keyboard.actions.action[i].when[j]['@_state'] === "none") - returnarray.push(data.keyboard.actions.action[i]['@_id']) + for (let k = 0; k < search.length; k++) { + for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { + for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { + if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search[k][0]) { + returnarray.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']) } } } } return returnarray } - public get_Action2ID_NoneOutput__From__ActionID_Id(data: any, search: any): any { - let OutputValue = "" - for (let i = 0; i < data.keyboard.actions.action.length; i++) { - if (data.keyboard.actions.action[i]['@_id'] === search) { - for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { - if (data.keyboard.actions.action[i].when[j]['@_state'] === "none") { - OutputValue = data.keyboard.actions.action[i].when[j]['@_output'] + public get_KeyMap_Code_array__From__KeyMap_Action_array2D(data: any, search: string[][]): string[][] { + const returnarray2D: string[][] = [] + for (let k = 0; k < search.length; k++) { + for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { + for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { + const returnarray: string[] = [] + if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search[k][0]) { + returnarray.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']) + returnarray.push(this.map_UkeleleKC_To_VK(Number(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']))) + returnarray.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action']) + returnarray.push(data.keyboard.keyMapSet[0].keyMap[i]['@_index']) } + if (returnarray.length > 0) + returnarray2D.push(returnarray) } } } - return OutputValue + return returnarray2D } - // get all entries for state= and a given action id - public get_Action2ID_State_arrayState_Array__From__ActionID_Id(data: any, search: any): any[] { - const returnarray: string[] = [] + public get_ActionID_Index__From__ActionID_Id(data: any, search: string): number { + for (let i = 0; i < data.keyboard.actions.action.length; i++) { + if (data.keyboard.actions.action[i]['@_id'] === search) + return i + } + return 0 + } + public get_ActionID_Next__From__ActionID_None(data: any, search: string): string { for (let i = 0; i < data.keyboard.actions.action.length; i++) { if (data.keyboard.actions.action[i]['@_id'] === search) { for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { - if (data.keyboard.actions.action[i].when[j]['@_state'] !== "none") { - returnarray.push(data.keyboard.actions.action[i].when[j]['@_state']) + if (data.keyboard.actions.action[i].when[j]['@_state'] === "none") + return data.keyboard.actions.action[i].when[j]['@_next'] + } + } + } + return "" + } + public get_ActionID_Id__From__ActionID_next(data: any, search: string): string { + if (search !== "none") { + for (let i = 0; i < data.keyboard.actions.action.length; i++) { + for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { + if (data.keyboard.actions.action[i].when[j]['@_next'] === search) { + return data.keyboard.actions.action[i]['@_id'] } } } } - return returnarray + return "" } - // get all entries for state= and a given action id - public get_ActionID_Id_arrayNext_Array__From__ActionID_StateNext(data: any, search: any): string[] { + public get_ActionID_array__From__ActionID_NoneNext(data: any, search: string): string[] { const returnarray: string[] = [] - for (let i = 0; i < data.keyboard.actions.action.length; i++) { - for (let kk = 0; kk < data.keyboard.actions.action[i].when.length; kk++) { - if ((data.keyboard.actions.action[i].when[kk]['@_next'] === search) && (data.keyboard.actions.action[i].when[kk]['@_state'] !== "none")) { - returnarray.push(data.keyboard.actions.action[i]['@_id']) + if (search !== "none") { + for (let i = 0; i < data.keyboard.actions.action.length; i++) { + for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { + if (data.keyboard.actions.action[i].when[j]['@_next'] === search) { + if (data.keyboard.actions.action[i].when[j]['@_state'] === "none") + returnarray.push(data.keyboard.actions.action[i]['@_id']) + } } } } @@ -943,6 +1029,19 @@ export class KeylayoutToKmnConverter { } return returnarray2D } + public get_Action2ID_NoneOutput__From__ActionID_Id(data: any, search: any): any { + let OutputValue = "" + for (let i = 0; i < data.keyboard.actions.action.length; i++) { + if (data.keyboard.actions.action[i]['@_id'] === search) { + for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { + if (data.keyboard.actions.action[i].when[j]['@_state'] === "none") { + OutputValue = data.keyboard.actions.action[i].when[j]['@_output'] + } + } + } + } + return OutputValue + } public get_Terminator_Output__From__Terminator_State(data: any, search: string): string { for (let i = 0; i < data.keyboard.terminators.when.length; i++) { if (data.keyboard.terminators.when[i]['@_state'] === search) { @@ -951,69 +1050,21 @@ export class KeylayoutToKmnConverter { } return "" } - public get_ActionID_Index__From__ActionID_Id(data: any, search: string): number { + + // ToDo needed?? + public get_ActionID_Output__From__ActionID_IdState(data: any, search_id: string, search_state: string): Uint8Array { for (let i = 0; i < data.keyboard.actions.action.length; i++) { - if (data.keyboard.actions.action[i]['@_id'] === search) - return i - } - return 0 - } - public get_KeyMap_Code__From__KeyMap_Action(data: any, search: string): number { - for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { - for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { - if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { - return data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'] + for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { + if ((data.keyboard.actions.action[i]['@_id'] === search_id) && + (data.keyboard.actions.action[i].when[j]['@_state'] === search_state)) { + return new TextEncoder().encode(data.keyboard.actions.action[i].when[j]['@_output']) } } } - return -1 + return new TextEncoder().encode("") } - public get_KecCode_arr__From__ActionId(data: any, search: string): string[] { - const returnarray: string[] = [] - for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { - for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { - if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { - returnarray.push(this.map_UkeleleKC_To_VK(Number(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']))) - } - } - } - return returnarray - } - - - - public get_KeyMap_Code_array__From__KeyMap_Action(data: any, search: string[]): string[] { - const returnarray: string[] = [] - for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { - for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { - if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { - returnarray.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']) - } - } - } - return returnarray - } - - public get_KeyMap_Code_array__From__KeyMap_Action_array2D(data: any, search: string[][]): string[][] { - const returnarray2D: string[][] = [] - for (let k = 0; k < search.length; k++) { - for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { - for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { - const returnarray: string[] = [] - if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search[k][0]) { - returnarray.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']) - returnarray.push(this.map_UkeleleKC_To_VK(Number(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']))) - returnarray.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action']) - returnarray.push(data.keyboard.keyMapSet[0].keyMap[i]['@_index']) - } - if (returnarray.length > 0) - returnarray2D.push(returnarray) - } - } - } - return returnarray2D - } - public get_ActionID_Output__From__ActionID_IdState(data: any, search_id: string, search_state: string): Uint8Array { + // ToDo needed?? + public get_ActionID_Key__From__ActionID_IdState(data: any, search_id: string, search_state: string): Uint8Array { for (let i = 0; i < data.keyboard.actions.action.length; i++) { for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { if ((data.keyboard.actions.action[i]['@_id'] === search_id) && @@ -1024,34 +1075,7 @@ export class KeylayoutToKmnConverter { } return new TextEncoder().encode("") } - - - public get_ActionID_Keyt__From__ActionID_IdState(data: any, search_id: string, search_state: string): Uint8Array { - for (let i = 0; i < data.keyboard.actions.action.length; i++) { - for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { - if ((data.keyboard.actions.action[i]['@_id'] === search_id) && - (data.keyboard.actions.action[i].when[j]['@_state'] === search_state)) { - return new TextEncoder().encode(data.keyboard.actions.action[i].when[j]['@_output']) - } - } - } - return new TextEncoder().encode("") - } - - public get_KeyMap_Code_array__From__KeyMap_Action_array(data: any, search: string[][]): string[] { - const returnarray: string[] = [] - for (let k = 0; k < search.length; k++) { - for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { - for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { - if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search[k][0]) { - returnarray.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']) - } - } - } - } - return returnarray - } - + // ToDo needed?? public get_KeyMap_Keymaparray__From__KeyMap_Code_array(data: any, search: string[]): string[][] { const returnarray: string[][] = [] for (let k = 0; k < search.length; k++) { @@ -1068,6 +1092,7 @@ export class KeylayoutToKmnConverter { } return returnarray } + // ToDo needed?? public get_KeyMap_Keymaparray__From__KeyMap_Action(data: any, search: string): string[] { const returnarray: string[] = [] for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { @@ -1079,7 +1104,49 @@ export class KeylayoutToKmnConverter { } return returnarray } - + // ToDo needed?? + public get_ActionID_Id_array__From__ActionID_next(data: any, search: string): string[][] { + const returnarray2D: string[][] = [] + if (search !== "none") { + for (let i = 0; i < data.keyboard.actions.action.length; i++) { + const returnarray: string[] = [] + for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { + if (data.keyboard.actions.action[i].when[j]['@_next'] === search) { + returnarray.push(data.keyboard.actions.action[i]['@_id']) + } + } + if (returnarray.length > 0) + returnarray2D.push(returnarray) + } + } + return returnarray2D + } + // ToDo needed?? get all entries for state= and a given action id + public get_Action2ID_State_arrayState_Array__From__ActionID_Id(data: any, search: any): any[] { + const returnarray: string[] = [] + for (let i = 0; i < data.keyboard.actions.action.length; i++) { + if (data.keyboard.actions.action[i]['@_id'] === search) { + for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { + if (data.keyboard.actions.action[i].when[j]['@_state'] !== "none") { + returnarray.push(data.keyboard.actions.action[i].when[j]['@_state']) + } + } + } + } + return returnarray + } + // ToDo needed?? get all entries for state= and a given action id + public get_ActionID_Id_arrayNext_Array__From__ActionID_StateNext(data: any, search: any): string[] { + const returnarray: string[] = [] + for (let i = 0; i < data.keyboard.actions.action.length; i++) { + for (let kk = 0; kk < data.keyboard.actions.action[i].when.length; kk++) { + if ((data.keyboard.actions.action[i].when[kk]['@_next'] === search) && (data.keyboard.actions.action[i].when[kk]['@_state'] !== "none")) { + returnarray.push(data.keyboard.actions.action[i]['@_id']) + } + } + } + return returnarray + } public map_UkeleleKC_To_VK_array(search: string[]): string[] { const returnarray: string[] = [] @@ -1091,7 +1158,6 @@ export class KeylayoutToKmnConverter { return returnarray } - public get_ActionID_Id__From__ActionID_Next(data: any, search: string) { for (let i = 0; i < data.keyboard.actions.action.length; i++) { for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { @@ -1125,8 +1191,6 @@ export class KeylayoutToKmnConverter { } return mapIndexArray_max } - - public get_Modifier_Text__From__Modifier_Index(data: any, search: string): string[] { const mapIndexArray_max: string[] = [] const mapIndexArrayperKey: string[] = [] @@ -1138,8 +1202,6 @@ export class KeylayoutToKmnConverter { } return mapIndexArray_max } - - public get_KeyMap_Code__From__ActionID_Action(data: any, search: string): number { const mapIndexArray_max: number[][] = [] for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { @@ -1156,8 +1218,6 @@ export class KeylayoutToKmnConverter { } return mapIndexArray_max[0][1] } - - public get_KeyMap_Code__From__ActionID_Action2(data: any, search: string): number { const mapIndexArray_max: number[][] = [] for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { @@ -1236,21 +1296,12 @@ export class KeylayoutToKmnConverter { } return "" } - - - - - - - public get_KeyMap_Modifier_aray__From__KeyMap_Index(data: any, search: number): string[] { return data.ArrayOf_Modifiers[search] } public get_data_From__KeyMap_Modifier_Index(data: any, search: number): string[] { return data[search] } - - public get_dataArray2D__From__KeyMap_Modifier_Index(data: any, search: string[]): string[][] { const returnarray: string[][] = [] for (let i = 0; i < search.length; i++) { @@ -1273,6 +1324,7 @@ export class KeylayoutToKmnConverter { * @param keylayout_modifier the modifier value used in the .keylayout-file * @return kmn_modifier the modifier value used in the .kmn-file */ + //ToDo review lower part public create_kmn_modifier(keylayout_modifier: string, isCAPSused: boolean): string { let add_modifier = "" let kmn_modifier = "" @@ -1281,47 +1333,27 @@ export class KeylayoutToKmnConverter { // copy each modifier seperate element of array const modifier_state: string[] = keylayout_modifier.split(" "); - // TODO review these conditions-> what else do I need? - // TODO spelling entries of .keylayout( uppercase/lowercase, control<->ctrl,...) - // TODO anyOption? - // opt?+ LOPT?+ ROPT? -> what will be result?? - for (let i = 0; i < modifier_state.length; i++) { - /*if (String(modifier_state[i]) === "Command") - continue*/ - if (isCAPSused && (String(keylayout_modifier).indexOf("caps") === -1)) + if (isCAPSused && (String(keylayout_modifier).toUpperCase().indexOf("CAPS") === -1)) kmn_ncaps = " NCAPS " - // TODO review, find more conditions & simplify - if (String(modifier_state[i]) === "anyOption") add_modifier = "RALT " - else if (String(modifier_state[i]) === "anyShift") add_modifier = "SHIFT " - else if (String(modifier_state[i]) === "anyControl") add_modifier = "CTRL " + // if we find a modifier containing a '?' e.g. SHIFT?: => SHIFT is not neccessary. If it is not neccessary we don`t write this modifier + if ((String(modifier_state[i]).toUpperCase().includes('?') && (!String(modifier_state[i]).toUpperCase().includes('CAPS?')))) add_modifier = ""; - else if (String(modifier_state[i]) === "anyOption?") add_modifier = "" // does anyOption?... happen? - else if (String(modifier_state[i]) === "anyShift?") add_modifier = "" - else if (String(modifier_state[i]) === "anyControl?") add_modifier = "" + // TODO is this correct: caps? => caps is not neccessary. If its not neccessary and isCAPSused we need to write out NCAPS. Correct? + else if ((isCAPSused) && (String(modifier_state[i]).toUpperCase().includes('CAPS?'))) add_modifier = "NCAPS "; + else if ((!isCAPSused) && (String(modifier_state[i]).toUpperCase().includes('CAPS?'))) add_modifier = ""; + else if ((String(modifier_state[i]).toUpperCase().includes('CAPS'))) add_modifier = "CAPS "; - // TODO naming RSHIFT, rshift, Rshift,...? - else if ((String(modifier_state[i]) === "shift?") && modifier_state.includes('rshift')) add_modifier = "RSHIFT " - else if ((String(modifier_state[i]) === "shift?") && modifier_state.includes('lshift')) add_modifier = "LSHIFT " - else if ((String(modifier_state[i]) === "shift?") && modifier_state.includes('rshift') && modifier_state.includes('lshift')) add_modifier = "SHIFT " - - else if ((String(modifier_state[i]) === "option?") && modifier_state.includes('rOption')) add_modifier = "ROPT " - else if ((String(modifier_state[i]) === "option?") && modifier_state.includes('lOption')) add_modifier = "LOPT " - else if ((String(modifier_state[i]) === "option?") && modifier_state.includes('rOption') && modifier_state.includes('lOption')) add_modifier = "OPT " - - else if ((String(modifier_state[i]) === "ctrl?") && modifier_state.includes('rControl')) add_modifier = "RCTRL " - else if ((String(modifier_state[i]) === "ctrl?") && modifier_state.includes('lControl')) add_modifier = "LCTRL " - else if ((String(modifier_state[i]) === "ctrl?") && modifier_state.includes('rControl') && modifier_state.includes('lControl')) add_modifier = "CTRL " - - // remove if modifier contains '?' except for 'caps?' e.g. 'shift?', 'ctrl?', ... - // TODO is this correct: caps? => caps is not neccessary. If its not neccessary we need to write NCAPS. Correct? - else if (String(modifier_state[i]) === "caps?") add_modifier = "NCAPS " - else if (String(modifier_state[i]).charAt(modifier_state[i].length - 1) === "?") add_modifier = "" + // we do not use the right or left version of a modifier ( e.g. rightshift, leftshift). If they are used in keylayout files they will not be changed but used as is. + // Later when we write out the rules to the kmn file instead of writing those rules we print out a warning + else if ((String(modifier_state[i]).toUpperCase() === 'ANYOPTION') || (String(modifier_state[i]).toUpperCase() === 'OPTION')) add_modifier = "RALT "; + else if ((String(modifier_state[i]).toUpperCase() === 'RIGHTOPTION')) add_modifier = "RALT "; + else if ((String(modifier_state[i]).toUpperCase() === 'ANYSHIFT') || (String(modifier_state[i]).toUpperCase() === 'SHIFT')) add_modifier = "SHIFT "; + else if ((String(modifier_state[i]).toUpperCase() === 'ANYCONTROL') || (String(modifier_state[i]).toUpperCase() === 'CONTROL')) add_modifier = "CTRL "; else add_modifier = String(modifier_state[i]) + " " - kmn_modifier += kmn_ncaps + add_modifier } @@ -1331,12 +1363,173 @@ export class KeylayoutToKmnConverter { return self.indexOf(item) == pos; }) - return unique_Modifier.join(" ").replace(/\s+/g, " ").trim().toUpperCase() + //ToDo review lower part + const unique_Modifier_string = unique_Modifier.join(" ").replace(/\s+/g, " ").trim() + + const modifier_array: string[] = unique_Modifier_string.split(" "); + + for (let i = 0; i < modifier_array.length; i++) { + if ((modifier_array[i].toUpperCase() === "RIGHTSHIFT") || (modifier_array[i].toUpperCase() === "RSHIFT")) modifier_array[i] = "SHIFT" + else if ((modifier_array[i].toUpperCase() === "LEFTSHIFT") || (modifier_array[i].toUpperCase() === "LSHIFT")) modifier_array[i] = "SHIFT" + else if ((modifier_array[i].toUpperCase() === "LEFTCONTROL") || (modifier_array[i].toUpperCase() === "LCONTROL")) modifier_array[i] = "CTRL" + else if ((modifier_array[i].toUpperCase() === "RIGHTCONTROL") || (modifier_array[i].toUpperCase() === "LCONTROL")) modifier_array[i] = "CTRL" + else if ((modifier_array[i].toUpperCase() === "LEFTOPTION") || (modifier_array[i].toUpperCase() === "LOPTION")) modifier_array[i] = "RALT" + else if ((modifier_array[i].toUpperCase() === "RIGHTOPTION") || (modifier_array[i].toUpperCase() === "ROPTION")) modifier_array[i] = "RALT" + } + + const unique_modifier_array: string[] = modifier_array.filter(function (item, pos, self) { + return self.indexOf(item) == pos; + }) + + return unique_modifier_array.flat().toString().replace(/,/g, " ") + //return unique_Modifier.join(" ").replace(/\s+/g, " ").trim().toUpperCase() + //return unique_Modifier.join(" ").replace(/\s+/g, " ").trim() + //return unique_Modifier_string } public checkIfCapsUsed(keylayout_modifier: string[][]): boolean { return keylayout_modifier.flat().flat().includes("caps") } + /* + public replaceModifier(keylayout_modifier: string): string { + + const modifier_array: string[] = keylayout_modifier.split(" "); + + for (let i = 0; i < modifier_array.length; i++) { + if ((modifier_array[i].toUpperCase() === "RIGHTSHIFT") || (modifier_array[i].toUpperCase() === "RSHIFT")) modifier_array[i] = "SHIFT" + else if ((modifier_array[i].toUpperCase() === "LEFTSHIFT") || (modifier_array[i].toUpperCase() === "LSHIFT")) modifier_array[i] = "SHIFT" + else if ((modifier_array[i].toUpperCase() === "LEFTCONTROL") || (modifier_array[i].toUpperCase() === "LCONTROL")) modifier_array[i] = "CTRL" + else if ((modifier_array[i].toUpperCase() === "RIGHTCONTROL") || (modifier_array[i].toUpperCase() === "LCONTROL")) modifier_array[i] = "CTRL" + else if ((modifier_array[i].toUpperCase() === "LEFTOPTION") || (modifier_array[i].toUpperCase() === "LOPTION")) modifier_array[i] = "RALT" + else if ((modifier_array[i].toUpperCase() === "RIGHTOPTION") || (modifier_array[i].toUpperCase() === "ROPTION")) modifier_array[i] = "RALT" + } + + const unique_modifier_array: string[] = modifier_array.filter(function (item, pos, self) { + return self.indexOf(item) == pos; + }) + + return unique_modifier_array.flat().toString().replace(/,/g, " ") + } + */ + + public isAcceptableKeymanModifier(keylayout_modifier: string): boolean { + let iskKeymanModifier = true + const modifier_single: string[] = keylayout_modifier.split(" "); + + for (let i = 0; i < modifier_single.length; i++) { + if ( + (modifier_single[i].toUpperCase() === "NCAPS") + || (modifier_single[i].toUpperCase() === "SHIFT") + || (modifier_single[i].toUpperCase() === "CAPS") + || (modifier_single[i].toUpperCase() === "RALT") + || (modifier_single[i].toUpperCase() === "CTRL") + || (modifier_single[i].toUpperCase() === "") + + ) { iskKeymanModifier = iskKeymanModifier && true } + else { iskKeymanModifier = iskKeymanModifier && false } + } + return iskKeymanModifier + } + + + public findDuplicateRule_allC(uniqueDeadkeyRules: any[], index: number, rule_type: string, isCapsused: boolean): string { + + for (let i = 0; i < index - 1; i++) { + if ( + (((rule_type === "C014")) + //&& this.create_kmn_modifier(uniqueDeadkeyRules[i].modifier_key, true) === this.create_kmn_modifier(uniqueDeadkeyRules[index].modifier_key, true) + && uniqueDeadkeyRules[i].modifier_key === uniqueDeadkeyRules[index].modifier_key + && uniqueDeadkeyRules[i].key === uniqueDeadkeyRules[index].key + && new TextDecoder().decode(uniqueDeadkeyRules[i].deadkeyed_Ch) === new TextDecoder().decode(uniqueDeadkeyRules[index].deadkeyed_Ch)) + + || (rule_type === "C2" + && this.create_kmn_modifier(uniqueDeadkeyRules[i].modifier_key, isCapsused) === this.create_kmn_modifier(uniqueDeadkeyRules[index].modifier_key, isCapsused) + && uniqueDeadkeyRules[i].key === uniqueDeadkeyRules[index].key + && this.create_kmn_modifier(uniqueDeadkeyRules[i].modifier_deadkey, isCapsused) === this.create_kmn_modifier(uniqueDeadkeyRules[index].modifier_deadkey, isCapsused) + && uniqueDeadkeyRules[i].deadkey === uniqueDeadkeyRules[index].deadkey + && new TextDecoder().decode(uniqueDeadkeyRules[i].deadkeyed_Ch) === new TextDecoder().decode(uniqueDeadkeyRules[index].deadkeyed_Ch) + ) + + || (rule_type === "C3" + && this.create_kmn_modifier(uniqueDeadkeyRules[i].modifier_key, isCapsused) === this.create_kmn_modifier(uniqueDeadkeyRules[index].modifier_key, isCapsused) + && uniqueDeadkeyRules[i].key === uniqueDeadkeyRules[index].key + && this.create_kmn_modifier(uniqueDeadkeyRules[i].modifier_deadkey, isCapsused) === this.create_kmn_modifier(uniqueDeadkeyRules[index].modifier_deadkey, isCapsused) + && uniqueDeadkeyRules[i].deadkey === uniqueDeadkeyRules[index].deadkey + && this.create_kmn_modifier(uniqueDeadkeyRules[i].modifier_prev_deadkey, isCapsused) === this.create_kmn_modifier(uniqueDeadkeyRules[index].modifier_prev_deadkey, isCapsused) + && uniqueDeadkeyRules[i].prev_deadkey === uniqueDeadkeyRules[index].prev_deadkey + && new TextDecoder().decode(uniqueDeadkeyRules[i].deadkeyed_Ch) === new TextDecoder().decode(uniqueDeadkeyRules[index].deadkeyed_Ch) + ) + ) + return ("duplicate Rule: [" + + + this.create_kmn_modifier(uniqueDeadkeyRules[i].modifier_prev_deadkey, true) + " " + uniqueDeadkeyRules[i].prev_deadkey + "] > XXX [" + + this.create_kmn_modifier(uniqueDeadkeyRules[i].modifier_deadkey, true) + " " + uniqueDeadkeyRules[i].deadkey + "] > YYY [" + + this.create_kmn_modifier(uniqueDeadkeyRules[i].modifier_key, true) + " " + uniqueDeadkeyRules[i].key + + "] °°-> \'" + new TextDecoder().decode(uniqueDeadkeyRules[i].deadkeyed_Ch) + "\' <--> ") + } + return "" + } + + + public findAmbiguousRule_allC(uniqueDeadkeyRules: any[], index: number, rule_type: string, isCapsused: boolean): string { + + for (let i = 0; i < index - 1; i++) { + if ( + ( + (rule_type === "C014") + && this.create_kmn_modifier(uniqueDeadkeyRules[i].modifier_key, isCapsused) === this.create_kmn_modifier(uniqueDeadkeyRules[index].modifier_key, isCapsused) + && uniqueDeadkeyRules[i].key === uniqueDeadkeyRules[index].key && + new TextDecoder().decode(uniqueDeadkeyRules[i].deadkeyed_Ch) !== new TextDecoder().decode(uniqueDeadkeyRules[index].deadkeyed_Ch)) + + || ( + rule_type === "C2" + && this.create_kmn_modifier(uniqueDeadkeyRules[i].modifier_key, isCapsused) === this.create_kmn_modifier(uniqueDeadkeyRules[index].modifier_key, isCapsused) + && uniqueDeadkeyRules[i].key === uniqueDeadkeyRules[index].key + && this.create_kmn_modifier(uniqueDeadkeyRules[i].modifier_deadkey, isCapsused) === this.create_kmn_modifier(uniqueDeadkeyRules[index].modifier_deadkey, isCapsused) + && uniqueDeadkeyRules[i].deadkey === uniqueDeadkeyRules[index].deadkey + && new TextDecoder().decode(uniqueDeadkeyRules[i].deadkeyed_Ch) !== new TextDecoder().decode(uniqueDeadkeyRules[index].deadkeyed_Ch) + ) + + || ( + rule_type === "C3" + && this.create_kmn_modifier(uniqueDeadkeyRules[i].modifier_key, isCapsused) === this.create_kmn_modifier(uniqueDeadkeyRules[index].modifier_key, isCapsused) + && uniqueDeadkeyRules[i].key === uniqueDeadkeyRules[index].key + && this.create_kmn_modifier(uniqueDeadkeyRules[i].modifier_deadkey, isCapsused) === this.create_kmn_modifier(uniqueDeadkeyRules[index].modifier_deadkey, isCapsused) + && uniqueDeadkeyRules[i].deadkey === uniqueDeadkeyRules[index].deadkey + && this.create_kmn_modifier(uniqueDeadkeyRules[i].modifier_prev_deadkey, isCapsused) === this.create_kmn_modifier(uniqueDeadkeyRules[index].modifier_prev_deadkey, isCapsused) + && uniqueDeadkeyRules[i].prev_deadkey === uniqueDeadkeyRules[index].prev_deadkey + && new TextDecoder().decode(uniqueDeadkeyRules[i].deadkeyed_Ch) !== new TextDecoder().decode(uniqueDeadkeyRules[index].deadkeyed_Ch) + ) + ) + // return ("ambiguous Rule: [" + uniqueDeadkeyRules[i].modifier_key + " " + uniqueDeadkeyRules[i].key + "] > " + new TextDecoder().decode(uniqueDeadkeyRules[i].deadkeyed_Ch) + " <--> ") + return ("ambiguous Rule: [" + + this.create_kmn_modifier(uniqueDeadkeyRules[i].modifier_prev_deadkey, isCapsused) + " " + uniqueDeadkeyRules[i].prev_deadkey + "] | [" + + this.create_kmn_modifier(uniqueDeadkeyRules[i].modifier_deadkey, isCapsused) + " " + uniqueDeadkeyRules[i].deadkey + "] > XXX [" + + this.create_kmn_modifier(uniqueDeadkeyRules[i].modifier_key, isCapsused) + " " + uniqueDeadkeyRules[i].key + + "] °°-> \'" + new TextDecoder().decode(uniqueDeadkeyRules[i].deadkeyed_Ch) + "\' <--> ") + } + return "" + } + + public findUnAvailableRule(uniqueDeadkeyRules: any[], index: number, isCapsused: boolean): string { + if ( + (((uniqueDeadkeyRules[index].rule_type === "C0") || (uniqueDeadkeyRules[index].rule_type === "C1") || (uniqueDeadkeyRules[index].rule_type === "C4")) + && (this.isAcceptableKeymanModifier(this.create_kmn_modifier(uniqueDeadkeyRules[index].modifier_key, isCapsused)))) + + || (uniqueDeadkeyRules[index].rule_type === "C2" + && ((this.isAcceptableKeymanModifier(this.create_kmn_modifier(uniqueDeadkeyRules[index].modifier_deadkey, isCapsused))) + && (this.isAcceptableKeymanModifier(this.create_kmn_modifier(uniqueDeadkeyRules[index].modifier_key, isCapsused)))) + ) + + || (uniqueDeadkeyRules[index].rule_type === "C3" + && ((this.isAcceptableKeymanModifier(this.create_kmn_modifier(uniqueDeadkeyRules[index].modifier_prev_deadkey, isCapsused))) + && (this.isAcceptableKeymanModifier(this.create_kmn_modifier(uniqueDeadkeyRules[index].modifier_deadkey, isCapsused))) + && (this.isAcceptableKeymanModifier(this.create_kmn_modifier(uniqueDeadkeyRules[index].modifier_key, isCapsused)))) + ) + ) + return "" + return ("unavailable modifier in: ") + } /** * @brief member function to map Ukelele keycodes to a Windows Keycodes @@ -1414,8 +1607,16 @@ export class KeylayoutToKmnConverter { let data: string = "" // filter for dk values - data += '\########## OK #################################################################\n' - data += '\nNOW MY C4 RULES **ccc ********* (only to get 02C6 ect) *********************\n\n' + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~ draft print ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + if (KeylayoutToKmnConverter.print_draft) { + data += '\########## OK #################################################################\n' + data += '\nNOW MY C4 RULES **ccc ********* (only to get 02C6 ect) *********************\n\n' + } + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~ draft print ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ const DeadkeyRules = data_ukelele.ArrayOf_Rules.filter((curr) => { if (curr.isTerminator === true) { @@ -1442,6 +1643,8 @@ export class KeylayoutToKmnConverter { line = "+ [" + uniqueDeadkeyRules[i].modifier_key + " " + uniqueDeadkeyRules[i].key + "] > dxk(" + this.getHexFromChar(new TextDecoder().decode(uniqueDeadkeyRules[i].deadkeyed_Ch)) + ")" data += line + '\n' } + + //*************************************************************************************************** */ /* How to create rules from keylayout data from data_ukelele.ArrayOf_processed_RuleData: @@ -1493,7 +1696,7 @@ export class KeylayoutToKmnConverter { // remove duplicates const deadkeyed_raw = deadkeyed_raw_multiple.reduce((unique, o) => { - if (!unique.some((obj: { chars: any; rule_type: any; modifier_key: any; key: any; deadkeyed_Ch: any }) => + if (!unique.some((obj: { rule_type: any; modifier_key: any; key: any; deadkeyed_Ch: any }) => new TextDecoder().decode(obj.deadkeyed_Ch) === new TextDecoder().decode(o.deadkeyed_Ch) && obj.key === o.key && obj.rule_type === o.rule_type @@ -1552,58 +1755,43 @@ export class KeylayoutToKmnConverter { } - /*const newAA: string[][] = [] - let merker = "" - for (let i = 0; i < deadkeyedElement.length; i++) { - if (deadkeyedElement[i][1] !== merker) { - const newA: string[] = [] - newA.push(deadkeyedElement[i][1]) - newA.push(deadkeyablesElement[i][0]) - newA.push(deadkeyedElement[i][0]) - newAA.push(newA) - merker = deadkeyedElement[i][1] - } - } - console.log("newAA ", newAA)*/ - /* - const newAA: string[][] = [] - let merker = "" - for (let i = 0; i < deadkeyedElement.length; i++) { - merker = deadkeyedElement[i][1] - for (let j = 0; j < newAA.length; j++) { - if (newAA[j][0] === deadkeyedElement[i][0]) { - } - } - - - - - if (deadkeyedElement[i][1] !== merker) { - const newA: string[] = [] - newA.push(deadkeyedElement[i][1]) - newA.push(deadkeyablesElement[i][0]) - newA.push(deadkeyedElement[i][0]) - newAA.push(newA) - } - } - console.log("newAA ", newAA)*/ - - + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~ draft print ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + if (KeylayoutToKmnConverter.print_draft) { - data += "\n" - data += '\########## OK #################################################################\n' + data += "\n" + data += '\########## OK #################################################################\n' - data += '\nmatch > use(deadkeys)\n\n' - data += '\ngroup(deadkeys)\n\n' + data += '\nmatch > use(deadkeys)\n\n' + data += '\ngroup(deadkeys)\n\n' - //for (let i = 0; i < newAA.length; i++) { - for (let i = 0; i < deadkeyablesElement.length; i++) { - data += "\n\ndk: " + deadkeyedElement[i][1] - data += "\ndeadkeyablesArray xx" + deadkeyablesElement[i][0] - data += "\ndeadkeyedArray xx " + deadkeyedElement[i][0] - /*data += "\n\ndk: " + newAA[i][0] - data += "\ndeadkeyablesArray xx" + newAA[i][1] - data += "\ndeadkeyedArray xx " + newAA[i][2]*/ + //for (let i = 0; i < newAA.length; i++) { + for (let i = 0; i < deadkeyablesElement.length; i++) { + data += "\n\ndk: " + deadkeyedElement[i][1] + data += "\ndeadkeyablesArray xx" + deadkeyablesElement[i][0] + data += "\ndeadkeyedArray xx " + deadkeyedElement[i][0] + /*data += "\n\ndk: " + newAA[i][0] + data += "\ndeadkeyablesArray xx" + newAA[i][1] + data += "\ndeadkeyedArray xx " + newAA[i][2]*/ + } + } + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~ draft print ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + else { + data += '\nmatch > use(deadkeys)\n\n' + data += '\ngroup(deadkeys)\n\n' + + //for (let i = 0; i < newAA.length; i++) { + for (let i = 0; i < deadkeyablesElement.length; i++) { + data += "\n\ndk: " + deadkeyedElement[i][1] + data += "\ndeadkeyablesArray xx" + deadkeyablesElement[i][0] + data += "\ndeadkeyedArray xx " + deadkeyedElement[i][0] + /*data += "\n\ndk: " + newAA[i][0] + data += "\ndeadkeyablesArray xx" + newAA[i][1] + data += "\ndeadkeyedArray xx " + newAA[i][2]*/ + } } return data } @@ -1622,8 +1810,7 @@ export class KeylayoutToKmnConverter { } else return "" }); - - // Also remove duplicates + // Also remove duplicates C014 types const uniqueDeadkeyRules = data_C0_C1.reduce((unique, o) => { if (!unique.some((obj: { deadkeyed_Ch: any; rule_type: any; modifier_key: any; key: any }) => new TextDecoder().decode(obj.deadkeyed_Ch) === new TextDecoder().decode(o.deadkeyed_Ch) @@ -1637,53 +1824,261 @@ export class KeylayoutToKmnConverter { }, []); - const data_C2_C3 = data_ukelele.ArrayOf_Rules.filter((curr) => { + /* + const data_C2_C3 = data_ukelele.ArrayOf_Rules.filter((curr) => { + if ((curr.deadkeyed_Ch !== new TextEncoder().encode("") || curr.deadkeyed_Ch !== undefined) + && (curr.rule_type === "C2") || (curr.rule_type === "C3")) { + return curr; + } + else return "" + }); + // console.log("data_C2_C3 ", data_C2_C3) + */ + + const data_C2 = data_ukelele.ArrayOf_Rules.filter((curr) => { if ((curr.deadkeyed_Ch !== new TextEncoder().encode("") || curr.deadkeyed_Ch !== undefined) - && (curr.rule_type === "CX") || (curr.rule_type === "CX")) { + && (curr.rule_type === "C2")) { return curr; } else return "" - }); + });// Also remove duplicates C014 types - // Also remove duplicates - const uniqueDeadkeys_obj_C2_C3 = data_C2_C3.reduce((unique, o) => { - if (!unique.some((obj: { deadkeyed_Ch: any; rule_type: any; modifier_key: any; key: any }) => + // ToDo: true or false for create_kmn_modifier ??? where to gt true/false from? + const uniqueC2Rules = data_C2.reduce((unique, o) => { + if (!unique.some((obj: { deadkeyed_Ch: any; rule_type: any; modifier_key: any; modifier_deadkey: string; deadkey: any; key: any }) => + new TextDecoder().decode(obj.deadkeyed_Ch) === new TextDecoder().decode(o.deadkeyed_Ch) + && obj.rule_type === o.rule_type + + && obj.rule_type === o.rule_type + && this.create_kmn_modifier(obj.modifier_key, false) === this.create_kmn_modifier(o.modifier_key, false) + + && this.create_kmn_modifier(obj.modifier_deadkey, false) === this.create_kmn_modifier(o.modifier_deadkey, false) + && obj.deadkey === o.deadkey + ) + ) { + unique.push(o); + } + return unique; + }, []); + /* + /// console log all entries + for(let i=0;i { + if ((curr.deadkeyed_Ch !== new TextEncoder().encode("") || curr.deadkeyed_Ch !== undefined) + && (curr.rule_type === "C3")) { + return curr; + } + else return "" + }); + // ToDo: true or false for create_kmn_modifier ??? where to gt true/false from? + const uniqueC3Rules = data_C3.reduce((unique, o) => { + if (!unique.some((obj: { deadkeyed_Ch: any; rule_type: any; modifier_key: any; modifier_deadkey: string; prev_deadkey: string; modifier_prev_deadkey: string; deadkey: any; key: any }) => new TextDecoder().decode(obj.deadkeyed_Ch) === new TextDecoder().decode(o.deadkeyed_Ch) && obj.key === o.key + && obj.rule_type === o.rule_type - && obj.modifier_key === o.modifier_key) + && this.create_kmn_modifier(obj.modifier_key, false) === this.create_kmn_modifier(o.modifier_key, false) + + && this.create_kmn_modifier(obj.modifier_deadkey, false) === this.create_kmn_modifier(o.modifier_deadkey, false) + && obj.deadkey === o.deadkey + + && this.create_kmn_modifier(obj.modifier_prev_deadkey, false) === this.create_kmn_modifier(o.modifier_prev_deadkey, false) + && obj.prev_deadkey === o.prev_deadkey) ) { unique.push(o); } return unique; }, []); + // console.log("data_C2_C3 ", data_C3, uniqueC3Rules.length) - let old_c = 0 - for (let k = 0; k < uniqueDeadkeys_obj_C2_C3.length; k++) { - if (/*(ObjectArray[k].rule_type === "C3")||*/(uniqueDeadkeys_obj_C2_C3[k].rule_type === "CX")) { - old_c++ - console.log("1Obj: k ", k, - "\tType: ", (uniqueDeadkeys_obj_C2_C3[k].rule_type !== "" ? uniqueDeadkeys_obj_C2_C3[k].rule_type : "--".padEnd(4, " ")), - "| modi_prev_dk: ", (uniqueDeadkeys_obj_C2_C3[k].modifier_prev_deadkey !== "" ? uniqueDeadkeys_obj_C2_C3[k].modifier_prev_deadkey.padEnd(23, " ") : "--".padEnd(23, " ")), - "key_prev_dk: ", (uniqueDeadkeys_obj_C2_C3[k].prev_deadkey !== "" ? uniqueDeadkeys_obj_C2_C3[k].prev_deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), - "is_prev dk(): ", (uniqueDeadkeys_obj_C2_C3[k].dk_prev !== 0 ? ("dk_p(" + String(uniqueDeadkeys_obj_C2_C3[k].dk_prev) + ")").padEnd(11, " ") : "--".padEnd(11, " ")), - "| modi_dk: ", (uniqueDeadkeys_obj_C2_C3[k].modifier_deadkey !== "" ? uniqueDeadkeys_obj_C2_C3[k].modifier_deadkey.padEnd(23, " ") : "--".padEnd(23, " ")), - "key_dk: ", (uniqueDeadkeys_obj_C2_C3[k].deadkey !== "" ? uniqueDeadkeys_obj_C2_C3[k].deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), - "is dk(): ", (uniqueDeadkeys_obj_C2_C3[k].dk !== 0 ? ("dk(" + String(uniqueDeadkeys_obj_C2_C3[k].dk) + ")").padEnd(9, " ") : "--".padEnd(9, " ")), - "| modi: ", (uniqueDeadkeys_obj_C2_C3[k].modifier_key !== "" ? uniqueDeadkeys_obj_C2_C3[k].modifier_key.padEnd(20, " ") : "--".padEnd(20, " ")), - "key: ", (uniqueDeadkeys_obj_C2_C3[k].key !== "" ? uniqueDeadkeys_obj_C2_C3[k].key.padEnd(8, " ") : "--".padEnd(8, " ")), - "ch: ", (new TextDecoder().decode(uniqueDeadkeys_obj_C2_C3[k].deadkeyed_Ch) !== "" ? new TextDecoder().decode(uniqueDeadkeys_obj_C2_C3[k].deadkeyed_Ch).padEnd(10, " ") : "--".padEnd(10, " ")), + for (let i = 0; i < uniqueC3Rules.length; i++) { + console.log("uniqueC3Rules ", uniqueC3Rules.length, i, - "| °°" - ) + uniqueC3Rules[i].rule_type !== "" ? uniqueC3Rules[i].rule_type : "--".padEnd(4, " "), + + + "| ", (uniqueC3Rules[i].modifier_prev_deadkey !== "" ? uniqueC3Rules[i].modifier_prev_deadkey.padEnd(33, " ") : "--".padEnd(33, " ")), + (uniqueC3Rules[i].prev_deadkey !== "" ? uniqueC3Rules[i].prev_deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), + (uniqueC3Rules[i].dk_prev !== 0 ? ("dk(A" + String(uniqueC3Rules[i].dk_prev) + ")").padEnd(11, " ") : "--".padEnd(11, " ")), + + + (uniqueC3Rules[i].modifier_deadkey !== "" ? uniqueC3Rules[i].modifier_deadkey.padEnd(30, " ") : "--".padEnd(30, " ")), + (uniqueC3Rules[i].deadkey !== "" ? uniqueC3Rules[i].deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), + (uniqueC3Rules[i].dk !== 0 ? ("dk(B" + String(uniqueC3Rules[i].dk) + ")").padEnd(9, " ") : "--".padEnd(9, " ")), + + + "| ", (uniqueC3Rules[i].modifier_key !== "" ? uniqueC3Rules[i].modifier_key.padEnd(40, " ") : "--".padEnd(40, " ")), + (uniqueC3Rules[i].key !== "" ? uniqueC3Rules[i].key.padEnd(8, " ") : "--".padEnd(8, " ")), + (new TextDecoder().decode(uniqueC3Rules[i].deadkeyed_Ch) !== "" ? new TextDecoder().decode(uniqueC3Rules[i].deadkeyed_Ch).padEnd(10, " ") : "--".padEnd(10, " ")), + + "| °°") + } + + const data_All_C = data_ukelele.ArrayOf_Rules.filter((curr) => { + if ((curr.deadkeyed_Ch !== new TextEncoder().encode("") || curr.deadkeyed_Ch !== undefined) + && ((curr.rule_type === "C0") || (curr.rule_type === "C1") || (curr.rule_type === "C2") || (curr.rule_type === "C3") || (curr.rule_type === "C4"))) { + return curr; } + else return "" + }); + // console.log("data_All_C ", data_All_C) + + + /* // Also remove duplicates + const uniqueDeadkeys_obj_C2_C3 = data_C2_C3.reduce((unique, o) => { + if (!unique.some((obj: { rule_type: any; modifier_prev_deadkey: string; prev_deadkey: string; modifier_deadkey: string; deadkey: string; modifier_key: any; key: any }) => + + obj.rule_type === o.rule_type + && obj.modifier_prev_deadkey === o.modifier_prev_deadkey + && obj.prev_deadkey === o.prev_deadkey + + && obj.modifier_deadkey === o.modifier_deadkey + && obj.deadkey === o.deadkey + + && obj.modifier_key === o.modifier_key + && obj.key === o.key + ) + ) { + unique.push(o); + } + return unique; + }, []); + console.log("uniqueDeadkeys_obj_C2_C3 ", uniqueDeadkeys_obj_C2_C3)*/ + + // Also remove duplicates + /* const uniqueDeadkeys_obj_All_C = data_All_C.reduce((unique, o) => { + if (!unique.some((obj: { deadkeyed_Ch: Uint8Array; rule_type: any; modifier_prev_deadkey: string; prev_deadkey: string; modifier_deadkey: string; deadkey: string; modifier_key: any; key: any }) => + + obj.rule_type === o.rule_type + && obj.modifier_prev_deadkey === o.modifier_prev_deadkey + && obj.prev_deadkey === o.prev_deadkey + + && obj.modifier_deadkey === o.modifier_deadkey + && obj.deadkey === o.deadkey + + && obj.modifier_key === o.modifier_key + && obj.key === o.key + + && new TextDecoder().decode(obj.deadkeyed_Ch) === new TextDecoder().decode(o.deadkeyed_Ch) + ) + ) { + unique.push(o); + } + return unique; + }, []);*/ + + /*console.log(" uniqueDeadkeys_obj_All_C.leng ", data_All_C.length, "--", uniqueDeadkeys_obj_All_C.length) + for (let i = 0; i < uniqueDeadkeys_obj_All_C.length; i++) { + + console.log("uniqueDeadkeys_obj_All_C ", uniqueDeadkeys_obj_All_C.length, i, + + uniqueDeadkeys_obj_All_C[i].rule_type !== "" ? uniqueDeadkeys_obj_All_C[i].rule_type : "--".padEnd(4, " "), + + + "| ", (uniqueDeadkeys_obj_All_C[i].modifier_prev_deadkey !== "" ? uniqueDeadkeys_obj_All_C[i].modifier_prev_deadkey.padEnd(33, " ") : "--".padEnd(33, " ")), + (uniqueDeadkeys_obj_All_C[i].prev_deadkey !== "" ? uniqueDeadkeys_obj_All_C[i].prev_deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), + (uniqueDeadkeys_obj_All_C[i].dk_prev !== 0 ? ("dk(A" + String(uniqueDeadkeys_obj_All_C[i].dk_prev) + ")").padEnd(11, " ") : "--".padEnd(11, " ")), + + + (uniqueDeadkeys_obj_All_C[i].modifier_deadkey !== "" ? uniqueDeadkeys_obj_All_C[i].modifier_deadkey.padEnd(30, " ") : "--".padEnd(30, " ")), + (uniqueDeadkeys_obj_All_C[i].deadkey !== "" ? uniqueDeadkeys_obj_All_C[i].deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), + (uniqueDeadkeys_obj_All_C[i].dk !== 0 ? ("dk(B" + String(uniqueDeadkeys_obj_All_C[i].dk) + ")").padEnd(9, " ") : "--".padEnd(9, " ")), + + + "| ", (uniqueDeadkeys_obj_All_C[i].modifier_key !== "" ? uniqueDeadkeys_obj_All_C[i].modifier_key.padEnd(40, " ") : "--".padEnd(40, " ")), + (uniqueDeadkeys_obj_All_C[i].key !== "" ? uniqueDeadkeys_obj_All_C[i].key.padEnd(8, " ") : "--".padEnd(8, " ")), + (new TextDecoder().decode(uniqueDeadkeys_obj_All_C[i].deadkeyed_Ch) !== "" ? new TextDecoder().decode(uniqueDeadkeys_obj_All_C[i].deadkeyed_Ch).padEnd(10, " ") : "--".padEnd(10, " ")), + + "| °°") + + }**/ +/* + for (let i = 0; i < data_All_C.length; i++) { + + console.log("data_All_C ", data_All_C.length, i, + + data_All_C[i].rule_type !== "" ? data_All_C[i].rule_type : "--".padEnd(4, " "), + + + "| ", (data_All_C[i].modifier_prev_deadkey !== "" ? data_All_C[i].modifier_prev_deadkey.padEnd(33, " ") : "--".padEnd(33, " ")), + (data_All_C[i].prev_deadkey !== "" ? data_All_C[i].prev_deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), + (data_All_C[i].dk_prev !== 0 ? ("dk(A" + String(data_All_C[i].dk_prev) + ")").padEnd(11, " ") : "--".padEnd(11, " ")), + + + (data_All_C[i].modifier_deadkey !== "" ? data_All_C[i].modifier_deadkey.padEnd(30, " ") : "--".padEnd(30, " ")), + (data_All_C[i].deadkey !== "" ? data_All_C[i].deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), + (data_All_C[i].dk !== 0 ? ("dk(B" + String(data_All_C[i].dk) + ")").padEnd(9, " ") : "--".padEnd(9, " ")), + + + "| ", (data_All_C[i].modifier_key !== "" ? data_All_C[i].modifier_key.padEnd(40, " ") : "--".padEnd(40, " ")), + (data_All_C[i].key !== "" ? data_All_C[i].key.padEnd(8, " ") : "--".padEnd(8, " ")), + (new TextDecoder().decode(data_All_C[i].deadkeyed_Ch) !== "" ? new TextDecoder().decode(data_All_C[i].deadkeyed_Ch).padEnd(10, " ") : "--".padEnd(10, " ")), + + "| °°") + } - console.log("old_c ", old_c) + + +*/ + + + + + + + const isCapsused = this.checkIfCapsUsed(data_ukelele.ArrayOf_Modifiers) for (let i = 0; i < uniqueDeadkeyRules.length; i++) { // lookup key nr of the key that is being processed @@ -1701,11 +2096,152 @@ export class KeylayoutToKmnConverter { if (uniqueDeadkeyRules[i].key !== keymarker) data += '\n' - // write rule - data += keyNr + "-(modif:" + uniqueDeadkeyRules[i].rule_type + "-" + "i" + `) + [` + (uniqueDeadkeyRules[i].modifier_key + ' ' + uniqueDeadkeyRules[i].key).trim() + `] > \'` + new TextDecoder().decode(uniqueDeadkeyRules[i].deadkeyed_Ch) + '\'\n' + let warningtext = "c C0 WARNING: " + warningtext = warningtext + this.findDuplicateRule_allC(uniqueDeadkeyRules, i, "C014", isCapsused) // OK + warningtext = warningtext + this.findAmbiguousRule_allC(uniqueDeadkeyRules, i, "C014", isCapsused) // OK + warningtext = warningtext + this.findUnAvailableRule(uniqueDeadkeyRules, i, isCapsused) // OK + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~ draft print ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + if (KeylayoutToKmnConverter.print_draft) { + if (warningtext === "c C0 WARNING: ") + data += keyNr + "-(modif:" + uniqueDeadkeyRules[i].rule_type + "-" + "i" + `) + [` + (uniqueDeadkeyRules[i].modifier_key + ' ' + uniqueDeadkeyRules[i].key).trim() + `] °°-> \'` + new TextDecoder().decode(uniqueDeadkeyRules[i].deadkeyed_Ch) + '\'\n' + else + data += warningtext + keyNr + "-(modif:" + uniqueDeadkeyRules[i].rule_type + "-" + "i" + `) + [` + (uniqueDeadkeyRules[i].modifier_key + ' ' + uniqueDeadkeyRules[i].key).trim() + `] **°°-> \'` + new TextDecoder().decode(uniqueDeadkeyRules[i].deadkeyed_Ch) + '\'\n' + } + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~ draft print ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + else { + if (warningtext === "c C0 WARNING: ") + data += "[" + (uniqueDeadkeyRules[i].modifier_key + ' ' + uniqueDeadkeyRules[i].key).trim() + `] > \'` + new TextDecoder().decode(uniqueDeadkeyRules[i].deadkeyed_Ch) + '\'\n' + else + data += warningtext + "[" + (uniqueDeadkeyRules[i].modifier_key + ' ' + uniqueDeadkeyRules[i].key).trim() + `] > \'` + new TextDecoder().decode(uniqueDeadkeyRules[i].deadkeyed_Ch) + '\'\n' + } + keymarker = uniqueDeadkeyRules[i].key } + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~ draft print ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + if (KeylayoutToKmnConverter.print_draft) { + data += "\n########## C2 #################################################################\n" + } + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~ draft print ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // console.log("XXXXYYYZZc2") + for (let k = 0; k < uniqueC2Rules.length; k++) { + + if ((uniqueC2Rules[k].rule_type === "C2")) { + + let warningtext = "c C2 WARNING: "//uniqueC3Rules + warningtext = warningtext + this.findDuplicateRule_allC(uniqueC2Rules, k, "C2", isCapsused) // OK + warningtext = warningtext + this.findAmbiguousRule_allC(uniqueC2Rules, k, "C2", isCapsused) // OK + warningtext = warningtext + this.findUnAvailableRule(uniqueC2Rules, k, isCapsused) // OK + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~ draft print ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + if (KeylayoutToKmnConverter.print_draft) { + if (warningtext === "c C2 WARNING: ") { + /* data += " [" + this.create_kmn_modifier(uniqueC2Rules[k].modifier_deadkey, isCapsused) + " " + uniqueC2Rules[k].deadkey + "] > dk(C" + String(uniqueC2Rules[k].dk_C2) + ")\n" + data += " dk(C" + String(uniqueC2Rules[k].dk_C2) + ") [" + this.create_kmn_modifier(uniqueC2Rules[k].modifier_key, isCapsused) + " " + uniqueC2Rules[k].key + "] °°-> \'" + new TextDecoder().decode(uniqueC2Rules[k].deadkeyed_Ch) + "\'\n" + */ + data += " [" + this.create_kmn_modifier(uniqueC2Rules[k].modifier_deadkey, isCapsused) + " " + uniqueC2Rules[k].deadkey + "] > XXX" + + " [" + this.create_kmn_modifier(uniqueC2Rules[k].modifier_key, isCapsused) + " " + uniqueC2Rules[k].key + "] °°-> \'" + new TextDecoder().decode(uniqueC2Rules[k].deadkeyed_Ch) + "\'" + } + else { + /* data += warningtext + " [" + this.create_kmn_modifier(uniqueC2Rules[k].modifier_deadkey, isCapsused) + " " + uniqueC2Rules[k].deadkey + "] > dk(C" + String(uniqueC2Rules[k].dk_C2) + ")\n" + data += warningtext + " dk(C" + String(uniqueC2Rules[k].dk_C2) + ") [" + this.create_kmn_modifier(uniqueC2Rules[k].modifier_key, isCapsused) + " " + uniqueC2Rules[k].key + "] > \'" + new TextDecoder().decode(uniqueC2Rules[k].deadkeyed_Ch) + "\'\n" + */ + data += warningtext + " [" + this.create_kmn_modifier(uniqueC2Rules[k].modifier_deadkey, isCapsused) + " " + uniqueC2Rules[k].deadkey + "] > XXX" + + "[" + this.create_kmn_modifier(uniqueC2Rules[k].modifier_key, isCapsused) + " " + uniqueC2Rules[k].key + "] > \'" + new TextDecoder().decode(uniqueC2Rules[k].deadkeyed_Ch) + "\'" + } + } + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~ draft print ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + else { + if (warningtext === "c C2 WARNING: ") { + data += " [" + this.create_kmn_modifier(uniqueC2Rules[k].modifier_deadkey, isCapsused) + " " + uniqueC2Rules[k].deadkey + "] > dk(C" + String(uniqueC2Rules[k].dk_C2) + ")\n" + data += " dk(C" + String(uniqueC2Rules[k].dk_C2) + ") [" + this.create_kmn_modifier(uniqueC2Rules[k].modifier_key, isCapsused) + " " + uniqueC2Rules[k].key + "] °°-> \'" + new TextDecoder().decode(uniqueC2Rules[k].deadkeyed_Ch) + "\'\n" + } + else { + data += warningtext + " [" + this.create_kmn_modifier(uniqueC2Rules[k].modifier_deadkey, isCapsused) + " " + uniqueC2Rules[k].deadkey + "] > dk(C" + String(uniqueC2Rules[k].dk_C2) + ")\n" + data += warningtext + " dk(C" + String(uniqueC2Rules[k].dk_C2) + ") [" + this.create_kmn_modifier(uniqueC2Rules[k].modifier_key, isCapsused) + " " + uniqueC2Rules[k].key + "] > \'" + new TextDecoder().decode(uniqueC2Rules[k].deadkeyed_Ch) + "\'\n" + } + } + data += "\n" + } + } + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~ draft print ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + if (KeylayoutToKmnConverter.print_draft) { + data += "\n########## C3 #################################################################\n" + } + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~ draft print ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + for (let k = 0; k < uniqueC3Rules.length; k++) { + if ((uniqueC3Rules[k].rule_type === "C3")) { + + let warningtext = "c C3 WARNING: " + warningtext = warningtext + this.findDuplicateRule_allC(uniqueC3Rules, k, "C3", isCapsused) // OK + warningtext = warningtext + this.findAmbiguousRule_allC(uniqueC3Rules, k, "C3", isCapsused) // OK + warningtext = warningtext + this.findUnAvailableRule(uniqueC3Rules, k, isCapsused) // OK + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~ draft print ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + if (KeylayoutToKmnConverter.print_draft) { + if (warningtext === "c C3 WARNING: ") { + /* data += " [" + this.create_kmn_modifier(uniqueC3Rules[k].modifier_prev_deadkey, isCapsused) + " " + uniqueC3Rules[k].prev_deadkey + "] > dk(A" + String(uniqueC3Rules[k].dk_prev) + ")\n" + data += " dk(A" + String(uniqueC3Rules[k].dk_prev) + ") + [" + this.create_kmn_modifier(uniqueC3Rules[k].modifier_deadkey, isCapsused) + " " + uniqueC3Rules[k].deadkey + "] > dk(B" + String(uniqueC3Rules[k].dk) + ")\n" + data += " dk(B" + String(uniqueC3Rules[k].dk) + ") [" + this.create_kmn_modifier(uniqueC3Rules[k].modifier_key, isCapsused) + " " + uniqueC3Rules[k].key + "] °°-> \'" + new TextDecoder().decode(uniqueC3Rules[k].deadkeyed_Ch) + "\'\n" + */ + data += " [" + this.create_kmn_modifier(uniqueC3Rules[k].modifier_prev_deadkey, isCapsused) + " " + uniqueC3Rules[k].prev_deadkey + "] > XXX " + + "[" + this.create_kmn_modifier(uniqueC3Rules[k].modifier_deadkey, isCapsused) + " " + uniqueC3Rules[k].deadkey + "] > YYY " + + " [" + this.create_kmn_modifier(uniqueC3Rules[k].modifier_key, isCapsused) + " " + uniqueC3Rules[k].key + "] °°-> \'" + new TextDecoder().decode(uniqueC3Rules[k].deadkeyed_Ch) + "\'" + + } + else { + /* data += warningtext + " [" + this.create_kmn_modifier(uniqueC3Rules[k].modifier_prev_deadkey, isCapsused) + " " + uniqueC3Rules[k].prev_deadkey + "] > dk(A" + String(uniqueC3Rules[k].dk_prev) + ")\n" + data += warningtext + " dk(A" + String(uniqueC3Rules[k].dk_prev) + ") + [" + this.create_kmn_modifier(uniqueC3Rules[k].modifier_deadkey, isCapsused) + " " + uniqueC3Rules[k].deadkey + "] > dk(B" + String(uniqueC3Rules[k].dk) + ")\n" + data += warningtext + " dk(B" + String(uniqueC3Rules[k].dk) + ") [" + this.create_kmn_modifier(uniqueC3Rules[k].modifier_key, isCapsused) + " " + uniqueC3Rules[k].key + "] **°°-> \'" + new TextDecoder().decode(uniqueC3Rules[k].deadkeyed_Ch) + "\'\n" + */ + data += warningtext + " [" + this.create_kmn_modifier(uniqueC3Rules[k].modifier_prev_deadkey, isCapsused) + " " + uniqueC3Rules[k].prev_deadkey + "] > XXX " + + "[" + this.create_kmn_modifier(uniqueC3Rules[k].modifier_deadkey, isCapsused) + " " + uniqueC3Rules[k].deadkey + "] > YYY " + + " [" + this.create_kmn_modifier(uniqueC3Rules[k].modifier_key, isCapsused) + " " + uniqueC3Rules[k].key + "] °°-> \'" + new TextDecoder().decode(uniqueC3Rules[k].deadkeyed_Ch) + "\'" + + + } + } + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~ draft print ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + else { + if (warningtext === "c C3 WARNING: ") { + data += " [" + this.create_kmn_modifier(uniqueC3Rules[k].modifier_prev_deadkey, isCapsused) + " " + uniqueC3Rules[k].prev_deadkey + "] > dk(A" + String(uniqueC3Rules[k].dk_prev) + ")\n" + data += " dk(A" + String(uniqueC3Rules[k].dk_prev) + ") + [" + this.create_kmn_modifier(uniqueC3Rules[k].modifier_deadkey, isCapsused) + " " + uniqueC3Rules[k].deadkey + "] > dk(B" + String(uniqueC3Rules[k].dk) + ")\n" + data += " dk(B" + String(uniqueC3Rules[k].dk) + ") [" + this.create_kmn_modifier(uniqueC3Rules[k].modifier_key, isCapsused) + " " + uniqueC3Rules[k].key + "] °°-> \'" + new TextDecoder().decode(uniqueC3Rules[k].deadkeyed_Ch) + "\'\n" + } + else { + data += warningtext + " [" + this.create_kmn_modifier(uniqueC3Rules[k].modifier_prev_deadkey, isCapsused) + " " + uniqueC3Rules[k].prev_deadkey + "] > dk(A" + String(uniqueC3Rules[k].dk_prev) + ")\n" + data += warningtext + " dk(A" + String(uniqueC3Rules[k].dk_prev) + ") + [" + this.create_kmn_modifier(uniqueC3Rules[k].modifier_deadkey, isCapsused) + " " + uniqueC3Rules[k].deadkey + "] > dk(B" + String(uniqueC3Rules[k].dk) + ")\n" + data += warningtext + " dk(B" + String(uniqueC3Rules[k].dk) + ") [" + this.create_kmn_modifier(uniqueC3Rules[k].modifier_key, isCapsused) + " " + uniqueC3Rules[k].key + "] **°°-> \'" + new TextDecoder().decode(uniqueC3Rules[k].deadkeyed_Ch) + "\'\n" + } + } + data += "\n" + } + } data += '\n' return data } @@ -1713,33 +2249,84 @@ export class KeylayoutToKmnConverter { public createData_Stores(data_ukelele: convert_object): string { let data: string = "" - data += "c\n" - data += "c Keyman keyboard generated by kmn-convert\n" - data += "c\n" - data += "\n" + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~ draft print ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + if (KeylayoutToKmnConverter.print_draft) { + data += "c\n" + data += "c Keyman keyboard generated by kmn-convert\n" + data += "c\n" + data += "\n" + + data += '\########## OK #################################################################\n' + data += "store(&VERSION) \'...\'\n" + data += "store(&TARGETS) \'any\'\n" + data += "store(&KEYBOARDVERSION) \'...\'\n" + data += "store(©RIGHT) '© 2024 SIL International\n" + // TODO what else ?? + + data += '\########## OK #################################################################\n' + data += "\n" + data += "begin Unicode > use(main)\n\n" + data += "group(main) using keys\n\n" + + data += '\########## OK #################################################################\n' + data += "Tipp: if K_? is replaced by undefined-> no enry in kmn_Key_Name=> add K_? there and it will be shown here\n" + data += "Tipp: keys that are marked with sction do not aoear in ukelele_Array_output->do not appear in kmn\n" + data += "\n" + } + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~ draft print ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + else { + data += "c\n" + data += "c Keyman keyboard generated by kmn-convert\n" + data += "c\n" + data += "\n" + + data += "store(&VERSION) \'...\'\n" + data += "store(&TARGETS) \'any\'\n" + data += "store(&KEYBOARDVERSION) \'...\'\n" + data += "store(©RIGHT) '© 2024 SIL International\n" + // TODO what else ?? + + data += "\n" + data += "begin Unicode > use(main)\n\n" + data += "group(main) using keys\n\n" + + data += "\n" + } + return data + } - data += '\########## OK #################################################################\n' - data += "store(&VERSION) \'...\'\n" - data += "store(&TARGETS) \'any\'\n" - data += "store(&KEYBOARDVERSION) \'...\'\n" - data += "store(©RIGHT) '© 2024 SIL International\n" - // TODO what else ?? +} - data += '\########## OK #################################################################\n' - data += "\n" - data += "begin Unicode > use(main)\n\n" - data += "group(main) using keys\n\n" +/* /// console log all entries - data += '\########## OK #################################################################\n' - data += "Tipp: if K_? is replaced by undefined-> no enry in kmn_Key_Name=> add K_? there and it will be shown here\n" - data += "Tipp: keys that are marked with sction do not aoear in ukelele_Array_output->do not appear in kmn\n" - data += "\n" + for(let i=0;i Date: Mon, 27 Jan 2025 19:36:16 +0100 Subject: [PATCH 044/251] feat(developer): kmc-convert: warnings finished --- .../keylayout-to-kmn-converter.ts | 894 +++++++----------- 1 file changed, 333 insertions(+), 561 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index ca488348796..d3beb841e8b 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -154,7 +154,7 @@ export class KeylayoutToKmnConverter { static readonly OUTPUT_FILE_EXTENSION = '.kmn'; //Todo remove print_draft - static print_draft = true + static print_draft = false // TODO use callbacks what about /*private*/ for options //constructor(/*private*/ _callbacks: CompilerCallbacks, /*private*/ _options: CompilerOptions) { @@ -283,7 +283,7 @@ export class KeylayoutToKmnConverter { data += this.createData_Rules(data_ukelele) // add bottom part of kmn file: DEADKEYS - data += this.createData_Deadkeys(data_ukelele) + // data += this.createData_Deadkeys(data_ukelele) data += "\n" @@ -306,6 +306,7 @@ export class KeylayoutToKmnConverter { let dk_counter_C3_A = 0 let dk_counter_C3_B = 0 let dk_counter_C2 = 0 + let C2_count = 0 // start Tests v ToDo remove...................................... const testArray_Ukelele: string[] = [] @@ -391,7 +392,8 @@ export class KeylayoutToKmnConverter { this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), new TextEncoder().encode(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output']), ) - ObjectArray.push(RuleObj) + if (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] !== "") + ObjectArray.push(RuleObj) } } } @@ -431,80 +433,14 @@ export class KeylayoutToKmnConverter { this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), new TextEncoder().encode(this.get_Action2ID_NoneOutput__From__ActionID_Id(jsonObj, action_id)) ) - ObjectArray.push(RuleObj) - } - } - // ...................................................................................................... - // case C2: action + state Nr + output .................................................................. - // a key is mapped to an action, then to an state+output ................................................ - // replace state x with all rules that result in x ( KeyMap:action -> KeyMap:Code -> KeyName............................................ - // Action:next -> Action:state -> action:output ......................................................... - // ...............e. g. .................................................... - // ...................................................................................................... - - /* oldcase C2 - let nextVal: string[] = [] - // find the nth action id e.g. id a9 ->id nr 20 - action_id = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] - const indexOfActions = this.get_ActionID_Index__From__ActionID_Id(jsonObj, action_id) - - // loop through all actionh/when find state and get action id ( 20-> state = 1) - for (let jj = 0; jj < jsonObj.keyboard.actions.action[indexOfActions].when.length; jj++) { - const stateVal = jsonObj.keyboard.actions.action[indexOfActions].when[jj]['@_state'] - - if (jsonObj.keyboard.actions.action[indexOfActions].when[jj]['@_output'] !== undefined) { - testArray_kmn_action.push(jsonObj.keyboard.actions.action[indexOfActions].when[jj]['@_output']) - testArray_kmn_action_count++ - } - testArray_kmn_action1 = testArray_kmn_action.filter(function (item, pos, self) { - return self.indexOf(item) == pos; - }) - - // if there is a state defined, collect all cases which result in that state ( e.g. which action id contains next = 1) - if (stateVal !== undefined) { - - // get all cases which result in state 3 - nextVal = this.get_ActionID_array__From__ActionID_NoneNext(jsonObj, stateVal) - - // for all modifier combinations - for (let l = 0; l < data_ukelele.ArrayOf_Modifiers[i].length; l++) { - for (let k = 0; k < nextVal.length; k++) { - if (jsonObj.keyboard.actions.action[indexOfActions].when[jj]['@_output'] !== undefined) { - const KeymapIndex = this.get_KeyMap_Index__From__KeyMap_Action(jsonObj, nextVal[k]) - - for (let zz = 0; zz < data_ukelele.ArrayOf_Modifiers[KeymapIndex].length; zz++) { - RuleObj = new Rules( - "C2", - false, - - "", - "", - new TextEncoder().encode(""), - 0, - - this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[KeymapIndex][zz], isCapsused), - this.map_UkeleleKC_To_VK(Number(this.get_KeyMap_Code__From__KeyMap_Action(jsonObj, nextVal[k]))), - new TextEncoder().encode(""), - 0, - dk_counter_C2++, - - this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[i][l], isCapsused), - this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), - new TextEncoder().encode(jsonObj.keyboard.actions.action[indexOfActions].when[jj]['@_output']) - ) - ObjectArray.push(RuleObj) - } - } - } - } + if (this.get_Action2ID_NoneOutput__From__ActionID_Id(jsonObj, action_id) !== "") + ObjectArray.push(RuleObj) } } - */ // ...................................................................................................... - // case C2 NEW : action + state Nr + Next .................................................................... + // case C2: action + state Nr + Next .................................................................... // ...............e. g. ..................................................... // replace state x with all rules that result in 14 ( KeyMap:action -> keyMap:code (key) ...................................................... // ...................................................................................................... - // get a9 in behavior/key action_id = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] const actionIdIndexC2 = this.get_ActionID_Index__From__ActionID_Id(jsonObj, action_id) @@ -529,21 +464,23 @@ export class KeylayoutToKmnConverter { // Data of Block Nr 5 .......................................................... - /* eg: state = 3 */ // const b5_value_state = jsonObj.keyboard.actions.action[actionIdIndexC2].when[l]['@_state'] + /* eg: state = none */ // const b5_value_state = jsonObj.keyboard.actions.action[actionIdIndexC2].when[l]['@_state'] /* eg: next = 1 */ const b5_value_next = jsonObj.keyboard.actions.action[actionIdIndexC2].when[l]['@_next'] - /* eg: StateNextID = a16 */ const b5_actionId = jsonObj.keyboard.actions.action[actionIdIndexC2]['@_id'] + /* eg: StateNextID = a18 */ const b5_actionId = jsonObj.keyboard.actions.action[actionIdIndexC2]['@_id'] // ............................................................................. -console.log(" action_id", action_id) - - console.log("b5_value_next ",b5_value_next ) -console.log(" b5_actionId", b5_actionId) + console.log(" Block 5 action_id", action_id, b5_value_next, actionIdIndexC2, b5_actionId) // Data of Block Nr 4 .......................................................... - /* eg: [ '6', '31', '32' ]*/ const b4_code_arr = this.get_KeyMap_Code_array__From__KeyMap_Action(jsonObj, b5_actionId) - /* eg: 0 */ const b4_behaviourId = this.get_KeyMap_Index__From__KeyMap_Action(jsonObj, b5_actionId) - /* eg: ['CAPS', 'RALT'] */ const b4_modifier_arr = this.get_data_From__KeyMap_Modifier_Index(data_ukelele.ArrayOf_Modifiers, b4_behaviourId) + /* eg: key codes [ '24', '24' ]*/ const b4_code_arr = this.get_KeyMap_Code_array__From__KeyMap_Action(jsonObj, b5_actionId) + ///* eg: mod 0 */ const b4_behaviourId = this.get_KeyMap_Index__From__KeyMap_Action(jsonObj, b5_actionId) + // /* eg: [[0,24,a18],[3,24,a18]] */ const b4_behaviour_id_arr = this.get_KeyMap_IndexCodeAction_array__From__KeyMap_Action(jsonObj, b5_actionId) + // /* eg: ['CAPS', 'RALT'] */ const b4_modifier_arr = this.get_data_From__KeyMap_Modifier_Index(data_ukelele.ArrayOf_Modifiers, b4_behaviourId) + /* eg: [['CAPS','RALT'],['CAPS']] */ //const b4_modifier2D_array = this.get_KeyMap_IndexCodeAction_array__From__KeyMap_Action_Array(jsonObj, b4_behaviour_id_arr) + /* eg: [['24', 0], ['24', 3]] */ const b2_keyBehaviour_arr = this.get_KeyMap_Code_array__From__ActionID_Action(jsonObj, String(action_id)) + /* e.g. [[ '','caps?'], ['Caps']]*/ const b4_modifier2D_array = this.get_KeyMap_Modifier_array__From__behaviour_arr(data_ukelele.ArrayOf_Modifiers, b2_keyBehaviour_arr) // ............................................................................. + // Data of Block Nr 3 .......................................................... /* eg: actioniD = a17 */ //const b3_actionId = this.get_ActionID_Id__From__ActionID_next(jsonObj, b5_value_state) // ............................................................................. @@ -560,19 +497,24 @@ console.log(" b5_actionId", b5_actionId) // Data of Block Nr 1 .......................................................... /* eg: ['49','K_SPACE','a0','0'] */ const b1_keycode_arr = this.get_KeyMap_Code_array__From__KeyMap_Action_array2D(jsonObj, b6_actionId_arr) + // ............................................................................. for (let n1 = 0; n1 < b6_actionId_arr.length; n1++) { for (let n2 = 0; n2 < b1_keycode_arr.length; n2++) { if (b6_actionId_arr[n1][0] === b1_keycode_arr[n2][2]) { for (let n3 = 0; n3 < data_ukelele.ArrayOf_Modifiers[Number(b1_keycode_arr[n2][3])].length; n3++) { - for (let n4 = 0; n4 < b4_modifier_arr.length; n4++) { - // for (let x5 = 0; x5 < b2_modifier_arr_all.length; x5++) { - // for (let n6 = 0; n6 < b2_modifier_arr_all[x5].length; n6++) { - for (let n7 = 0; n7 < b4_code_arr.length; n7++) { - // for (let n8 = 0; n8 < b2_keyname_arr.length; n8++) { - - RuleObj = new Rules( + //somewhere the loop throughh b4_modifier_arr does not work!! + for (let n4 = 0; n4 < b4_modifier2D_array.length; n4++) { + for (let n4x = 0; n4x < b4_modifier2D_array[n4].length; n4x++) { + // console.log("b4_modifier2D_array[n4][n4x] ",b4_modifier2D_array[n4][n4x] ) + + // for (let x5 = 0; x5 < b2_modifier_arr_all.length; x5++) { + // for (let n6 = 0; n6 < b2_modifier_arr_all[x5].length; n6++) { + for (let n7 = 0; n7 < b4_code_arr.length; n7++) { + // for (let n8 = 0; n8 < b2_keyname_arr.length; n8++) { + C2_count++ + RuleObj = new Rules( /* OK rule_type */ "C2", /* OK isTerminator */ false, @@ -581,22 +523,25 @@ console.log(" b5_actionId", b5_actionId) /* prev_deadkeys_Ch*/ new TextEncoder().encode(""), /* OK dk_prev */ 0, - /* OK modifier_deadkey */ b4_modifier_arr[n4], + /* OK modifier_deadkey */ this.create_kmn_modifier(b4_modifier2D_array[n4][n4x], isCapsused), /* OK deadkey */ this.map_UkeleleKC_To_VK(Number(b4_code_arr[n7])), /* deadkeys_Ch */ new TextEncoder().encode(""), /* OK dk*/ dk_counter_C2++, /* OK dk for C2*/ 0, - /* OK modifier_key*/ data_ukelele.ArrayOf_Modifiers[Number(b1_keycode_arr[n2][3])][n3], + /* OK modifier_key*/ this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[Number(b1_keycode_arr[n2][3])][n3], isCapsused), /* OK key */ b1_keycode_arr[n2][1], /* OK deadkeyed_Ch */ new TextEncoder().encode(b6_actionId_arr[n1][2]) - ) - ObjectArray.push(RuleObj) + ) + + if (b6_actionId_arr[n1][2] !== undefined) + ObjectArray.push(RuleObj) + } } + // } + // } + // } } - // } - // } - // } } } } @@ -614,7 +559,7 @@ console.log(" b5_actionId", b5_actionId) // Action:next -> Action:state -> action:output ......................................................... // Action:id -> KeyMap:action -> keyMap:code (key) ...................................................... // ...................................................................................................... - + // todo check loop as in b2_keyBehaviour_arr // get a9 in behavior/key action_id = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] const actionIdIndex = this.get_ActionID_Index__From__ActionID_Id(jsonObj, action_id) @@ -635,7 +580,34 @@ console.log(" b5_actionId", b5_actionId) // Data of Block Nr 4 .......................................................... /* eg: [ '6', '31', '32' ]*/ const b4_code_arr = this.get_KeyMap_Code_array__From__KeyMap_Action(jsonObj, b5_actionId) /* eg: 0 */ const b4_behaviourId = this.get_KeyMap_Index__From__KeyMap_Action(jsonObj, b5_actionId) + // ToDo array!! /* eg: ['CAPS', 'RALT'] */ const b4_modifier_arr = this.get_data_From__KeyMap_Modifier_Index(data_ukelele.ArrayOf_Modifiers, b4_behaviourId) + /* eg: [['24', 0], ['24', 3]] */ const b4_keyBehaviour_arr = this.get_KeyMap_Code_array__From__ActionID_Action(jsonObj, String(action_id)) + /* e.g. [[ '','caps?'], ['Caps']]*/ const b4_modifier2D_array = this.get_KeyMap_Modifier_array__From__behaviour_arr(data_ukelele.ArrayOf_Modifiers, b4_keyBehaviour_arr) + + console.log("b4_code_arr ", b4_code_arr) + console.log("b4_behaviourId ", b4_behaviourId) + console.log("b4_modifier_arr ", b4_modifier_arr) //no + console.log("b4_keyBehaviour_arr ", b4_keyBehaviour_arr) + console.log(" b4_modifier2D_array", b4_modifier2D_array) + + + /* + // Data of Block Nr 4 .......................................................... + //XX /* eg: key codes [ '24', '24' ]*/ //const b4_code_arr = this.get_KeyMap_Code_array__From__KeyMap_Action(jsonObj, b5_actionId) + //XX /* eg: mod 0 */ const b4_behaviourId = this.get_KeyMap_Index__From__KeyMap_Action(jsonObj, b5_actionId) + //XX /* eg: [[0,24,a18],[3,24,a18]] */ const b4_behaviour_id_arr = this.get_KeyMap_IndexCodeAction_array__From__KeyMap_Action(jsonObj, b5_actionId) + //XX /* eg: ['CAPS', 'RALT'] */ const b4_modifier_arr = this.get_data_From__KeyMap_Modifier_Index(data_ukelele.ArrayOf_Modifiers, b4_behaviourId) + //XX /* eg: [['CAPS','RALT'],['CAPS']] */ //const b4_modifier2D_array = this.get_KeyMap_IndexCodeAction_array__From__KeyMap_Action_Array(jsonObj, b4_behaviour_id_arr) + // /* eg: [['24', 0], ['24', 3]] */ const b2_keyBehaviour_arr = this.get_KeyMap_Code_array__From__ActionID_Action(jsonObj, String(action_id)) + // /* e.g. [[ '','caps?'], ['Caps']]*/ const b4_modifier2D_array = this.get_KeyMap_Modifier_array__From__behaviour_arr(data_ukelele.ArrayOf_Modifiers, b2_keyBehaviour_arr) + + // */ + + + + + // ............................................................................. // Data of Block Nr 3 .......................................................... @@ -656,36 +628,41 @@ console.log(" b5_actionId", b5_actionId) /* eg: ['49','K_SPACE','a0','0'] */ const b1_keycode_arr = this.get_KeyMap_Code_array__From__KeyMap_Action_array2D(jsonObj, b6_actionId_arr) // ............................................................................. - for (let n1 = 0; n1 < b6_actionId_arr.length; n1++) { - for (let n2 = 0; n2 < b1_keycode_arr.length; n2++) { - if (b6_actionId_arr[n1][0] === b1_keycode_arr[n2][2]) { - for (let n3 = 0; n3 < data_ukelele.ArrayOf_Modifiers[Number(b1_keycode_arr[n2][3])].length; n3++) { - for (let n4 = 0; n4 < b4_modifier_arr.length; n4++) { - for (let x5 = 0; x5 < b2_modifier_arr_all.length; x5++) { - for (let n6 = 0; n6 < b2_modifier_arr_all[x5].length; n6++) { - for (let n7 = 0; n7 < b4_code_arr.length; n7++) { - for (let n8 = 0; n8 < b2_keyname_arr.length; n8++) { - - RuleObj = new Rules( + for (let n1 = 0; n1 < b6_actionId_arr.length; n1++) { /*OK */ + for (let n2 = 0; n2 < b1_keycode_arr.length; n2++) {/*OK */ + if (b6_actionId_arr[n1][0] === b1_keycode_arr[n2][2]) {/*OK */ + for (let n3 = 0; n3 < data_ukelele.ArrayOf_Modifiers[Number(b1_keycode_arr[n2][3])].length; n3++) {/*OK */ + for (let n4x = 0; n4x < b4_modifier2D_array.length; n4x++) {/*OK */ + for (let n4 = 0; n4 < b4_modifier2D_array[n4x].length; n4++) {/*OK */ + // for (let n4 = 0; n4 < b4_modifier_arr.length; n4++) { + for (let x5 = 0; x5 < b2_modifier_arr_all.length; x5++) { + for (let n6 = 0; n6 < b2_modifier_arr_all[x5].length; n6++) { + for (let n7 = 0; n7 < b4_code_arr.length; n7++) {/*OK */ + for (let n8 = 0; n8 < b2_keyname_arr.length; n8++) {/*OK */ + + RuleObj = new Rules( /* OK rule_type */ "C3", /* OK isTerminator */ false, - /* OK modifier_prev_deadkey*/ b2_modifier_arr_all[x5][n6], + /* OK modifier_prev_deadkey*/ this.create_kmn_modifier(b2_modifier_arr_all[x5][n6], isCapsused), /* OK prev_deadkey */ b2_keyname_arr[n8], /* prev_deadkeys_Ch*/ new TextEncoder().encode(""), /* OK dk_prev */ dk_counter_C3_A++, - /* OK modifier_deadkey */ b4_modifier_arr[n4], + /* OK modifier_deadkey */ this.create_kmn_modifier(b4_modifier2D_array[n4x][n4], isCapsused), /* OK deadkey */ this.map_UkeleleKC_To_VK(Number(b4_code_arr[n7])), /* deadkeys_Ch */ new TextEncoder().encode(""), /* OK dk*/ dk_counter_C3_B++, /* OK dk for C2*/ 0, - /* OK modifier_key*/ data_ukelele.ArrayOf_Modifiers[Number(b1_keycode_arr[n2][3])][n3], + /* OK modifier_key*/ this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[Number(b1_keycode_arr[n2][3])][n3], isCapsused), /* OK key */ b1_keycode_arr[n2][1], /* OK deadkeyed_Ch */ new TextEncoder().encode(b6_actionId_arr[n1][2]) - ) - ObjectArray.push(RuleObj) + ) + + if (b6_actionId_arr[n1][2] !== undefined) + ObjectArray.push(RuleObj) + } } } } @@ -729,12 +706,14 @@ console.log(" b5_actionId", b5_actionId) 0, 0, - this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[i][l], isCapsused), + data_ukelele.ArrayOf_Modifiers[i][l], this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), new TextEncoder().encode(this.get_Terminator_Output__From__Terminator_State(jsonObj, next_id)) ) } - ObjectArray.push(RuleObj) + + if (this.get_Terminator_Output__From__Terminator_State(jsonObj, next_id) !== "") + ObjectArray.push(RuleObj) } } else @@ -864,6 +843,8 @@ console.log(" b5_actionId", b5_actionId) if (this.create_kmn_modifier("caps anyOption ?", false) === "CAPS RALT") console.log("testNr 51 OK "); else console.log("testNr 51 NOT OK - ", (this.create_kmn_modifier("caps anyOption ?", false))) if (this.create_kmn_modifier("anyShift? caps? anyOption? anyControl", false) === "CTRL") console.log("testNr 52 OK "); else console.log("testNr 52 NOT OK - ", (this.create_kmn_modifier("anyShift? caps? anyOption? anyControl", false))) if (this.create_kmn_modifier("anyShift? caps? anyOption anyControl", false) === "RALT CTRL") console.log("testNr 53 OK "); else console.log("testNr 53 NOT OK - ", (this.create_kmn_modifier("anyShift? caps? anyOption anyControl", false))) + if (this.create_kmn_modifier("CAPS", false) === "CAPS") console.log("testNr 531 OK "); else console.log("testNr 531 NOT OK - ", (this.create_kmn_modifier("CAPS", true))) + if (this.create_kmn_modifier("NCAPS", false) === "NCAPS") console.log("testNr 532 OK "); else console.log("testNr 532 NOT OK - ", (this.create_kmn_modifier("NCAPS", true))) @@ -883,15 +864,6 @@ console.log(" b5_actionId", b5_actionId) if (this.isAcceptableKeymanModifier("rightoption") === false) console.log("testNr A 8 OK "); else console.log("testNr A 8 NOT OK - ", (this.isAcceptableKeymanModifier("rightoption"))) if (this.isAcceptableKeymanModifier("abc") === false) console.log("testNr A 9 OK "); else console.log("testNr A 9 NOT OK - ", (this.isAcceptableKeymanModifier("abc"))) if (this.isAcceptableKeymanModifier("ralt") === true) console.log("testNr A 13 OK "); else console.log("testNr A 13 NOT OK - ", (this.isAcceptableKeymanModifier("ralt"))) - /* - if (this.replaceModifier("rightshift") === "SHIFT") console.log("testNr B 1 OK "); else console.log("testNr B 1 NOT OK - ", this.replaceModifier("rightshift")) - if (this.replaceModifier("rightshift SHIFT") === "SHIFT") console.log("testNr B 2 OK "); else console.log("testNr B 2 NOT OK - ", this.replaceModifier("rightshift SHIFT")) - if (this.replaceModifier("lshift") === "SHIFT") console.log("testNr B 3 OK "); else console.log("testNr B 3 NOT OK - ", this.replaceModifier("lshift")) - if (this.replaceModifier("lcontrol") === "CTRL") console.log("testNr B 4 OK "); else console.log("testNr B 4 NOT OK - ", this.replaceModifier("lcontrol")) - if (this.replaceModifier("RIGHTOPTION") === "RALT") console.log("testNr B 5 OK "); else console.log("testNr B 5 NOT OK - ", this.replaceModifier("RIGHTOPTION")) - */ - - //--------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------- @@ -1251,7 +1223,7 @@ console.log(" b5_actionId", b5_actionId) } return -1 } - public get_KeyMap_IndexCodeAction_array__From__KeyMap_Action(data: any, search: string, keycode: number): string[][] { + public get_KeyMap_IndexCodeAction_array__From__KeyMap_Action(data: any, search: string): string[][] { const returnarray2D: string[][] = [] for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { @@ -1268,6 +1240,46 @@ console.log(" b5_actionId", b5_actionId) } return returnarray2D } + public get_KeyMap_IndexCodeAction_array__From__KeyMap_Action_Array(data: any, search: string[][]): string[][] { + console.log("search uuuu ", search) + const modifierArray: number[] = [] + const modifierArray2D: number[][] = [] + + + const returnarray2D: string[][] = [] + for (let i = 0; i < search.length; i++) { + + console.log("search[i][2] ", search[i][0]) + modifierArray.push(Number(search[i][0])) + + console.log("this.get_KeyMap_IndexCodeAction_array__From__KeyMap_Action(data, search[i][0]) ", this.get_KeyMap_IndexCodeAction_array__From__KeyMap_Action(data, search[i][2])) + console.log(" this.get_KeyMap_IndexCodeAction_array__From__KeyMap_Action(data, search[i][0]).flat()", this.get_KeyMap_IndexCodeAction_array__From__KeyMap_Action(data, search[i][2]).flat()) + + + + console.log("returnarray2D ", returnarray2D) + + } + modifierArray2D.push(modifierArray) + console.log("modifierArray2D ", modifierArray2D) + + returnarray2D.push(this.get_KeyMap_Modifier_array__From__behaviour_arr(data, modifierArray2D)) + + /* for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { + for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { + const returnarray: string[] = [] + if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { + returnarray.push(data.keyboard.keyMapSet[0].keyMap[i]['@_index']) + returnarray.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']) + returnarray.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action']) + } + if (returnarray.length > 0) { + returnarray2D.push(returnarray) + } + } + }*/ + return returnarray2D + } public get_KeyMap_ModiIndex_array__From__KeyMap_Action(data: any, search_code: string, search_action: string): string[][] { const returnarray2D: string[][] = [] for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { @@ -1309,7 +1321,6 @@ console.log(" b5_actionId", b5_actionId) } return returnarray } - /** * @brief member function to return the unicode value of a character * @param character the value that will converted @@ -1318,7 +1329,6 @@ console.log(" b5_actionId", b5_actionId) public getHexFromChar(character: string): string { return character.charCodeAt(0).toString(16).slice(-4).toUpperCase().padStart(4, "0") } - /** * @brief member function to create a string of modifiers in kmn-style from the modifierMap section of .keylayout-file * @param keylayout_modifier the modifier value used in the .keylayout-file @@ -1338,6 +1348,8 @@ console.log(" b5_actionId", b5_actionId) if (isCAPSused && (String(keylayout_modifier).toUpperCase().indexOf("CAPS") === -1)) kmn_ncaps = " NCAPS " + //if (String(modifier_state[i]).toUpperCase().includes('NCAPS')) add_modifier = "NCAPS "; + // if we find a modifier containing a '?' e.g. SHIFT?: => SHIFT is not neccessary. If it is not neccessary we don`t write this modifier if ((String(modifier_state[i]).toUpperCase().includes('?') && (!String(modifier_state[i]).toUpperCase().includes('CAPS?')))) add_modifier = ""; @@ -1345,13 +1357,14 @@ console.log(" b5_actionId", b5_actionId) else if ((isCAPSused) && (String(modifier_state[i]).toUpperCase().includes('CAPS?'))) add_modifier = "NCAPS "; else if ((!isCAPSused) && (String(modifier_state[i]).toUpperCase().includes('CAPS?'))) add_modifier = ""; else if ((String(modifier_state[i]).toUpperCase().includes('CAPS'))) add_modifier = "CAPS "; + else if ((isCAPSused) && (String(modifier_state[i]).toUpperCase().includes('NCAPS'))) add_modifier = "NCAPS "; // we do not use the right or left version of a modifier ( e.g. rightshift, leftshift). If they are used in keylayout files they will not be changed but used as is. // Later when we write out the rules to the kmn file instead of writing those rules we print out a warning else if ((String(modifier_state[i]).toUpperCase() === 'ANYOPTION') || (String(modifier_state[i]).toUpperCase() === 'OPTION')) add_modifier = "RALT "; else if ((String(modifier_state[i]).toUpperCase() === 'RIGHTOPTION')) add_modifier = "RALT "; else if ((String(modifier_state[i]).toUpperCase() === 'ANYSHIFT') || (String(modifier_state[i]).toUpperCase() === 'SHIFT')) add_modifier = "SHIFT "; - else if ((String(modifier_state[i]).toUpperCase() === 'ANYCONTROL') || (String(modifier_state[i]).toUpperCase() === 'CONTROL')) add_modifier = "CTRL "; + else if ((String(modifier_state[i]).toUpperCase() === 'ANYCONTROL') || (String(modifier_state[i]).toUpperCase() === 'CONTROL')) add_modifier = "RCTRL "; else add_modifier = String(modifier_state[i]) + " " kmn_modifier += kmn_ncaps + add_modifier @@ -1386,32 +1399,9 @@ console.log(" b5_actionId", b5_actionId) //return unique_Modifier.join(" ").replace(/\s+/g, " ").trim() //return unique_Modifier_string } - public checkIfCapsUsed(keylayout_modifier: string[][]): boolean { return keylayout_modifier.flat().flat().includes("caps") } - /* - public replaceModifier(keylayout_modifier: string): string { - - const modifier_array: string[] = keylayout_modifier.split(" "); - - for (let i = 0; i < modifier_array.length; i++) { - if ((modifier_array[i].toUpperCase() === "RIGHTSHIFT") || (modifier_array[i].toUpperCase() === "RSHIFT")) modifier_array[i] = "SHIFT" - else if ((modifier_array[i].toUpperCase() === "LEFTSHIFT") || (modifier_array[i].toUpperCase() === "LSHIFT")) modifier_array[i] = "SHIFT" - else if ((modifier_array[i].toUpperCase() === "LEFTCONTROL") || (modifier_array[i].toUpperCase() === "LCONTROL")) modifier_array[i] = "CTRL" - else if ((modifier_array[i].toUpperCase() === "RIGHTCONTROL") || (modifier_array[i].toUpperCase() === "LCONTROL")) modifier_array[i] = "CTRL" - else if ((modifier_array[i].toUpperCase() === "LEFTOPTION") || (modifier_array[i].toUpperCase() === "LOPTION")) modifier_array[i] = "RALT" - else if ((modifier_array[i].toUpperCase() === "RIGHTOPTION") || (modifier_array[i].toUpperCase() === "ROPTION")) modifier_array[i] = "RALT" - } - - const unique_modifier_array: string[] = modifier_array.filter(function (item, pos, self) { - return self.indexOf(item) == pos; - }) - - return unique_modifier_array.flat().toString().replace(/,/g, " ") - } - */ - public isAcceptableKeymanModifier(keylayout_modifier: string): boolean { let iskKeymanModifier = true const modifier_single: string[] = keylayout_modifier.split(" "); @@ -1419,10 +1409,14 @@ console.log(" b5_actionId", b5_actionId) for (let i = 0; i < modifier_single.length; i++) { if ( (modifier_single[i].toUpperCase() === "NCAPS") - || (modifier_single[i].toUpperCase() === "SHIFT") || (modifier_single[i].toUpperCase() === "CAPS") + || (modifier_single[i].toUpperCase() === "SHIFT") + || (modifier_single[i].toUpperCase() === "ALT") || (modifier_single[i].toUpperCase() === "RALT") + || (modifier_single[i].toUpperCase() === "LALT") || (modifier_single[i].toUpperCase() === "CTRL") + || (modifier_single[i].toUpperCase() === "LCTRL") + || (modifier_single[i].toUpperCase() === "RCTRL") || (modifier_single[i].toUpperCase() === "") ) { iskKeymanModifier = iskKeymanModifier && true } @@ -1430,107 +1424,98 @@ console.log(" b5_actionId", b5_actionId) } return iskKeymanModifier } - - - public findDuplicateRule_allC(uniqueDeadkeyRules: any[], index: number, rule_type: string, isCapsused: boolean): string { + public findDuplicateRules(unique_C0_C1_Rules: any[], index: number, rule_type: string): string { for (let i = 0; i < index - 1; i++) { if ( - (((rule_type === "C014")) - //&& this.create_kmn_modifier(uniqueDeadkeyRules[i].modifier_key, true) === this.create_kmn_modifier(uniqueDeadkeyRules[index].modifier_key, true) - && uniqueDeadkeyRules[i].modifier_key === uniqueDeadkeyRules[index].modifier_key - && uniqueDeadkeyRules[i].key === uniqueDeadkeyRules[index].key - && new TextDecoder().decode(uniqueDeadkeyRules[i].deadkeyed_Ch) === new TextDecoder().decode(uniqueDeadkeyRules[index].deadkeyed_Ch)) + ( + (rule_type === "C01") + && unique_C0_C1_Rules[i].modifier_key === unique_C0_C1_Rules[index].modifier_key + && unique_C0_C1_Rules[i].key === unique_C0_C1_Rules[index].key && + new TextDecoder().decode(unique_C0_C1_Rules[i].deadkeyed_Ch) === new TextDecoder().decode(unique_C0_C1_Rules[index].deadkeyed_Ch) + ) || (rule_type === "C2" - && this.create_kmn_modifier(uniqueDeadkeyRules[i].modifier_key, isCapsused) === this.create_kmn_modifier(uniqueDeadkeyRules[index].modifier_key, isCapsused) - && uniqueDeadkeyRules[i].key === uniqueDeadkeyRules[index].key - && this.create_kmn_modifier(uniqueDeadkeyRules[i].modifier_deadkey, isCapsused) === this.create_kmn_modifier(uniqueDeadkeyRules[index].modifier_deadkey, isCapsused) - && uniqueDeadkeyRules[i].deadkey === uniqueDeadkeyRules[index].deadkey - && new TextDecoder().decode(uniqueDeadkeyRules[i].deadkeyed_Ch) === new TextDecoder().decode(uniqueDeadkeyRules[index].deadkeyed_Ch) + && unique_C0_C1_Rules[i].modifier_deadkey === unique_C0_C1_Rules[index].modifier_deadkey + && unique_C0_C1_Rules[i].deadkey === unique_C0_C1_Rules[index].deadkey + && unique_C0_C1_Rules[i].modifier_key === unique_C0_C1_Rules[index].modifier_key + && unique_C0_C1_Rules[i].key === unique_C0_C1_Rules[index].key + && new TextDecoder().decode(unique_C0_C1_Rules[i].deadkeyed_Ch) === new TextDecoder().decode(unique_C0_C1_Rules[index].deadkeyed_Ch) ) || (rule_type === "C3" - && this.create_kmn_modifier(uniqueDeadkeyRules[i].modifier_key, isCapsused) === this.create_kmn_modifier(uniqueDeadkeyRules[index].modifier_key, isCapsused) - && uniqueDeadkeyRules[i].key === uniqueDeadkeyRules[index].key - && this.create_kmn_modifier(uniqueDeadkeyRules[i].modifier_deadkey, isCapsused) === this.create_kmn_modifier(uniqueDeadkeyRules[index].modifier_deadkey, isCapsused) - && uniqueDeadkeyRules[i].deadkey === uniqueDeadkeyRules[index].deadkey - && this.create_kmn_modifier(uniqueDeadkeyRules[i].modifier_prev_deadkey, isCapsused) === this.create_kmn_modifier(uniqueDeadkeyRules[index].modifier_prev_deadkey, isCapsused) - && uniqueDeadkeyRules[i].prev_deadkey === uniqueDeadkeyRules[index].prev_deadkey - && new TextDecoder().decode(uniqueDeadkeyRules[i].deadkeyed_Ch) === new TextDecoder().decode(uniqueDeadkeyRules[index].deadkeyed_Ch) + && unique_C0_C1_Rules[i].modifier_prev_deadkey === unique_C0_C1_Rules[index].modifier_prev_deadkey + && unique_C0_C1_Rules[i].prev_deadkey === unique_C0_C1_Rules[index].prev_deadkey + && unique_C0_C1_Rules[i].modifier_deadkey === unique_C0_C1_Rules[index].modifier_deadkey + && unique_C0_C1_Rules[i].deadkey === unique_C0_C1_Rules[index].deadkey + && unique_C0_C1_Rules[i].modifier_key === unique_C0_C1_Rules[index].modifier_key + && unique_C0_C1_Rules[i].key === unique_C0_C1_Rules[index].key + && new TextDecoder().decode(unique_C0_C1_Rules[i].deadkeyed_Ch) === new TextDecoder().decode(unique_C0_C1_Rules[index].deadkeyed_Ch) ) ) - return ("duplicate Rule: [" + - - this.create_kmn_modifier(uniqueDeadkeyRules[i].modifier_prev_deadkey, true) + " " + uniqueDeadkeyRules[i].prev_deadkey + "] > XXX [" + - this.create_kmn_modifier(uniqueDeadkeyRules[i].modifier_deadkey, true) + " " + uniqueDeadkeyRules[i].deadkey + "] > YYY [" + - this.create_kmn_modifier(uniqueDeadkeyRules[i].modifier_key, true) + " " + uniqueDeadkeyRules[i].key + - "] °°-> \'" + new TextDecoder().decode(uniqueDeadkeyRules[i].deadkeyed_Ch) + "\' <--> ") + return ("duplicate Rule: old: modif[ modi; " + unique_C0_C1_Rules[i].dk_prev + "[" + + unique_C0_C1_Rules[i].modifier_prev_deadkey + " " + unique_C0_C1_Rules[i].prev_deadkey + "] > XXX [" + + unique_C0_C1_Rules[i].modifier_deadkey + " " + unique_C0_C1_Rules[i].deadkey + "] > YYY [" + + unique_C0_C1_Rules[i].modifier_key + " " + unique_C0_C1_Rules[i].key + + "] °°-> \'" + new TextDecoder().decode(unique_C0_C1_Rules[i].deadkeyed_Ch) + "\' <--> ") } return "" } - - - public findAmbiguousRule_allC(uniqueDeadkeyRules: any[], index: number, rule_type: string, isCapsused: boolean): string { + public findAmbiguousRules(unique_C0_C1_Rules: any[], index: number, rule_type: string): string { for (let i = 0; i < index - 1; i++) { if ( - ( - (rule_type === "C014") - && this.create_kmn_modifier(uniqueDeadkeyRules[i].modifier_key, isCapsused) === this.create_kmn_modifier(uniqueDeadkeyRules[index].modifier_key, isCapsused) - && uniqueDeadkeyRules[i].key === uniqueDeadkeyRules[index].key && - new TextDecoder().decode(uniqueDeadkeyRules[i].deadkeyed_Ch) !== new TextDecoder().decode(uniqueDeadkeyRules[index].deadkeyed_Ch)) - - || ( - rule_type === "C2" - && this.create_kmn_modifier(uniqueDeadkeyRules[i].modifier_key, isCapsused) === this.create_kmn_modifier(uniqueDeadkeyRules[index].modifier_key, isCapsused) - && uniqueDeadkeyRules[i].key === uniqueDeadkeyRules[index].key - && this.create_kmn_modifier(uniqueDeadkeyRules[i].modifier_deadkey, isCapsused) === this.create_kmn_modifier(uniqueDeadkeyRules[index].modifier_deadkey, isCapsused) - && uniqueDeadkeyRules[i].deadkey === uniqueDeadkeyRules[index].deadkey - && new TextDecoder().decode(uniqueDeadkeyRules[i].deadkeyed_Ch) !== new TextDecoder().decode(uniqueDeadkeyRules[index].deadkeyed_Ch) + ((rule_type === "C01") + && unique_C0_C1_Rules[i].modifier_key === unique_C0_C1_Rules[index].modifier_key + && unique_C0_C1_Rules[i].key === unique_C0_C1_Rules[index].key && + new TextDecoder().decode(unique_C0_C1_Rules[i].deadkeyed_Ch) !== new TextDecoder().decode(unique_C0_C1_Rules[index].deadkeyed_Ch) ) - || ( - rule_type === "C3" - && this.create_kmn_modifier(uniqueDeadkeyRules[i].modifier_key, isCapsused) === this.create_kmn_modifier(uniqueDeadkeyRules[index].modifier_key, isCapsused) - && uniqueDeadkeyRules[i].key === uniqueDeadkeyRules[index].key - && this.create_kmn_modifier(uniqueDeadkeyRules[i].modifier_deadkey, isCapsused) === this.create_kmn_modifier(uniqueDeadkeyRules[index].modifier_deadkey, isCapsused) - && uniqueDeadkeyRules[i].deadkey === uniqueDeadkeyRules[index].deadkey - && this.create_kmn_modifier(uniqueDeadkeyRules[i].modifier_prev_deadkey, isCapsused) === this.create_kmn_modifier(uniqueDeadkeyRules[index].modifier_prev_deadkey, isCapsused) - && uniqueDeadkeyRules[i].prev_deadkey === uniqueDeadkeyRules[index].prev_deadkey - && new TextDecoder().decode(uniqueDeadkeyRules[i].deadkeyed_Ch) !== new TextDecoder().decode(uniqueDeadkeyRules[index].deadkeyed_Ch) + || (rule_type === "C2" + && unique_C0_C1_Rules[i].modifier_key === unique_C0_C1_Rules[index].modifier_key + && unique_C0_C1_Rules[i].key === unique_C0_C1_Rules[index].key + && unique_C0_C1_Rules[i].modifier_deadkey === unique_C0_C1_Rules[index].modifier_deadkey + && unique_C0_C1_Rules[i].deadkey === unique_C0_C1_Rules[index].deadkey + && new TextDecoder().decode(unique_C0_C1_Rules[i].deadkeyed_Ch) !== new TextDecoder().decode(unique_C0_C1_Rules[index].deadkeyed_Ch) + ) + + || (rule_type === "C3" + && unique_C0_C1_Rules[i].modifier_prev_deadkey === unique_C0_C1_Rules[index].modifier_prev_deadkey + && unique_C0_C1_Rules[i].prev_deadkey === unique_C0_C1_Rules[index].prev_deadkey + && unique_C0_C1_Rules[i].modifier_deadkey === unique_C0_C1_Rules[index].modifier_deadkey + && unique_C0_C1_Rules[i].deadkey === unique_C0_C1_Rules[index].deadkey + && unique_C0_C1_Rules[i].modifier_key === unique_C0_C1_Rules[index].modifier_key + && unique_C0_C1_Rules[i].key === unique_C0_C1_Rules[index].key + && new TextDecoder().decode(unique_C0_C1_Rules[i].deadkeyed_Ch) !== new TextDecoder().decode(unique_C0_C1_Rules[index].deadkeyed_Ch) ) ) - // return ("ambiguous Rule: [" + uniqueDeadkeyRules[i].modifier_key + " " + uniqueDeadkeyRules[i].key + "] > " + new TextDecoder().decode(uniqueDeadkeyRules[i].deadkeyed_Ch) + " <--> ") - return ("ambiguous Rule: [" + - this.create_kmn_modifier(uniqueDeadkeyRules[i].modifier_prev_deadkey, isCapsused) + " " + uniqueDeadkeyRules[i].prev_deadkey + "] | [" + - this.create_kmn_modifier(uniqueDeadkeyRules[i].modifier_deadkey, isCapsused) + " " + uniqueDeadkeyRules[i].deadkey + "] > XXX [" + - this.create_kmn_modifier(uniqueDeadkeyRules[i].modifier_key, isCapsused) + " " + uniqueDeadkeyRules[i].key + - "] °°-> \'" + new TextDecoder().decode(uniqueDeadkeyRules[i].deadkeyed_Ch) + "\' <--> ") + return ("ambiguous Rule: (old:)[" + + unique_C0_C1_Rules[i].modifier_prev_deadkey + " " + unique_C0_C1_Rules[i].prev_deadkey + "] | [" + + unique_C0_C1_Rules[i].modifier_deadkey + " " + unique_C0_C1_Rules[i].deadkey + "] > XXX [" + + unique_C0_C1_Rules[i].modifier_key + " " + unique_C0_C1_Rules[i].key + + "] °°-> \'" + new TextDecoder().decode(unique_C0_C1_Rules[i].deadkeyed_Ch) + "\' <--> (new:) ") } return "" } - - public findUnAvailableRule(uniqueDeadkeyRules: any[], index: number, isCapsused: boolean): string { + public findUnAvailableRule(unique_Rules: any[], index: number): string { if ( - (((uniqueDeadkeyRules[index].rule_type === "C0") || (uniqueDeadkeyRules[index].rule_type === "C1") || (uniqueDeadkeyRules[index].rule_type === "C4")) - && (this.isAcceptableKeymanModifier(this.create_kmn_modifier(uniqueDeadkeyRules[index].modifier_key, isCapsused)))) + (((unique_Rules[index].rule_type === "C0") || (unique_Rules[index].rule_type === "C1") || (unique_Rules[index].rule_type === "C4")) + && (this.isAcceptableKeymanModifier(unique_Rules[index].modifier_key))) - || (uniqueDeadkeyRules[index].rule_type === "C2" - && ((this.isAcceptableKeymanModifier(this.create_kmn_modifier(uniqueDeadkeyRules[index].modifier_deadkey, isCapsused))) - && (this.isAcceptableKeymanModifier(this.create_kmn_modifier(uniqueDeadkeyRules[index].modifier_key, isCapsused)))) + || (unique_Rules[index].rule_type === "C2" + && ((this.isAcceptableKeymanModifier(unique_Rules[index].modifier_deadkey)) + && (this.isAcceptableKeymanModifier(unique_Rules[index].modifier_key))) ) - || (uniqueDeadkeyRules[index].rule_type === "C3" - && ((this.isAcceptableKeymanModifier(this.create_kmn_modifier(uniqueDeadkeyRules[index].modifier_prev_deadkey, isCapsused))) - && (this.isAcceptableKeymanModifier(this.create_kmn_modifier(uniqueDeadkeyRules[index].modifier_deadkey, isCapsused))) - && (this.isAcceptableKeymanModifier(this.create_kmn_modifier(uniqueDeadkeyRules[index].modifier_key, isCapsused)))) + || (unique_Rules[index].rule_type === "C3" + && ((this.isAcceptableKeymanModifier((unique_Rules[index].modifier_prev_deadkey))) + && (this.isAcceptableKeymanModifier((unique_Rules[index].modifier_deadkey))) + && (this.isAcceptableKeymanModifier((unique_Rules[index].modifier_key)))) ) ) return "" return ("unavailable modifier in: ") } - /** * @brief member function to map Ukelele keycodes to a Windows Keycodes * @param pos Ukelele (=mac) keycodes @@ -1597,7 +1582,6 @@ console.log(" b5_actionId", b5_actionId) if (pos === 0x24) return "K_ENTER" else return "" } - //---------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------- @@ -1615,7 +1599,7 @@ console.log(" b5_actionId", b5_actionId) data += '\nNOW MY C4 RULES **ccc ********* (only to get 02C6 ect) *********************\n\n' } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // ~~~~ draft print ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~ draft print end ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ const DeadkeyRules = data_ukelele.ArrayOf_Rules.filter((curr) => { @@ -1626,7 +1610,7 @@ console.log(" b5_actionId", b5_actionId) }); // remove duplicates - const uniqueDeadkeyRules = DeadkeyRules.reduce((unique, o) => { + const unique_C0_C1_Rules = DeadkeyRules.reduce((unique, o) => { if (!unique.some((obj: { deadkeyed_Ch: any; rule_type: any; modifier_key: any; key: any }) => new TextDecoder().decode(obj.deadkeyed_Ch) === new TextDecoder().decode(o.deadkeyed_Ch) && obj.key === o.key @@ -1638,9 +1622,10 @@ console.log(" b5_actionId", b5_actionId) return unique; }, []); - for (let i = 0; i < uniqueDeadkeyRules.length; i++) { + + for (let i = 0; i < unique_C0_C1_Rules.length; i++) { let line: string = "" - line = "+ [" + uniqueDeadkeyRules[i].modifier_key + " " + uniqueDeadkeyRules[i].key + "] > dxk(" + this.getHexFromChar(new TextDecoder().decode(uniqueDeadkeyRules[i].deadkeyed_Ch)) + ")" + line = "+ [" + unique_C0_C1_Rules[i].modifier_key + " " + unique_C0_C1_Rules[i].key + "] > dxk(" + this.getHexFromChar(new TextDecoder().decode(unique_C0_C1_Rules[i].deadkeyed_Ch)) + ")" data += line + '\n' } @@ -1676,6 +1661,11 @@ console.log(" b5_actionId", b5_actionId) */ + //---------------------------------------------------------------------------------------------------------- + //---------------------------------------------------------------------------------------------------------- + //----- output table goups start ( ToDo remove) ------------------------------------------------------------ + //---------------------------------------------------------------------------------------------------------- + //---------------------------------------------------------------------------------------------------------- // select only lines for deadkeyables ( entries that contain C1, are not K_SPACE and create chars e.g. from 'C1', 'CAPS', 'K_A', 'A' ]) const deadkeyables_raw = data_ukelele.ArrayOf_Rules.filter((curr) => { if ((curr.rule_type === "C1") && (curr.key !== "K_SPACE") && (new TextDecoder().decode(curr.deadkeyed_Ch) !== "")) { @@ -1736,25 +1726,20 @@ console.log(" b5_actionId", b5_actionId) return acc; }, [[], new Set()], ); - - - const deadkeyedElement: string[][] = Array.from({ length: uniqueDeadkeyRules.length }, () => new Array(2).fill('')); - const deadkeyablesElement: string[][] = Array.from({ length: uniqueDeadkeyRules.length }, () => new Array(1).fill('')); - + const deadkeyedElement: string[][] = Array.from({ length: unique_C0_C1_Rules.length }, () => new Array(2).fill('')); + const deadkeyablesElement: string[][] = Array.from({ length: unique_C0_C1_Rules.length }, () => new Array(1).fill('')); // why is there a set entry???? deadkeyables_raw[0] - for (let i = 0; i < uniqueDeadkeyRules.length; i++) { + for (let i = 0; i < unique_C0_C1_Rules.length; i++) { for (let j = 0; j < unique_dk_array_comlpete[0].length; j++) { - - if (uniqueDeadkeyRules[i].key === unique_dk_array_comlpete[0][j][1]) { + if (unique_C0_C1_Rules[i].key === unique_dk_array_comlpete[0][j][1]) { deadkeyablesElement[i][0] = deadkeyablesElement[i][0] + "\'" + unique_dk_array_comlpete[0][j][0] + "\' " deadkeyedElement[i][0] = deadkeyedElement[i][0] + "\'" + unique_dk_array_comlpete[0][j][2] + "\' " } - deadkeyedElement[i][1] = this.getHexFromChar(new TextDecoder().decode(uniqueDeadkeyRules[i].deadkeyed_Ch)) + deadkeyedElement[i][1] = this.getHexFromChar(new TextDecoder().decode(unique_C0_C1_Rules[i].deadkeyed_Ch)) } } - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~ draft print ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -1766,33 +1751,32 @@ console.log(" b5_actionId", b5_actionId) data += '\nmatch > use(deadkeys)\n\n' data += '\ngroup(deadkeys)\n\n' - //for (let i = 0; i < newAA.length; i++) { for (let i = 0; i < deadkeyablesElement.length; i++) { data += "\n\ndk: " + deadkeyedElement[i][1] data += "\ndeadkeyablesArray xx" + deadkeyablesElement[i][0] data += "\ndeadkeyedArray xx " + deadkeyedElement[i][0] - /*data += "\n\ndk: " + newAA[i][0] - data += "\ndeadkeyablesArray xx" + newAA[i][1] - data += "\ndeadkeyedArray xx " + newAA[i][2]*/ } } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // ~~~~ draft print ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~ draft print end ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ else { data += '\nmatch > use(deadkeys)\n\n' data += '\ngroup(deadkeys)\n\n' - //for (let i = 0; i < newAA.length; i++) { for (let i = 0; i < deadkeyablesElement.length; i++) { data += "\n\ndk: " + deadkeyedElement[i][1] data += "\ndeadkeyablesArray xx" + deadkeyablesElement[i][0] data += "\ndeadkeyedArray xx " + deadkeyedElement[i][0] - /*data += "\n\ndk: " + newAA[i][0] - data += "\ndeadkeyablesArray xx" + newAA[i][1] - data += "\ndeadkeyedArray xx " + newAA[i][2]*/ } } + + //---------------------------------------------------------------------------------------------------------- + //---------------------------------------------------------------------------------------------------------- + //----- output table goups end ( ToDo remove) -------------------------------------------------------------- + //---------------------------------------------------------------------------------------------------------- + //---------------------------------------------------------------------------------------------------------- + return data } @@ -1801,8 +1785,8 @@ console.log(" b5_actionId", b5_actionId) let data: string = "" let keymarker = "" - - // select only lines that contain C0 or C1 and create an output. + // prepare data for C0 and C1 .................................. + // select only lines that contain C0 or C1 and create an output character. const data_C0_C1 = data_ukelele.ArrayOf_Rules.filter((curr) => { if ((curr.deadkeyed_Ch !== new TextEncoder().encode("") || curr.deadkeyed_Ch !== undefined) && (curr.rule_type === "C0") || (curr.rule_type === "C1")) { @@ -1810,49 +1794,39 @@ console.log(" b5_actionId", b5_actionId) } else return "" }); - // Also remove duplicates C014 types - const uniqueDeadkeyRules = data_C0_C1.reduce((unique, o) => { + const unique_C0_C1_Rules = data_C0_C1.reduce((unique, o) => { if (!unique.some((obj: { deadkeyed_Ch: any; rule_type: any; modifier_key: any; key: any }) => new TextDecoder().decode(obj.deadkeyed_Ch) === new TextDecoder().decode(o.deadkeyed_Ch) && obj.key === o.key && obj.rule_type === o.rule_type - && obj.modifier_key === o.modifier_key) + && obj.modifier_key === o.modifier_key + ) ) { unique.push(o); } return unique; }, []); - - - /* - const data_C2_C3 = data_ukelele.ArrayOf_Rules.filter((curr) => { - if ((curr.deadkeyed_Ch !== new TextEncoder().encode("") || curr.deadkeyed_Ch !== undefined) - && (curr.rule_type === "C2") || (curr.rule_type === "C3")) { - return curr; - } - else return "" - }); - // console.log("data_C2_C3 ", data_C2_C3) - */ - + this.writeDalaset(unique_C0_C1_Rules) + // prepare data for C2 ......................................... const data_C2 = data_ukelele.ArrayOf_Rules.filter((curr) => { if ((curr.deadkeyed_Ch !== new TextEncoder().encode("") || curr.deadkeyed_Ch !== undefined) && (curr.rule_type === "C2")) { return curr; } else return "" - });// Also remove duplicates C014 types - - // ToDo: true or false for create_kmn_modifier ??? where to gt true/false from? - const uniqueC2Rules = data_C2.reduce((unique, o) => { + }); + const unique_C2_Rules = data_C2.reduce((unique, o) => { if (!unique.some((obj: { deadkeyed_Ch: any; rule_type: any; modifier_key: any; modifier_deadkey: string; deadkey: any; key: any }) => + new TextDecoder().decode(obj.deadkeyed_Ch) === new TextDecoder().decode(o.deadkeyed_Ch) - && obj.rule_type === o.rule_type + && new TextDecoder().decode(obj.deadkeyed_Ch) !== "" && obj.rule_type === o.rule_type - && this.create_kmn_modifier(obj.modifier_key, false) === this.create_kmn_modifier(o.modifier_key, false) - && this.create_kmn_modifier(obj.modifier_deadkey, false) === this.create_kmn_modifier(o.modifier_deadkey, false) + && obj.modifier_key === o.modifier_key + && obj.key === o.key + + && obj.modifier_deadkey === o.modifier_deadkey && obj.deadkey === o.deadkey ) ) { @@ -1860,56 +1834,9 @@ console.log(" b5_actionId", b5_actionId) } return unique; }, []); - /* - /// console log all entries - for(let i=0;i { if ((curr.deadkeyed_Ch !== new TextEncoder().encode("") || curr.deadkeyed_Ch !== undefined) && (curr.rule_type === "C3")) { @@ -1917,10 +1844,11 @@ console.log(" b5_actionId", b5_actionId) } else return "" }); - // ToDo: true or false for create_kmn_modifier ??? where to gt true/false from? - const uniqueC3Rules = data_C3.reduce((unique, o) => { + const unique_C3_Rules = data_C3.reduce((unique, o) => { + if (!unique.some((obj: { deadkeyed_Ch: any; rule_type: any; modifier_key: any; modifier_deadkey: string; prev_deadkey: string; modifier_prev_deadkey: string; deadkey: any; key: any }) => new TextDecoder().decode(obj.deadkeyed_Ch) === new TextDecoder().decode(o.deadkeyed_Ch) + && new TextDecoder().decode(obj.deadkeyed_Ch) !== "" && obj.key === o.key && obj.rule_type === o.rule_type @@ -1936,155 +1864,17 @@ console.log(" b5_actionId", b5_actionId) } return unique; }, []); - // console.log("data_C2_C3 ", data_C3, uniqueC3Rules.length) - - - - - - for (let i = 0; i < uniqueC3Rules.length; i++) { - console.log("uniqueC3Rules ", uniqueC3Rules.length, i, - - uniqueC3Rules[i].rule_type !== "" ? uniqueC3Rules[i].rule_type : "--".padEnd(4, " "), - - - "| ", (uniqueC3Rules[i].modifier_prev_deadkey !== "" ? uniqueC3Rules[i].modifier_prev_deadkey.padEnd(33, " ") : "--".padEnd(33, " ")), - (uniqueC3Rules[i].prev_deadkey !== "" ? uniqueC3Rules[i].prev_deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), - (uniqueC3Rules[i].dk_prev !== 0 ? ("dk(A" + String(uniqueC3Rules[i].dk_prev) + ")").padEnd(11, " ") : "--".padEnd(11, " ")), - - - (uniqueC3Rules[i].modifier_deadkey !== "" ? uniqueC3Rules[i].modifier_deadkey.padEnd(30, " ") : "--".padEnd(30, " ")), - (uniqueC3Rules[i].deadkey !== "" ? uniqueC3Rules[i].deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), - (uniqueC3Rules[i].dk !== 0 ? ("dk(B" + String(uniqueC3Rules[i].dk) + ")").padEnd(9, " ") : "--".padEnd(9, " ")), - - - "| ", (uniqueC3Rules[i].modifier_key !== "" ? uniqueC3Rules[i].modifier_key.padEnd(40, " ") : "--".padEnd(40, " ")), - (uniqueC3Rules[i].key !== "" ? uniqueC3Rules[i].key.padEnd(8, " ") : "--".padEnd(8, " ")), - (new TextDecoder().decode(uniqueC3Rules[i].deadkeyed_Ch) !== "" ? new TextDecoder().decode(uniqueC3Rules[i].deadkeyed_Ch).padEnd(10, " ") : "--".padEnd(10, " ")), - - "| °°") - } - - const data_All_C = data_ukelele.ArrayOf_Rules.filter((curr) => { - if ((curr.deadkeyed_Ch !== new TextEncoder().encode("") || curr.deadkeyed_Ch !== undefined) - && ((curr.rule_type === "C0") || (curr.rule_type === "C1") || (curr.rule_type === "C2") || (curr.rule_type === "C3") || (curr.rule_type === "C4"))) { - return curr; - } - else return "" - }); - // console.log("data_All_C ", data_All_C) - - - /* // Also remove duplicates - const uniqueDeadkeys_obj_C2_C3 = data_C2_C3.reduce((unique, o) => { - if (!unique.some((obj: { rule_type: any; modifier_prev_deadkey: string; prev_deadkey: string; modifier_deadkey: string; deadkey: string; modifier_key: any; key: any }) => - - obj.rule_type === o.rule_type - && obj.modifier_prev_deadkey === o.modifier_prev_deadkey - && obj.prev_deadkey === o.prev_deadkey - - && obj.modifier_deadkey === o.modifier_deadkey - && obj.deadkey === o.deadkey - - && obj.modifier_key === o.modifier_key - && obj.key === o.key - ) - ) { - unique.push(o); - } - return unique; - }, []); - console.log("uniqueDeadkeys_obj_C2_C3 ", uniqueDeadkeys_obj_C2_C3)*/ - - // Also remove duplicates - /* const uniqueDeadkeys_obj_All_C = data_All_C.reduce((unique, o) => { - if (!unique.some((obj: { deadkeyed_Ch: Uint8Array; rule_type: any; modifier_prev_deadkey: string; prev_deadkey: string; modifier_deadkey: string; deadkey: string; modifier_key: any; key: any }) => - - obj.rule_type === o.rule_type - && obj.modifier_prev_deadkey === o.modifier_prev_deadkey - && obj.prev_deadkey === o.prev_deadkey - - && obj.modifier_deadkey === o.modifier_deadkey - && obj.deadkey === o.deadkey - - && obj.modifier_key === o.modifier_key - && obj.key === o.key - - && new TextDecoder().decode(obj.deadkeyed_Ch) === new TextDecoder().decode(o.deadkeyed_Ch) - ) - ) { - unique.push(o); - } - return unique; - }, []);*/ - - /*console.log(" uniqueDeadkeys_obj_All_C.leng ", data_All_C.length, "--", uniqueDeadkeys_obj_All_C.length) - for (let i = 0; i < uniqueDeadkeys_obj_All_C.length; i++) { - - console.log("uniqueDeadkeys_obj_All_C ", uniqueDeadkeys_obj_All_C.length, i, - - uniqueDeadkeys_obj_All_C[i].rule_type !== "" ? uniqueDeadkeys_obj_All_C[i].rule_type : "--".padEnd(4, " "), - - - "| ", (uniqueDeadkeys_obj_All_C[i].modifier_prev_deadkey !== "" ? uniqueDeadkeys_obj_All_C[i].modifier_prev_deadkey.padEnd(33, " ") : "--".padEnd(33, " ")), - (uniqueDeadkeys_obj_All_C[i].prev_deadkey !== "" ? uniqueDeadkeys_obj_All_C[i].prev_deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), - (uniqueDeadkeys_obj_All_C[i].dk_prev !== 0 ? ("dk(A" + String(uniqueDeadkeys_obj_All_C[i].dk_prev) + ")").padEnd(11, " ") : "--".padEnd(11, " ")), - - - (uniqueDeadkeys_obj_All_C[i].modifier_deadkey !== "" ? uniqueDeadkeys_obj_All_C[i].modifier_deadkey.padEnd(30, " ") : "--".padEnd(30, " ")), - (uniqueDeadkeys_obj_All_C[i].deadkey !== "" ? uniqueDeadkeys_obj_All_C[i].deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), - (uniqueDeadkeys_obj_All_C[i].dk !== 0 ? ("dk(B" + String(uniqueDeadkeys_obj_All_C[i].dk) + ")").padEnd(9, " ") : "--".padEnd(9, " ")), - - - "| ", (uniqueDeadkeys_obj_All_C[i].modifier_key !== "" ? uniqueDeadkeys_obj_All_C[i].modifier_key.padEnd(40, " ") : "--".padEnd(40, " ")), - (uniqueDeadkeys_obj_All_C[i].key !== "" ? uniqueDeadkeys_obj_All_C[i].key.padEnd(8, " ") : "--".padEnd(8, " ")), - (new TextDecoder().decode(uniqueDeadkeys_obj_All_C[i].deadkeyed_Ch) !== "" ? new TextDecoder().decode(uniqueDeadkeys_obj_All_C[i].deadkeyed_Ch).padEnd(10, " ") : "--".padEnd(10, " ")), - - "| °°") - - }**/ -/* - for (let i = 0; i < data_All_C.length; i++) { - - console.log("data_All_C ", data_All_C.length, i, - - data_All_C[i].rule_type !== "" ? data_All_C[i].rule_type : "--".padEnd(4, " "), - - - "| ", (data_All_C[i].modifier_prev_deadkey !== "" ? data_All_C[i].modifier_prev_deadkey.padEnd(33, " ") : "--".padEnd(33, " ")), - (data_All_C[i].prev_deadkey !== "" ? data_All_C[i].prev_deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), - (data_All_C[i].dk_prev !== 0 ? ("dk(A" + String(data_All_C[i].dk_prev) + ")").padEnd(11, " ") : "--".padEnd(11, " ")), - - - (data_All_C[i].modifier_deadkey !== "" ? data_All_C[i].modifier_deadkey.padEnd(30, " ") : "--".padEnd(30, " ")), - (data_All_C[i].deadkey !== "" ? data_All_C[i].deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), - (data_All_C[i].dk !== 0 ? ("dk(B" + String(data_All_C[i].dk) + ")").padEnd(9, " ") : "--".padEnd(9, " ")), - - - "| ", (data_All_C[i].modifier_key !== "" ? data_All_C[i].modifier_key.padEnd(40, " ") : "--".padEnd(40, " ")), - (data_All_C[i].key !== "" ? data_All_C[i].key.padEnd(8, " ") : "--".padEnd(8, " ")), - (new TextDecoder().decode(data_All_C[i].deadkeyed_Ch) !== "" ? new TextDecoder().decode(data_All_C[i].deadkeyed_Ch).padEnd(10, " ") : "--".padEnd(10, " ")), - - "| °°") - - } - - - -*/ - - - + console.log(" unique_C3_Rules", this.writeDalaset(unique_C3_Rules)) const isCapsused = this.checkIfCapsUsed(data_ukelele.ArrayOf_Modifiers) - for (let i = 0; i < uniqueDeadkeyRules.length; i++) { + for (let i = 0; i < unique_C0_C1_Rules.length; i++) { // lookup key nr of the key that is being processed let keyNr = 0; for (let j = 0; j < maxkey; j++) { - if (this.map_UkeleleKC_To_VK(j) === uniqueDeadkeyRules[i].key) + if (this.map_UkeleleKC_To_VK(j) === unique_C0_C1_Rules[i].key) keyNr = j } @@ -2093,34 +1883,33 @@ console.log(" b5_actionId", b5_actionId) continue // add a line after rules of each key - if (uniqueDeadkeyRules[i].key !== keymarker) + if (unique_C0_C1_Rules[i].key !== keymarker) data += '\n' let warningtext = "c C0 WARNING: " - warningtext = warningtext + this.findDuplicateRule_allC(uniqueDeadkeyRules, i, "C014", isCapsused) // OK - warningtext = warningtext + this.findAmbiguousRule_allC(uniqueDeadkeyRules, i, "C014", isCapsused) // OK - warningtext = warningtext + this.findUnAvailableRule(uniqueDeadkeyRules, i, isCapsused) // OK + warningtext = warningtext + this.findDuplicateRules(unique_C0_C1_Rules, i, "C01") + warningtext = warningtext + this.findAmbiguousRules(unique_C0_C1_Rules, i, "C01") + warningtext = warningtext + this.findUnAvailableRule(unique_C0_C1_Rules, i) // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~ draft print ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - if (KeylayoutToKmnConverter.print_draft) { + if ((KeylayoutToKmnConverter.print_draft) && (new TextDecoder().decode(unique_C0_C1_Rules[i].deadkeyed_Ch) !== "")) { if (warningtext === "c C0 WARNING: ") - data += keyNr + "-(modif:" + uniqueDeadkeyRules[i].rule_type + "-" + "i" + `) + [` + (uniqueDeadkeyRules[i].modifier_key + ' ' + uniqueDeadkeyRules[i].key).trim() + `] °°-> \'` + new TextDecoder().decode(uniqueDeadkeyRules[i].deadkeyed_Ch) + '\'\n' + data += keyNr + "-(modif:" + unique_C0_C1_Rules[i].rule_type + "-" + unique_C0_C1_Rules[i].dk_prev + `) + [` + (unique_C0_C1_Rules[i].modifier_key + ' ' + unique_C0_C1_Rules[i].key).trim() + `] °°-> \'` + new TextDecoder().decode(unique_C0_C1_Rules[i].deadkeyed_Ch) + '\'\n' else - data += warningtext + keyNr + "-(modif:" + uniqueDeadkeyRules[i].rule_type + "-" + "i" + `) + [` + (uniqueDeadkeyRules[i].modifier_key + ' ' + uniqueDeadkeyRules[i].key).trim() + `] **°°-> \'` + new TextDecoder().decode(uniqueDeadkeyRules[i].deadkeyed_Ch) + '\'\n' + data += warningtext + keyNr + "-(modif:" + unique_C0_C1_Rules[i].rule_type + "-" + unique_C0_C1_Rules[i].dk_prev + `) + [` + (unique_C0_C1_Rules[i].modifier_key + ' ' + unique_C0_C1_Rules[i].key).trim() + `] **°°-> \'` + new TextDecoder().decode(unique_C0_C1_Rules[i].deadkeyed_Ch) + '\'\n' } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // ~~~~ draft print ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~ draft print end ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ else { if (warningtext === "c C0 WARNING: ") - data += "[" + (uniqueDeadkeyRules[i].modifier_key + ' ' + uniqueDeadkeyRules[i].key).trim() + `] > \'` + new TextDecoder().decode(uniqueDeadkeyRules[i].deadkeyed_Ch) + '\'\n' + data += "+ [" + (unique_C0_C1_Rules[i].modifier_key + ' ' + unique_C0_C1_Rules[i].key).trim() + `] > \'` + new TextDecoder().decode(unique_C0_C1_Rules[i].deadkeyed_Ch) + '\'\n' else - data += warningtext + "[" + (uniqueDeadkeyRules[i].modifier_key + ' ' + uniqueDeadkeyRules[i].key).trim() + `] > \'` + new TextDecoder().decode(uniqueDeadkeyRules[i].deadkeyed_Ch) + '\'\n' + data += warningtext + "[" + (unique_C0_C1_Rules[i].modifier_key + ' ' + unique_C0_C1_Rules[i].key).trim() + `] > \'` + new TextDecoder().decode(unique_C0_C1_Rules[i].deadkeyed_Ch) + '\'\n' } - - keymarker = uniqueDeadkeyRules[i].key + keymarker = unique_C0_C1_Rules[i].key } @@ -2131,48 +1920,42 @@ console.log(" b5_actionId", b5_actionId) data += "\n########## C2 #################################################################\n" } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // ~~~~ draft print ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~ draft print end ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // console.log("XXXXYYYZZc2") - for (let k = 0; k < uniqueC2Rules.length; k++) { - if ((uniqueC2Rules[k].rule_type === "C2")) { + for (let k = 0; k < unique_C2_Rules.length; k++) { - let warningtext = "c C2 WARNING: "//uniqueC3Rules - warningtext = warningtext + this.findDuplicateRule_allC(uniqueC2Rules, k, "C2", isCapsused) // OK - warningtext = warningtext + this.findAmbiguousRule_allC(uniqueC2Rules, k, "C2", isCapsused) // OK - warningtext = warningtext + this.findUnAvailableRule(uniqueC2Rules, k, isCapsused) // OK + if ((unique_C2_Rules[k].rule_type === "C2")) { + + let warningtext = "c C2 WARNING: " + warningtext = warningtext + this.findDuplicateRules(unique_C2_Rules, k, "C2") + warningtext = warningtext + this.findAmbiguousRules(unique_C2_Rules, k, "C2") + warningtext = warningtext + this.findUnAvailableRule(unique_C2_Rules, k) // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~ draft print ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (KeylayoutToKmnConverter.print_draft) { if (warningtext === "c C2 WARNING: ") { - /* data += " [" + this.create_kmn_modifier(uniqueC2Rules[k].modifier_deadkey, isCapsused) + " " + uniqueC2Rules[k].deadkey + "] > dk(C" + String(uniqueC2Rules[k].dk_C2) + ")\n" - data += " dk(C" + String(uniqueC2Rules[k].dk_C2) + ") [" + this.create_kmn_modifier(uniqueC2Rules[k].modifier_key, isCapsused) + " " + uniqueC2Rules[k].key + "] °°-> \'" + new TextDecoder().decode(uniqueC2Rules[k].deadkeyed_Ch) + "\'\n" - */ - data += " [" + this.create_kmn_modifier(uniqueC2Rules[k].modifier_deadkey, isCapsused) + " " + uniqueC2Rules[k].deadkey + "] > XXX" + - " [" + this.create_kmn_modifier(uniqueC2Rules[k].modifier_key, isCapsused) + " " + uniqueC2Rules[k].key + "] °°-> \'" + new TextDecoder().decode(uniqueC2Rules[k].deadkeyed_Ch) + "\'" + data += "new: [" + unique_C2_Rules[k].modifier_deadkey + " " + unique_C2_Rules[k].deadkey + "] > XXX" + + " [" + unique_C2_Rules[k].modifier_key + " " + unique_C2_Rules[k].key + "] °°-> \'" + new TextDecoder().decode(unique_C2_Rules[k].deadkeyed_Ch) + "\'" } else { - /* data += warningtext + " [" + this.create_kmn_modifier(uniqueC2Rules[k].modifier_deadkey, isCapsused) + " " + uniqueC2Rules[k].deadkey + "] > dk(C" + String(uniqueC2Rules[k].dk_C2) + ")\n" - data += warningtext + " dk(C" + String(uniqueC2Rules[k].dk_C2) + ") [" + this.create_kmn_modifier(uniqueC2Rules[k].modifier_key, isCapsused) + " " + uniqueC2Rules[k].key + "] > \'" + new TextDecoder().decode(uniqueC2Rules[k].deadkeyed_Ch) + "\'\n" - */ - data += warningtext + " [" + this.create_kmn_modifier(uniqueC2Rules[k].modifier_deadkey, isCapsused) + " " + uniqueC2Rules[k].deadkey + "] > XXX" + - "[" + this.create_kmn_modifier(uniqueC2Rules[k].modifier_key, isCapsused) + " " + uniqueC2Rules[k].key + "] > \'" + new TextDecoder().decode(uniqueC2Rules[k].deadkeyed_Ch) + "\'" + data += warningtext + " [" + unique_C2_Rules[k].modifier_deadkey + " " + unique_C2_Rules[k].deadkey + "] > XXX" + + "[" + unique_C2_Rules[k].modifier_key + " " + unique_C2_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_C2_Rules[k].deadkeyed_Ch) + "\'" } } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // ~~~~ draft print ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~ draft print end ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ else { if (warningtext === "c C2 WARNING: ") { - data += " [" + this.create_kmn_modifier(uniqueC2Rules[k].modifier_deadkey, isCapsused) + " " + uniqueC2Rules[k].deadkey + "] > dk(C" + String(uniqueC2Rules[k].dk_C2) + ")\n" - data += " dk(C" + String(uniqueC2Rules[k].dk_C2) + ") [" + this.create_kmn_modifier(uniqueC2Rules[k].modifier_key, isCapsused) + " " + uniqueC2Rules[k].key + "] °°-> \'" + new TextDecoder().decode(uniqueC2Rules[k].deadkeyed_Ch) + "\'\n" + data += "+ [" + unique_C2_Rules[k].modifier_deadkey + " " + unique_C2_Rules[k].deadkey + "] > dk(C" + String(unique_C2_Rules[k].dk_C2) + ")\n" + data += "dk(C" + String(unique_C2_Rules[k].dk) + ") + [" + unique_C2_Rules[k].modifier_key + " " + unique_C2_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_C2_Rules[k].deadkeyed_Ch) + "\'\n" } else { - data += warningtext + " [" + this.create_kmn_modifier(uniqueC2Rules[k].modifier_deadkey, isCapsused) + " " + uniqueC2Rules[k].deadkey + "] > dk(C" + String(uniqueC2Rules[k].dk_C2) + ")\n" - data += warningtext + " dk(C" + String(uniqueC2Rules[k].dk_C2) + ") [" + this.create_kmn_modifier(uniqueC2Rules[k].modifier_key, isCapsused) + " " + uniqueC2Rules[k].key + "] > \'" + new TextDecoder().decode(uniqueC2Rules[k].deadkeyed_Ch) + "\'\n" + data += warningtext + " [" + unique_C2_Rules[k].modifier_deadkey + " " + unique_C2_Rules[k].deadkey + "] > dk(C" + String(unique_C2_Rules[k].dk_C2) + ")\n" + data += warningtext + " dk(C" + String(unique_C2_Rules[k].dk_C2) + ") [" + unique_C2_Rules[k].modifier_key + " " + unique_C2_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_C2_Rules[k].deadkeyed_Ch) + "\'\n" } } data += "\n" @@ -2186,57 +1969,46 @@ console.log(" b5_actionId", b5_actionId) data += "\n########## C3 #################################################################\n" } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // ~~~~ draft print ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~ draft print end ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - for (let k = 0; k < uniqueC3Rules.length; k++) { - if ((uniqueC3Rules[k].rule_type === "C3")) { + for (let k = 0; k < unique_C3_Rules.length; k++) { + if ((unique_C3_Rules[k].rule_type === "C3")) { let warningtext = "c C3 WARNING: " - warningtext = warningtext + this.findDuplicateRule_allC(uniqueC3Rules, k, "C3", isCapsused) // OK - warningtext = warningtext + this.findAmbiguousRule_allC(uniqueC3Rules, k, "C3", isCapsused) // OK - warningtext = warningtext + this.findUnAvailableRule(uniqueC3Rules, k, isCapsused) // OK + warningtext = warningtext + this.findDuplicateRules(unique_C3_Rules, k, "C3") // OK + warningtext = warningtext + this.findAmbiguousRules(unique_C3_Rules, k, "C3") // OK + warningtext = warningtext + this.findUnAvailableRule(unique_C3_Rules, k) // OK // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~ draft print ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (KeylayoutToKmnConverter.print_draft) { if (warningtext === "c C3 WARNING: ") { - /* data += " [" + this.create_kmn_modifier(uniqueC3Rules[k].modifier_prev_deadkey, isCapsused) + " " + uniqueC3Rules[k].prev_deadkey + "] > dk(A" + String(uniqueC3Rules[k].dk_prev) + ")\n" - data += " dk(A" + String(uniqueC3Rules[k].dk_prev) + ") + [" + this.create_kmn_modifier(uniqueC3Rules[k].modifier_deadkey, isCapsused) + " " + uniqueC3Rules[k].deadkey + "] > dk(B" + String(uniqueC3Rules[k].dk) + ")\n" - data += " dk(B" + String(uniqueC3Rules[k].dk) + ") [" + this.create_kmn_modifier(uniqueC3Rules[k].modifier_key, isCapsused) + " " + uniqueC3Rules[k].key + "] °°-> \'" + new TextDecoder().decode(uniqueC3Rules[k].deadkeyed_Ch) + "\'\n" - */ - data += " [" + this.create_kmn_modifier(uniqueC3Rules[k].modifier_prev_deadkey, isCapsused) + " " + uniqueC3Rules[k].prev_deadkey + "] > XXX " + - "[" + this.create_kmn_modifier(uniqueC3Rules[k].modifier_deadkey, isCapsused) + " " + uniqueC3Rules[k].deadkey + "] > YYY " + - " [" + this.create_kmn_modifier(uniqueC3Rules[k].modifier_key, isCapsused) + " " + uniqueC3Rules[k].key + "] °°-> \'" + new TextDecoder().decode(uniqueC3Rules[k].deadkeyed_Ch) + "\'" - + data += " [" + unique_C3_Rules[k].modifier_prev_deadkey + " " + unique_C3_Rules[k].prev_deadkey + "] > XXX " + + "[" + unique_C3_Rules[k].modifier_deadkey + " " + unique_C3_Rules[k].deadkey + "] > YYY " + + " [" + unique_C3_Rules[k].modifier_key + " " + unique_C3_Rules[k].key + "] °°-> \'" + new TextDecoder().decode(unique_C3_Rules[k].deadkeyed_Ch) + "\'" } else { - /* data += warningtext + " [" + this.create_kmn_modifier(uniqueC3Rules[k].modifier_prev_deadkey, isCapsused) + " " + uniqueC3Rules[k].prev_deadkey + "] > dk(A" + String(uniqueC3Rules[k].dk_prev) + ")\n" - data += warningtext + " dk(A" + String(uniqueC3Rules[k].dk_prev) + ") + [" + this.create_kmn_modifier(uniqueC3Rules[k].modifier_deadkey, isCapsused) + " " + uniqueC3Rules[k].deadkey + "] > dk(B" + String(uniqueC3Rules[k].dk) + ")\n" - data += warningtext + " dk(B" + String(uniqueC3Rules[k].dk) + ") [" + this.create_kmn_modifier(uniqueC3Rules[k].modifier_key, isCapsused) + " " + uniqueC3Rules[k].key + "] **°°-> \'" + new TextDecoder().decode(uniqueC3Rules[k].deadkeyed_Ch) + "\'\n" - */ - data += warningtext + " [" + this.create_kmn_modifier(uniqueC3Rules[k].modifier_prev_deadkey, isCapsused) + " " + uniqueC3Rules[k].prev_deadkey + "] > XXX " + - "[" + this.create_kmn_modifier(uniqueC3Rules[k].modifier_deadkey, isCapsused) + " " + uniqueC3Rules[k].deadkey + "] > YYY " + - " [" + this.create_kmn_modifier(uniqueC3Rules[k].modifier_key, isCapsused) + " " + uniqueC3Rules[k].key + "] °°-> \'" + new TextDecoder().decode(uniqueC3Rules[k].deadkeyed_Ch) + "\'" - - + data += warningtext + " [" + unique_C3_Rules[k].modifier_prev_deadkey + " " + unique_C3_Rules[k].prev_deadkey + "] > XXX " + + "[" + unique_C3_Rules[k].modifier_deadkey + " " + unique_C3_Rules[k].deadkey + "] > YYY " + + " [" + unique_C3_Rules[k].modifier_key + " " + unique_C3_Rules[k].key + "] °°-> \'" + new TextDecoder().decode(unique_C3_Rules[k].deadkeyed_Ch) + "\'" } } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // ~~~~ draft print ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~ draft print end ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ else { if (warningtext === "c C3 WARNING: ") { - data += " [" + this.create_kmn_modifier(uniqueC3Rules[k].modifier_prev_deadkey, isCapsused) + " " + uniqueC3Rules[k].prev_deadkey + "] > dk(A" + String(uniqueC3Rules[k].dk_prev) + ")\n" - data += " dk(A" + String(uniqueC3Rules[k].dk_prev) + ") + [" + this.create_kmn_modifier(uniqueC3Rules[k].modifier_deadkey, isCapsused) + " " + uniqueC3Rules[k].deadkey + "] > dk(B" + String(uniqueC3Rules[k].dk) + ")\n" - data += " dk(B" + String(uniqueC3Rules[k].dk) + ") [" + this.create_kmn_modifier(uniqueC3Rules[k].modifier_key, isCapsused) + " " + uniqueC3Rules[k].key + "] °°-> \'" + new TextDecoder().decode(uniqueC3Rules[k].deadkeyed_Ch) + "\'\n" + data += "+ [" + this.create_kmn_modifier(unique_C3_Rules[k].modifier_prev_deadkey, isCapsused) + " " + unique_C3_Rules[k].prev_deadkey + "] > dk(A" + String(unique_C3_Rules[k].dk_prev) + ")\n" + data += "dk(A" + String(unique_C3_Rules[k].dk_prev) + ") + [" + this.create_kmn_modifier(unique_C3_Rules[k].modifier_deadkey, isCapsused) + " " + unique_C3_Rules[k].deadkey + "] > dk(B" + String(unique_C3_Rules[k].dk) + ")\n" + data += "dk(B" + String(unique_C3_Rules[k].dk) + ") + [" + this.create_kmn_modifier(unique_C3_Rules[k].modifier_key, isCapsused) + " " + unique_C3_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_C3_Rules[k].deadkeyed_Ch) + "\'\n" } else { - data += warningtext + " [" + this.create_kmn_modifier(uniqueC3Rules[k].modifier_prev_deadkey, isCapsused) + " " + uniqueC3Rules[k].prev_deadkey + "] > dk(A" + String(uniqueC3Rules[k].dk_prev) + ")\n" - data += warningtext + " dk(A" + String(uniqueC3Rules[k].dk_prev) + ") + [" + this.create_kmn_modifier(uniqueC3Rules[k].modifier_deadkey, isCapsused) + " " + uniqueC3Rules[k].deadkey + "] > dk(B" + String(uniqueC3Rules[k].dk) + ")\n" - data += warningtext + " dk(B" + String(uniqueC3Rules[k].dk) + ") [" + this.create_kmn_modifier(uniqueC3Rules[k].modifier_key, isCapsused) + " " + uniqueC3Rules[k].key + "] **°°-> \'" + new TextDecoder().decode(uniqueC3Rules[k].deadkeyed_Ch) + "\'\n" + data += warningtext + " [" + this.create_kmn_modifier(unique_C3_Rules[k].modifier_prev_deadkey, isCapsused) + " " + unique_C3_Rules[k].prev_deadkey + "] > dk(A" + String(unique_C3_Rules[k].dk_prev) + ")\n" + data += warningtext + " dk(A" + String(unique_C3_Rules[k].dk_prev) + ") + [" + this.create_kmn_modifier(unique_C3_Rules[k].modifier_deadkey, isCapsused) + " " + unique_C3_Rules[k].deadkey + "] > dk(B" + String(unique_C3_Rules[k].dk) + ")\n" + data += warningtext + " dk(B" + String(unique_C3_Rules[k].dk) + ") + [" + this.create_kmn_modifier(unique_C3_Rules[k].modifier_key, isCapsused) + " " + unique_C3_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_C3_Rules[k].deadkeyed_Ch) + "\'\n" } } data += "\n" @@ -2246,6 +2018,34 @@ console.log(" b5_actionId", b5_actionId) return data } + /// console log all entries + public writeDalaset(unique_C3_Rules: any) { + for (let i = 0; i < unique_C3_Rules.length; i++) { + + console.log("unique_C3_Rules ", unique_C3_Rules.length, i, + + unique_C3_Rules[i].rule_type !== "" ? unique_C3_Rules[i].rule_type : "--".padEnd(4, " "), + + + "| ", (unique_C3_Rules[i].modifier_prev_deadkey !== "" ? unique_C3_Rules[i].modifier_prev_deadkey.padEnd(33, " ") : "--".padEnd(33, " ")), + (unique_C3_Rules[i].prev_deadkey !== "" ? unique_C3_Rules[i].prev_deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), + (unique_C3_Rules[i].dk_prev !== 0 ? ("dk(A" + String(unique_C3_Rules[i].dk_prev) + ")").padEnd(11, " ") : "--".padEnd(11, " ")), + + + (unique_C3_Rules[i].modifier_deadkey !== "" ? unique_C3_Rules[i].modifier_deadkey.padEnd(30, " ") : "--".padEnd(30, " ")), + (unique_C3_Rules[i].deadkey !== "" ? unique_C3_Rules[i].deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), + (unique_C3_Rules[i].dk !== 0 ? ("dk(B" + String(unique_C3_Rules[i].dk) + ")").padEnd(9, " ") : "--".padEnd(9, " ")), + + + "| ", (unique_C3_Rules[i].modifier_key !== "" ? unique_C3_Rules[i].modifier_key.padEnd(40, " ") : "--".padEnd(40, " ")), + (unique_C3_Rules[i].key !== "" ? unique_C3_Rules[i].key.padEnd(8, " ") : "--".padEnd(8, " ")), + (new TextDecoder().decode(unique_C3_Rules[i].deadkeyed_Ch) !== "" ? new TextDecoder().decode(unique_C3_Rules[i].deadkeyed_Ch).padEnd(10, " ") : ("--" + unique_C3_Rules[i].deadkeyed_Ch) + "--"), + + "| °°") + } + + } + public createData_Stores(data_ukelele: convert_object): string { let data: string = "" @@ -2259,10 +2059,10 @@ console.log(" b5_actionId", b5_actionId) data += "\n" data += '\########## OK #################################################################\n' - data += "store(&VERSION) \'...\'\n" + data += "store(&VERSION) \'10.0\'\n" data += "store(&TARGETS) \'any\'\n" - data += "store(&KEYBOARDVERSION) \'...\'\n" - data += "store(©RIGHT) '© 2024 SIL International\n" + data += "store(&KEYBOARDVERSION) \'1.0\'\n" + data += "store(©RIGHT) '© 2024 SIL International\'\n" // TODO what else ?? data += '\########## OK #################################################################\n' @@ -2276,7 +2076,7 @@ console.log(" b5_actionId", b5_actionId) data += "\n" } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // ~~~~ draft print ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~ draft print end ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ else { data += "c\n" @@ -2284,10 +2084,10 @@ console.log(" b5_actionId", b5_actionId) data += "c\n" data += "\n" - data += "store(&VERSION) \'...\'\n" + data += "store(&VERSION) \'10.0\'\n" data += "store(&TARGETS) \'any\'\n" - data += "store(&KEYBOARDVERSION) \'...\'\n" - data += "store(©RIGHT) '© 2024 SIL International\n" + data += "store(&KEYBOARDVERSION) \'1.0\'\n" + data += "store(©RIGHT) '© 2024 SIL International\'\n" // TODO what else ?? data += "\n" @@ -2298,36 +2098,8 @@ console.log(" b5_actionId", b5_actionId) } return data } - } -/* /// console log all entries - - for(let i=0;i Date: Fri, 31 Jan 2025 17:26:18 +0100 Subject: [PATCH 045/251] feat(developer): kmc-convert tidy up, add variable types --- .../keylayout-to-kmn-converter.ts | 1235 +++++++---------- 1 file changed, 534 insertions(+), 701 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index d3beb841e8b..6316d6cf3c8 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -28,9 +28,9 @@ import boxXmlArray = util.boxXmlArray;*/ // import { makePathToFixture } from '../../test/helpers/index.js'; // OK Mapping 0->30 or 0->K_A-> missing entries in mapping // OK Replace any-types - // Several steps action-> action-> action->character ( not only action->character) - // TODO waht about using actions twice in a row??? - // Usable for all keylayout files + // OK Several steps action-> action-> action->character ( not only action->character) + // TODO waht about using actions twice in a row??? -> error msg if chain >4 + // OK Usable for all keylayout files // Return conditions // OK Use callbacks as for writeFileSync // Tests throws @@ -45,19 +45,28 @@ import boxXmlArray = util.boxXmlArray;*/ // false arrangement of tags ? // OK no added NCAPS when first modifier in modifierMap does not contain "caps" or"caps?" // use length to clear array instead of defining evetry time new (modifierMap_ONE_InKeymapSelect.length=0 - // naming of for-loop var i,j,k?... + // OK naming of for-loop var i,j,k?... // warning if contrADICTING RULES E:G: [ 'modifier_C0', 'SHIFT NCAPS', 'K_C', 'c'], vs [ 'modifier_C0', 'SHIFT NCAPS', 'K_C', 'C' ], - // OK print NCAPS as the first of the modifiers in create_kmn_modifier + // OK print NCAPS as the first of the modifiers in create_kmn_modifier // use boxXmlArray from codebase instead of my own - // where are rules for action+none ( a, e, u, etc) - // order of object member var + // OK where are rules for action+none ( a, e, u, etc) + // OK order of object member var // readfilesync with paths better way? // rearrange code to use read, convert, write - // remove all any // TODO rewrite explanantion for object instead of array // remove all any types - // let push_count = 0 // Todo remove later - // check code for code styses keyman + // check code for code styles keyman + // public dk: number, //todo remove one + // todo use from elsewhere boxXmlArray_S + // prev_deadkeys_Ch: Uint8Array, /* Todo needed?*/ + // Todo remove print_draft + // TODO throws + // Todo files/path !!! + // TODO need to use export const USVirtualKeyCodes here + // start Tests v ToDo remove...................................... + // TODO remove: test files: checkif kmn gats the same output as ukelele file(except for C3 t works well :)) + // ToDo needed methods + // Filter functions use the same type } import { XMLParser } from 'fast-xml-parser'; // for reading a file @@ -126,7 +135,6 @@ function boxArrays_S(source: any) { export interface rule_object { rule_type: string, /* rule type C0-C4 */ - isTerminator: boolean, /* is this a terminator rule */ modifier_prev_deadkey: string, /* string of modifiers for the first key (e.g. "NCAPS RALT CTRL") */ prev_deadkey: string, /* name of the first key (e.g. K_U) */ @@ -137,10 +145,11 @@ export interface rule_object { deadkey: string, /* name of the second key */ deadkeys_Ch: Uint8Array, /* Todo needed?*/ dk: number, /* Todo needed?*/ + dk_C2: number, modifier_key: string, /* string of modifiers for the third key (e.g. "NCAPS RALT CTRL") */ key: string, /* name of the third key (e.g. K_U) */ - deadkeyed_Ch: Uint8Array, /* the output character */ + output: Uint8Array, /* the output character */ }; export interface convert_object { @@ -154,7 +163,8 @@ export class KeylayoutToKmnConverter { static readonly OUTPUT_FILE_EXTENSION = '.kmn'; //Todo remove print_draft - static print_draft = false + static print_draft = true + static used_Keys_count = 50 // TODO use callbacks what about /*private*/ for options //constructor(/*private*/ _callbacks: CompilerCallbacks, /*private*/ _options: CompilerOptions) { @@ -191,7 +201,7 @@ export class KeylayoutToKmnConverter { console.log(' _S2 then WRITE to kmn .....................................'); - const out = this.write(outArray) + const out: boolean = this.write(outArray) if (!out) { return null; } @@ -274,18 +284,18 @@ export class KeylayoutToKmnConverter { //TODO need to use export const USVirtualKeyCodes here public write(data_ukelele: convert_object): boolean { console.log("\n###################################################\n") - let data = "\n" + let data: string = "\n" // add top part of kmn file: STORES data += this.createData_Stores(data_ukelele) - // add middle part of kmn file: RULES + // add lower part of kmn file: RULES data += this.createData_Rules(data_ukelele) - // add bottom part of kmn file: DEADKEYS - // data += this.createData_Deadkeys(data_ukelele) - - data += "\n" + console.log("##################################################################################################################\n", + "kmn output looks like that :################################################################################################\n", + data, + "############################################################################################################################\n") /*writeFileSync("data/MyResult.kmn", data, { flag: "w" })*/ this.callbacks.fs.writeFileSync("data/MyResult.kmn", new TextEncoder().encode(data)) // not usable here since it takes UInt8array data @@ -302,29 +312,24 @@ export class KeylayoutToKmnConverter { // for more info about mapping and cases C0-C4 see https://docs.google.com/document/d/1ISjACTA9aUBueTo1AoKnOsI6QR5kXeeD_maI0XUyXqg/edit?tab=t.0 public createRuleData(data_ukelele: convert_object, jsonObj: any): convert_object { - const ObjectArray: any[] = [] - let dk_counter_C3_A = 0 - let dk_counter_C3_B = 0 - let dk_counter_C2 = 0 - let C2_count = 0 + const ObjectArray: rule_object[] = [] + let dk_counter_C3_A: number = 0 + let dk_counter_C3_B: number = 0 + let dk_counter_C2: number = 0 // start Tests v ToDo remove...................................... - const testArray_Ukelele: string[] = [] + /*const testArray_Ukelele: string[] = [] let testArray_Ukelele_count = 0 const testArray_Ukelele_action: string[] = [] let testArray_Ukelele_action_count = 0 - const testArray_kmn: string[] = [] - // const testArray_kmn_action: string[] = [] - const testArray_kmn_action1: string[] = [] + //const testArray_kmn_action1: string[] = [] let testArray_kmn_count = 0 - // let testArray_kmn_action_count = 0 - // loop behaviors ( in ukelele it is possible to define multiple modifier combinations that behave in the same) for (let i = 0; i < jsonObj.keyboard.keyMapSet[0].keyMap.length; i++) { // loop keys 0-50 (= all keys we use) - for (let j = 0; j < 51; j++) { + for (let j = 0; j <= KeylayoutToKmnConverter.used_Keys_count; j++) { if ((jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] !== undefined)) { testArray_Ukelele.push(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output']) @@ -340,20 +345,20 @@ export class KeylayoutToKmnConverter { testArray_Ukelele_action_count++ } } - } + }*/ // End Tests ToDo remove ^....................................... - let action_id - const used_Keys_count = 51 + let action_id: string - const isCapsused = this.checkIfCapsUsed(data_ukelele.ArrayOf_Modifiers) + const isCapsused: boolean = this.checkIfCapsUsed(data_ukelele.ArrayOf_Modifiers) // loop keys 0-50 (= all keys we use) - for (let j = 0; j < used_Keys_count; j++) { + for (let j = 0; j <= KeylayoutToKmnConverter.used_Keys_count; j++) { // loop behaviors ( in ukelele it is possible to define multiple modifier combinations that behave in the same) for (let i = 0; i < jsonObj.keyboard.keyMapSet[0].keyMap.length; i++) { + let RuleObj: rule_object // ...................................................................................................... // case C0: output ...................................................................................... @@ -361,36 +366,33 @@ export class KeylayoutToKmnConverter { // ...............e. g. ...................................................... // ...................................................................................................... - let RuleObj - if ((jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] !== undefined)) { - testArray_kmn.push(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output']) - testArray_kmn_count++ + // testArray_kmn.push(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output']) + // testArray_kmn_count++ if (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] !== "") { - // loop modifier combinations + // loop behaviours for (let l = 0; l < data_ukelele.ArrayOf_Modifiers[i].length; l++) { if (this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']))) { RuleObj = new Rules( - "C0", - false, - - "", - "", - new TextEncoder().encode(""), - 0, - - "", - "", - new TextEncoder().encode(""), - 0, - 0, - - this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[i][l], isCapsused), - this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), - new TextEncoder().encode(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output']), + /* rule_type */ "C0", + + /* modifier_prev_deadkey*/ "", + /* prev_deadkey */ "", + /* prev_deadkeys_Ch*/ new TextEncoder().encode(""), + /* dk_prev */ 0, + + /* modifier_deadkey */ "", + /* deadkey */ "", + /* deadkeys_Ch */ new TextEncoder().encode(""), + /* dk*/ 0, + /* dk for C2*/ 0, + + /* modifier_key*/ this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[i][l], isCapsused), + /* key */ this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), + /* output */ new TextEncoder().encode(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output']), ) if (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] !== "") ObjectArray.push(RuleObj) @@ -398,9 +400,10 @@ export class KeylayoutToKmnConverter { } } } - else if (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] !== undefined) { + action_id = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] + // ...................................................................................................... // case C1: action + state none + output ................................................................ // a key is mapped to an action and then to an output ................................................... @@ -408,263 +411,194 @@ export class KeylayoutToKmnConverter { // ...............e. g. ..................................................... + // case C2: action + none + next ........................................................................ + // ...............e. g. ................................................... // replace state x with all rules that result in 14 (action->action(state)->action(next)->terminator(output) ........................................ - // Action:state -> Action:state -> Action:id -> KeyMap:action -> keyMap:code (first dk) ................. - // Action:id -> KeyMap:action -> keyMap:code (second dk) ................................................ - // Action:next -> Action:state -> action:output ......................................................... - // Action:id -> KeyMap:action -> keyMap:code (key) ...................................................... - // ...................................................................................................... - - // get a9 in behavior/key - action_id = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] - const actionIdIndexC2 = this.get_ActionID_Index__From__ActionID_Id(jsonObj, action_id) + // ...................................................................................................... + // Definition of Blocks 1-6 see ......................................................................... + // https://docs.google.com/document/d/1ISjACTA9aUBueTo1AoKnOsI6QR5kXeeD_maI0XUyXqg/edit?tab=t.0 ......... + // ...................................................................................................... + + const actionIdIndex2: number = this.get_ActionID_Index__From__ActionID_Id(jsonObj, action_id) // loop all action-when and find state-next-pair - for (let l = 0; l < jsonObj.keyboard.actions.action[actionIdIndexC2].when.length; l++) { - - // state_none data - if ((jsonObj.keyboard.actions.action[actionIdIndexC2].when[l]['@_state'] === "none") - && (jsonObj.keyboard.actions.action[actionIdIndexC2].when[l]['@_next'] !== undefined)) { - - - // Data of Block Nr 5 .......................................................... - /* eg: state = none */ // const b5_value_state = jsonObj.keyboard.actions.action[actionIdIndexC2].when[l]['@_state'] - /* eg: next = 1 */ const b5_value_next = jsonObj.keyboard.actions.action[actionIdIndexC2].when[l]['@_next'] - /* eg: StateNextID = a18 */ const b5_actionId = jsonObj.keyboard.actions.action[actionIdIndexC2]['@_id'] - // ............................................................................. - console.log(" Block 5 action_id", action_id, b5_value_next, actionIdIndexC2, b5_actionId) - - // Data of Block Nr 4 .......................................................... - /* eg: key codes [ '24', '24' ]*/ const b4_code_arr = this.get_KeyMap_Code_array__From__KeyMap_Action(jsonObj, b5_actionId) - ///* eg: mod 0 */ const b4_behaviourId = this.get_KeyMap_Index__From__KeyMap_Action(jsonObj, b5_actionId) - // /* eg: [[0,24,a18],[3,24,a18]] */ const b4_behaviour_id_arr = this.get_KeyMap_IndexCodeAction_array__From__KeyMap_Action(jsonObj, b5_actionId) - // /* eg: ['CAPS', 'RALT'] */ const b4_modifier_arr = this.get_data_From__KeyMap_Modifier_Index(data_ukelele.ArrayOf_Modifiers, b4_behaviourId) - /* eg: [['CAPS','RALT'],['CAPS']] */ //const b4_modifier2D_array = this.get_KeyMap_IndexCodeAction_array__From__KeyMap_Action_Array(jsonObj, b4_behaviour_id_arr) - /* eg: [['24', 0], ['24', 3]] */ const b2_keyBehaviour_arr = this.get_KeyMap_Code_array__From__ActionID_Action(jsonObj, String(action_id)) - /* e.g. [[ '','caps?'], ['Caps']]*/ const b4_modifier2D_array = this.get_KeyMap_Modifier_array__From__behaviour_arr(data_ukelele.ArrayOf_Modifiers, b2_keyBehaviour_arr) - // ............................................................................. - - - // Data of Block Nr 3 .......................................................... - /* eg: actioniD = a17 */ //const b3_actionId = this.get_ActionID_Id__From__ActionID_next(jsonObj, b5_value_state) - // ............................................................................. - - // Data of Block Nr 2 .......................................................... - /* eg: ['K_8', 'K_M] */ //const b2_keyname_arr = this.get_KecCode_arr__From__ActionId(jsonObj, b3_actionId) - /* eg: index=3 */ // const b2_keyBehaviour_arr = this.get_KeyMap_Code_array__From__ActionID_Action(jsonObj, String(b3_actionId)) - /* e.g. [[ '0','1shift? caps?']]*/ // const b2_modifier_arr_all = this.get_KeyMap_Modifier_array__From__behaviour_arr(data_ukelele.ArrayOf_Modifiers, b2_keyBehaviour_arr) - // ............................................................................. - - // Data of Block Nr 6 .......................................................... - /* eg: [ 'a9','1','â'] */ const b6_actionId_arr = this.get_ActionID_Output_array__From__ActionID_State(jsonObj, b5_value_next) - // ............................................................................. - - // Data of Block Nr 1 .......................................................... - /* eg: ['49','K_SPACE','a0','0'] */ const b1_keycode_arr = this.get_KeyMap_Code_array__From__KeyMap_Action_array2D(jsonObj, b6_actionId_arr) - - // ............................................................................. - - for (let n1 = 0; n1 < b6_actionId_arr.length; n1++) { - for (let n2 = 0; n2 < b1_keycode_arr.length; n2++) { - if (b6_actionId_arr[n1][0] === b1_keycode_arr[n2][2]) { - for (let n3 = 0; n3 < data_ukelele.ArrayOf_Modifiers[Number(b1_keycode_arr[n2][3])].length; n3++) { - //somewhere the loop throughh b4_modifier_arr does not work!! - for (let n4 = 0; n4 < b4_modifier2D_array.length; n4++) { - for (let n4x = 0; n4x < b4_modifier2D_array[n4].length; n4x++) { - // console.log("b4_modifier2D_array[n4][n4x] ",b4_modifier2D_array[n4][n4x] ) - - // for (let x5 = 0; x5 < b2_modifier_arr_all.length; x5++) { - // for (let n6 = 0; n6 < b2_modifier_arr_all[x5].length; n6++) { - for (let n7 = 0; n7 < b4_code_arr.length; n7++) { - // for (let n8 = 0; n8 < b2_keyname_arr.length; n8++) { - C2_count++ - RuleObj = new Rules( - /* OK rule_type */ "C2", - /* OK isTerminator */ false, - - /* OK modifier_prev_deadkey*/ "", - /* OK prev_deadkey */ "", - /* prev_deadkeys_Ch*/ new TextEncoder().encode(""), - /* OK dk_prev */ 0, - - /* OK modifier_deadkey */ this.create_kmn_modifier(b4_modifier2D_array[n4][n4x], isCapsused), - /* OK deadkey */ this.map_UkeleleKC_To_VK(Number(b4_code_arr[n7])), - /* deadkeys_Ch */ new TextEncoder().encode(""), - /* OK dk*/ dk_counter_C2++, - /* OK dk for C2*/ 0, - - /* OK modifier_key*/ this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[Number(b1_keycode_arr[n2][3])][n3], isCapsused), - /* OK key */ b1_keycode_arr[n2][1], - /* OK deadkeyed_Ch */ new TextEncoder().encode(b6_actionId_arr[n1][2]) - ) + for (let l = 0; l < jsonObj.keyboard.actions.action[actionIdIndex2].when.length; l++) { - if (b6_actionId_arr[n1][2] !== undefined) - ObjectArray.push(RuleObj) - } - } - // } - // } - // } - } + // find state ="none" - next data + if ((jsonObj.keyboard.actions.action[actionIdIndex2].when[l]['@_state'] === "none") + && (jsonObj.keyboard.actions.action[actionIdIndex2].when[l]['@_next'] !== undefined)) { + + // Data of Block Nr 5 .................................................................................................................... + /* eg: next = 1 */ const b5_value_next: string = jsonObj.keyboard.actions.action[actionIdIndex2].when[l]['@_next'] + /* eg: StateNextID = a16 */ const b5_actionId: string[] = jsonObj.keyboard.actions.action[actionIdIndex2]['@_id'] + // ....................................................................................................................................... + + + // Data of Block Nr 4 .................................................................................................................... + /* eg: [ '6', '31', '32' ]*/ const b4_code_arr: string[] = this.get_KeyMap_Code_array__From__KeyMap_Action(jsonObj, b5_actionId) + /* eg: [['24', 0], ['24', 3]] */ const b4_keyBehaviour_arr: number[][] = this.get_KeyMap_Code_array__From__ActionID_Action(jsonObj, String(action_id)) + /* e.g. [['','caps?'], ['Caps']]*/ const b4_modifier2D_array: string[] = this.get_KeyMap_Modifier_array__From__behaviour_arr(data_ukelele.ArrayOf_Modifiers, b4_keyBehaviour_arr) + // ....................................................................................................................................... + + + // Data of Block Nr 6 .................................................................................................................... + /* eg: [ 'a9','1','â'] */ const b6_actionId_arr: string[][] = this.get_ActionID_Output_array__From__ActionID_State(jsonObj, b5_value_next) + // ....................................................................................................................................... + + + // Data of Block Nr 1 .................................................................................................................... + /* eg: ['49','K_SPACE','a0','0','Â'] */ const b1_keycode_arr: string[][] = this.get_KeyMap_Code_array__From__KeyMap_Action_array2D(jsonObj, b6_actionId_arr) + /* eg: ['K_SPACE','a0','0','NCAPS','Â']*/ const b1_KeyMapModiKeyArray: string[][] = this.get_KeyMapModiKeyArray__from__array(jsonObj, b1_keycode_arr, isCapsused) + // ....................................................................................................................................... + + + for (let n1 = 0; n1 < b4_modifier2D_array.length; n1++) { + for (let n2 = 0; n2 < b4_modifier2D_array[n1].length; n2++) { + for (let n3 = 0; n3 < b4_code_arr.length; n3++) { + for (let n4 = 0; n4 < b1_KeyMapModiKeyArray.length; n4++) { + + RuleObj = new Rules( + /* rule_type */ "C2", + + /* modifier_prev_deadkey*/ "", + /* prev_deadkey */ "", + /* prev_deadkeys_Ch*/ new TextEncoder().encode(""), + /* dk_prev */ 0, + + /* modifier_deadkey */ this.create_kmn_modifier(b4_modifier2D_array[n1][n2], isCapsused), + /* deadkey */ this.map_UkeleleKC_To_VK(Number(b4_code_arr[n3])), + /* deadkeys_Ch */ new TextEncoder().encode(""), + /* dk*/ 0, + /* dk for C2*/ dk_counter_C2++, + + /* modifier_key*/ b1_KeyMapModiKeyArray[n4][3], + /* key */ b1_KeyMapModiKeyArray[n4][0], + /* output */ new TextEncoder().encode(b1_KeyMapModiKeyArray[n4][4]), + ) + if (b1_KeyMapModiKeyArray[n4][4] !== undefined) + ObjectArray.push(RuleObj) } } } } } } + // ...................................................................................................... // case C3: action + state Nr + Next .................................................................... - // ...............e. g. ..................................................... - // replace state x with all rules that result in 14 (action->action(state)->action(next)->terminator(output) ........................................ - // Action:state -> Action:state -> Action:id -> KeyMap:action -> keyMap:code (first dk) ................. - // Action:id -> KeyMap:action -> keyMap:code (second dk) ................................................ - // Action:next -> Action:state -> action:output ......................................................... - // Action:id -> KeyMap:action -> keyMap:code (key) ...................................................... - // ...................................................................................................... - // todo check loop as in b2_keyBehaviour_arr - // get a9 in behavior/key - action_id = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] - const actionIdIndex = this.get_ActionID_Index__From__ActionID_Id(jsonObj, action_id) + // ...............e. g. ....................................................... + // replace state x with all rules that result in 1 ( ................................................... @@ -683,35 +618,30 @@ export class KeylayoutToKmnConverter { // action:id -> keyMap:action -> keyMap:code ( key) ..................................................... // ...................................................................................................... - action_id = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] - - const next_id = this.get_ActionID_Next__From__ActionID_None(jsonObj, action_id) + const next_id: string = this.get_ActionID_Next__From__ActionID_None(jsonObj, action_id) for (let l = 0; l < data_ukelele.ArrayOf_Modifiers[i].length; l++) { - if (new TextEncoder().encode(this.get_Terminator_Output__From__Terminator_State(jsonObj, next_id)).length !== 0) { RuleObj = new Rules( - "C4", - true, - - "", - "", - new TextEncoder().encode(""), - 0, - - "", - "", - new TextEncoder().encode(""), - 0, - 0, - - data_ukelele.ArrayOf_Modifiers[i][l], - this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), - new TextEncoder().encode(this.get_Terminator_Output__From__Terminator_State(jsonObj, next_id)) + /* rule_type */ "C4", + + /* modifier_prev_deadkey*/ "", + /* prev_deadkey */ "", + /* prev_deadkeys_Ch*/ new TextEncoder().encode(""), + /* dk_prev */ 0, + + /* modifier_deadkey */ "", + /* deadkey */ "", + /* deadkeys_Ch */ new TextEncoder().encode(""), + /* dk*/ 0, + /* dk for C2*/ 0, + + /* modifier_key*/ this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[i][l], isCapsused), + /* key */ this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), + /* output */ new TextEncoder().encode(this.get_Terminator_Output__From__Terminator_State(jsonObj, next_id)) ) } - if (this.get_Terminator_Output__From__Terminator_State(jsonObj, next_id) !== "") ObjectArray.push(RuleObj) } @@ -724,57 +654,58 @@ export class KeylayoutToKmnConverter { //--------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------- - // TODO remove: test files: checkif kmn gats the same output as ukelele file(except for C3 t works well :)) + // TODO remove: test files: checkif kmn gets the same output as ukelele file //--------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------- - - //remove entries that are available in both arrays - for (let i = 0; i < (testArray_Ukelele.length); i++) { - for (let j = 0; j < (testArray_kmn.length); j++) { - if (testArray_Ukelele[i] === testArray_kmn[j]) { - testArray_Ukelele[i] = "" - testArray_kmn[j] = "" - } - } - } - // remove empty fields - const testArray_Ukelele_filter = testArray_Ukelele.filter((el) => (el !== "")) - const testArray_kmn_filter = testArray_kmn.filter((el) => (el !== "")) - // should be empty now - if (testArray_kmn_filter.length !== testArray_Ukelele_filter.length) - console.log("OOOOHHHH DIFFERENT AMOUNTS ") - else - console.log("####### SAME AMOUNTS :)) ", - "testArray_kmn_filter:", testArray_kmn_filter, "testArray_Ukelele_filter:", testArray_Ukelele_filter) - - const testArray_Ukelele_action_uni: string[] = testArray_Ukelele_action.filter(function (item, pos, self) { - return self.indexOf(item) == pos; - }) - - //remove entries that are available in both arrays - for (let i = 0; i < (testArray_Ukelele_action_uni.length); i++) { - for (let j = 0; j < (testArray_kmn_action1.length); j++) { - if (testArray_Ukelele_action_uni[i] === testArray_kmn_action1[j]) { - testArray_Ukelele_action_uni[i] = "" - testArray_kmn_action1[j] = "" - } - } - } - // remove empty fields - const testArray_Ukelele_action_uni_filter = testArray_Ukelele_action_uni.filter((el) => (el !== "")) - const testArray_kmn_action_uni_filter = testArray_kmn_action1.filter((el) => (el !== "")) - // should be empty now - if ((testArray_kmn_action_uni_filter.length === 0) && (testArray_Ukelele_action_uni_filter.length === 0)) - console.log("####### SAME AMOUNTS :)) HERE ALSo", - "testArray_kmn_action_uni_filter:", testArray_kmn_action_uni_filter, "testArray_Ukelele_action_uni_filter:", testArray_Ukelele_action_uni_filter) - else - console.log("OOOOHHHH DIFFERENT AMOUNTS ") + /* + //remove entries that are available in both arrays + for (let i = 0; i < (testArray_Ukelele.length); i++) { + for (let j = 0; j < (testArray_kmn.length); j++) { + if (testArray_Ukelele[i] === testArray_kmn[j]) { + testArray_Ukelele[i] = "" + testArray_kmn[j] = "" + } + } + } + // remove empty fields + const testArray_Ukelele_filter = testArray_Ukelele.filter((el) => (el !== "")) + const testArray_kmn_filter = testArray_kmn.filter((el) => (el !== "")) + // should be empty now + if (testArray_kmn_filter.length !== testArray_Ukelele_filter.length) + console.log("OOOOHHHH DIFFERENT AMOUNTS ") + else + console.log("####### SAME AMOUNTS :)) ", + "testArray_kmn_filter:", testArray_kmn_filter, "testArray_Ukelele_filter:", testArray_Ukelele_filter) + + const testArray_Ukelele_action_uni: string[] = testArray_Ukelele_action.filter(function (item, pos, self) { + return self.indexOf(item) == pos; + }) + + //remove entries that are available in both arrays + for (let i = 0; i < (testArray_Ukelele_action_uni.length); i++) { + for (let j = 0; j < (testArray_kmn_action1.length); j++) { + if (testArray_Ukelele_action_uni[i] === testArray_kmn_action1[j]) { + testArray_Ukelele_action_uni[i] = "" + testArray_kmn_action1[j] = "" + } + } + } + // remove empty fields + const testArray_Ukelele_action_uni_filter = testArray_Ukelele_action_uni.filter((el) => (el !== "")) + const testArray_kmn_action_uni_filter = testArray_kmn_action1.filter((el) => (el !== "")) + // should be empty now + if ((testArray_kmn_action_uni_filter.length === 0) && (testArray_Ukelele_action_uni_filter.length === 0)) + console.log("####### SAME AMOUNTS :)) HERE ALSo", + "testArray_kmn_action_uni_filter:", testArray_kmn_action_uni_filter, "testArray_Ukelele_action_uni_filter:", testArray_Ukelele_action_uni_filter) + else + console.log("OOOOHHHH DIFFERENT AMOUNTS ")*/ // test modifiers + /* if (this.create_kmn_modifier("", true) === "NCAPS") console.log("testNr 1 OK "); else console.log("testNr 1 NOT OK - ", (this.create_kmn_modifier("", true))) if (this.create_kmn_modifier("", false) === "") console.log("testNr 2 OK "); else console.log("testNr 2 NOT OK - ", (this.create_kmn_modifier("", false))) if (this.create_kmn_modifier("caps", true) === "CAPS") console.log("testNr 5 OK "); else console.log("testNr 5 NOT OK - ", (this.create_kmn_modifier("caps", true))) @@ -844,10 +775,8 @@ export class KeylayoutToKmnConverter { if (this.create_kmn_modifier("anyShift? caps? anyOption? anyControl", false) === "CTRL") console.log("testNr 52 OK "); else console.log("testNr 52 NOT OK - ", (this.create_kmn_modifier("anyShift? caps? anyOption? anyControl", false))) if (this.create_kmn_modifier("anyShift? caps? anyOption anyControl", false) === "RALT CTRL") console.log("testNr 53 OK "); else console.log("testNr 53 NOT OK - ", (this.create_kmn_modifier("anyShift? caps? anyOption anyControl", false))) if (this.create_kmn_modifier("CAPS", false) === "CAPS") console.log("testNr 531 OK "); else console.log("testNr 531 NOT OK - ", (this.create_kmn_modifier("CAPS", true))) - if (this.create_kmn_modifier("NCAPS", false) === "NCAPS") console.log("testNr 532 OK "); else console.log("testNr 532 NOT OK - ", (this.create_kmn_modifier("NCAPS", true))) - - - + if (this.create_kmn_modifier("shift leftShift caps", false) === "SHIFT CAPS") console.log("testNr 532 OK "); else console.log("testNr 532 NOT OK - ", (this.create_kmn_modifier("shift leftShift caps", false))) + if (this.create_kmn_modifier("shift leftShift caps", true) === "SHIFT CAPS") console.log("testNr 532 OK "); else console.log("testNr 532 NOT OK - ", (this.create_kmn_modifier("shift leftShift caps", true))) console.log("------------------ ") @@ -864,7 +793,7 @@ export class KeylayoutToKmnConverter { if (this.isAcceptableKeymanModifier("rightoption") === false) console.log("testNr A 8 OK "); else console.log("testNr A 8 NOT OK - ", (this.isAcceptableKeymanModifier("rightoption"))) if (this.isAcceptableKeymanModifier("abc") === false) console.log("testNr A 9 OK "); else console.log("testNr A 9 NOT OK - ", (this.isAcceptableKeymanModifier("abc"))) if (this.isAcceptableKeymanModifier("ralt") === true) console.log("testNr A 13 OK "); else console.log("testNr A 13 NOT OK - ", (this.isAcceptableKeymanModifier("ralt"))) - + */ //--------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------- @@ -909,13 +838,29 @@ export class KeylayoutToKmnConverter { } return returnarray } + public get_KeyMap_Behaviour_array__From__KeyMap_Action(data: any, search: string[]): string[][] { + const returnarray2D: string[][] = [] + for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { + for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { + const returnarray: string[] = [] + if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { + returnarray.push(this.map_UkeleleKC_To_VK(Number(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']))) + returnarray.push(data.keyboard.keyMapSet[0].keyMap[i]['@_index']) + returnarray.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action']) + } + if (returnarray.length > 0) + returnarray2D.push(returnarray) + } + } + return returnarray2D + } public get_KeyMap_Code_array__From__KeyMap_Action_array(data: any, search: string[][]): string[] { const returnarray: string[] = [] - for (let k = 0; k < search.length; k++) { - for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { - for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { - if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search[k][0]) { - returnarray.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']) + for (let i = 0; i < search.length; i++) { + for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap.length; j++) { + for (let k = 0; k < data.keyboard.keyMapSet[0].keyMap[j].key.length; k++) { + if (data.keyboard.keyMapSet[0].keyMap[j].key[k]['@_action'] === search[i][0]) { + returnarray.push(data.keyboard.keyMapSet[0].keyMap[j].key[k]['@_code']) } } } @@ -933,6 +878,7 @@ export class KeylayoutToKmnConverter { returnarray.push(this.map_UkeleleKC_To_VK(Number(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']))) returnarray.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action']) returnarray.push(data.keyboard.keyMapSet[0].keyMap[i]['@_index']) + returnarray.push(search[k][2]) } if (returnarray.length > 0) returnarray2D.push(returnarray) @@ -1001,8 +947,8 @@ export class KeylayoutToKmnConverter { } return returnarray2D } - public get_Action2ID_NoneOutput__From__ActionID_Id(data: any, search: any): any { - let OutputValue = "" + public get_Action2ID_NoneOutput__From__ActionID_Id(data: any, search: string): string { + let OutputValue: string = "" for (let i = 0; i < data.keyboard.actions.action.length; i++) { if (data.keyboard.actions.action[i]['@_id'] === search) { for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { @@ -1014,6 +960,54 @@ export class KeylayoutToKmnConverter { } return OutputValue } + + // in a0 + // out: Array:string[][] a0, K_A, behavi, shiftCombo, out, + public get_Datat_array2D__From__ActionID_stateOutput(data: any, modi: any, search: string, outchar: string, isCapsused: boolean): string[][] { + const returnarray2D: string[][] = [] + + // loop behaviors ( in ukelele it is possible to define multiple modifier combinations that behave in the same) + for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { + for (let j = 0; j <= KeylayoutToKmnConverter.used_Keys_count; j++) { + if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { + for (let k = 0; k < modi[data.keyboard.keyMapSet[0].keyMap[i]['@_index']].length; k++) { + const returnarray: string[] = [] + const behaviour: string = data.keyboard.keyMapSet[0].keyMap[i]['@_index'] + const modifierkmn: string = this.create_kmn_modifier(modi[behaviour][k], isCapsused) + const keyName: string = this.map_UkeleleKC_To_VK(Number(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])) + + returnarray.push(search) + returnarray.push(outchar) + returnarray.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action']) + returnarray.push(behaviour) + returnarray.push(keyName) + returnarray.push(modifierkmn) + + if (returnarray.length > 0) + returnarray2D.push(returnarray) + } + } + } + } + + // remove duplicates + const [unique_returnarray] = returnarray2D.reduce((acc, curr) => { + const [uniq, set] = acc; + if (!set.has(curr.join(','))) { + set.add(curr.join(',')); + uniq.push(curr); + } + return acc; + }, + [[], new Set()], + ); + + return unique_returnarray + } + + + + public get_Terminator_Output__From__Terminator_State(data: any, search: string): string { for (let i = 0; i < data.keyboard.terminators.when.length; i++) { if (data.keyboard.terminators.when[i]['@_state'] === search) { @@ -1022,6 +1016,23 @@ export class KeylayoutToKmnConverter { } return "" } + public get_keyModifierArray__from__Action(data: any, search: string): string[][] { + // search is a9 + const returnarray2D: string[][] = [] + for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { + for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { + const returnarray: string[] = [] + if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { + returnarray.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action']) + returnarray.push(this.map_UkeleleKC_To_VK(Number(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']))) + returnarray.push(data.keyboard.keyMapSet[0].keyMap[i]['@_index']) + } + if (returnarray.length > 0) + returnarray2D.push(returnarray) + } + } + return returnarray2D + } // ToDo needed?? public get_ActionID_Output__From__ActionID_IdState(data: any, search_id: string, search_state: string): Uint8Array { @@ -1064,6 +1075,66 @@ export class KeylayoutToKmnConverter { } return returnarray } + public get_KeyMap_Keymaparray__From__KeyMap_Action_array(data: any, search: string): string[][] { + const returnarray: string[][] = [] + for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { + const returnarray1D: string[] = [] + for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { + if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { + returnarray1D.push(search) + returnarray1D.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']) + returnarray1D.push(data.keyboard.keyMapSet[0].keyMap[i]['@_index']) + } + if (returnarray1D.length > 0) + returnarray.push(returnarray1D) + } + } + //ToDo check if I can use this filer somewhere else + const [uniqueElements] = returnarray.reduce((acc, curr) => { + const [uniq, set] = acc; + if (!set.has(curr.join(','))) { + set.add(curr.join(',')); + uniq.push(curr); + } + return acc; + }, + [[], new Set()], + ); + return uniqueElements + } + + + + public get_KeyMapModiKeyArray__from__array(data: any, search: string[][], isCAPSused: boolean): string[][] { + const returnarray: string[][] = [] + + for (let i = 0; i < search.length; i++) { + const behaviour: number = Number(search[i][3]) + + for (let j = 0; j < data.keyboard.modifierMap.keyMapSelect[behaviour].modifier.length; j++) { + const returnarray1D: string[] = [] + returnarray1D.push(search[i][1]) /* KeyName*/ + returnarray1D.push(search[i][2]) /* action*/ + returnarray1D.push(search[i][3]) /* behaviour*/ + returnarray1D.push(this.create_kmn_modifier(data.keyboard.modifierMap.keyMapSelect[behaviour].modifier[j]['@_keys'], isCAPSused)) /* modifier */ + returnarray1D.push(search[i][4]) /* char*/ + if (returnarray1D.length > 0) + returnarray.push(returnarray1D) + } + } + // remove duplicates + const [unique_returnarray] = returnarray.reduce((acc, curr) => { + const [uniq, set] = acc; + if (!set.has(curr.join(','))) { + set.add(curr.join(',')); + uniq.push(curr); + } + return acc; + }, + [[], new Set()], + ); + return unique_returnarray + } // ToDo needed?? public get_KeyMap_Keymaparray__From__KeyMap_Action(data: any, search: string): string[] { const returnarray: string[] = [] @@ -1094,7 +1165,7 @@ export class KeylayoutToKmnConverter { return returnarray2D } // ToDo needed?? get all entries for state= and a given action id - public get_Action2ID_State_arrayState_Array__From__ActionID_Id(data: any, search: any): any[] { + public get_Action2ID_State_arrayState_Array__From__ActionID_Id(data: any, search: string): string[] { const returnarray: string[] = [] for (let i = 0; i < data.keyboard.actions.action.length; i++) { if (data.keyboard.actions.action[i]['@_id'] === search) { @@ -1108,11 +1179,11 @@ export class KeylayoutToKmnConverter { return returnarray } // ToDo needed?? get all entries for state= and a given action id - public get_ActionID_Id_arrayNext_Array__From__ActionID_StateNext(data: any, search: any): string[] { + public get_ActionID_Id_arrayNext_Array__From__ActionID_StateNext(data: any, search: string): string[] { const returnarray: string[] = [] for (let i = 0; i < data.keyboard.actions.action.length; i++) { - for (let kk = 0; kk < data.keyboard.actions.action[i].when.length; kk++) { - if ((data.keyboard.actions.action[i].when[kk]['@_next'] === search) && (data.keyboard.actions.action[i].when[kk]['@_state'] !== "none")) { + for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { + if ((data.keyboard.actions.action[i].when[j]['@_next'] === search) && (data.keyboard.actions.action[i].when[j]['@_state'] !== "none")) { returnarray.push(data.keyboard.actions.action[i]['@_id']) } } @@ -1121,13 +1192,9 @@ export class KeylayoutToKmnConverter { } public map_UkeleleKC_To_VK_array(search: string[]): string[] { const returnarray: string[] = [] - - for (let i = 0; i < search.length; i++) { returnarray.push(this.map_UkeleleKC_To_VK(Number(search[i]))) } - - return returnarray } public get_ActionID_Id__From__ActionID_Next(data: any, search: string) { @@ -1158,19 +1225,19 @@ export class KeylayoutToKmnConverter { } public get_KeyMap_Modifier_array__From__behaviour_arr(data: any, search: number[][]): string[] { const mapIndexArray_max: string[] = [] - for (let j = 0; j < search.length; j++) { - mapIndexArray_max.push(data[search[j][1]]) + for (let i = 0; i < search.length; i++) { + mapIndexArray_max.push(data[search[i][1]]) } return mapIndexArray_max } public get_Modifier_Text__From__Modifier_Index(data: any, search: string): string[] { const mapIndexArray_max: string[] = [] const mapIndexArrayperKey: string[] = [] - for (let j = 0; j < data[search].length; j++) { - mapIndexArrayperKey.push((data[search][j])) + for (let i = 0; i < data[search].length; i++) { + mapIndexArrayperKey.push((data[search][i])) } - for (let j = 0; j < data[search].length; j++) { - mapIndexArray_max.push(data[search][j]) + for (let i = 0; i < data[search].length; i++) { + mapIndexArray_max.push(data[search][i]) } return mapIndexArray_max } @@ -1245,39 +1312,13 @@ export class KeylayoutToKmnConverter { const modifierArray: number[] = [] const modifierArray2D: number[][] = [] - const returnarray2D: string[][] = [] for (let i = 0; i < search.length; i++) { - - console.log("search[i][2] ", search[i][0]) modifierArray.push(Number(search[i][0])) - - console.log("this.get_KeyMap_IndexCodeAction_array__From__KeyMap_Action(data, search[i][0]) ", this.get_KeyMap_IndexCodeAction_array__From__KeyMap_Action(data, search[i][2])) - console.log(" this.get_KeyMap_IndexCodeAction_array__From__KeyMap_Action(data, search[i][0]).flat()", this.get_KeyMap_IndexCodeAction_array__From__KeyMap_Action(data, search[i][2]).flat()) - - - - console.log("returnarray2D ", returnarray2D) - } modifierArray2D.push(modifierArray) - console.log("modifierArray2D ", modifierArray2D) returnarray2D.push(this.get_KeyMap_Modifier_array__From__behaviour_arr(data, modifierArray2D)) - - /* for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { - for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { - const returnarray: string[] = [] - if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { - returnarray.push(data.keyboard.keyMapSet[0].keyMap[i]['@_index']) - returnarray.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']) - returnarray.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action']) - } - if (returnarray.length > 0) { - returnarray2D.push(returnarray) - } - } - }*/ return returnarray2D } public get_KeyMap_ModiIndex_array__From__KeyMap_Action(data: any, search_code: string, search_action: string): string[][] { @@ -1336,9 +1377,9 @@ export class KeylayoutToKmnConverter { */ //ToDo review lower part public create_kmn_modifier(keylayout_modifier: string, isCAPSused: boolean): string { - let add_modifier = "" - let kmn_modifier = "" - let kmn_ncaps = "" + let add_modifier: string = "" + let kmn_modifier: string = "" + let kmn_ncaps: string = "" // copy each modifier seperate element of array const modifier_state: string[] = keylayout_modifier.split(" "); @@ -1348,8 +1389,6 @@ export class KeylayoutToKmnConverter { if (isCAPSused && (String(keylayout_modifier).toUpperCase().indexOf("CAPS") === -1)) kmn_ncaps = " NCAPS " - //if (String(modifier_state[i]).toUpperCase().includes('NCAPS')) add_modifier = "NCAPS "; - // if we find a modifier containing a '?' e.g. SHIFT?: => SHIFT is not neccessary. If it is not neccessary we don`t write this modifier if ((String(modifier_state[i]).toUpperCase().includes('?') && (!String(modifier_state[i]).toUpperCase().includes('CAPS?')))) add_modifier = ""; @@ -1373,11 +1412,11 @@ export class KeylayoutToKmnConverter { // remove duplicate and empty entries const duplicate_modifier_array: string[] = kmn_modifier.split(" ").filter(item => item) const unique_Modifier: string[] = duplicate_modifier_array.filter(function (item, pos, self) { - return self.indexOf(item) == pos; + return self.indexOf(item) === pos; // ToDo == or === ???? }) //ToDo review lower part - const unique_Modifier_string = unique_Modifier.join(" ").replace(/\s+/g, " ").trim() + const unique_Modifier_string: string = unique_Modifier.join(" ").replace(/\s+/g, " ").trim() const modifier_array: string[] = unique_Modifier_string.split(" "); @@ -1395,15 +1434,12 @@ export class KeylayoutToKmnConverter { }) return unique_modifier_array.flat().toString().replace(/,/g, " ") - //return unique_Modifier.join(" ").replace(/\s+/g, " ").trim().toUpperCase() - //return unique_Modifier.join(" ").replace(/\s+/g, " ").trim() - //return unique_Modifier_string } public checkIfCapsUsed(keylayout_modifier: string[][]): boolean { return keylayout_modifier.flat().flat().includes("caps") } public isAcceptableKeymanModifier(keylayout_modifier: string): boolean { - let iskKeymanModifier = true + let iskKeymanModifier: boolean = true const modifier_single: string[] = keylayout_modifier.split(" "); for (let i = 0; i < modifier_single.length; i++) { @@ -1424,25 +1460,22 @@ export class KeylayoutToKmnConverter { } return iskKeymanModifier } - public findDuplicateRules(unique_C0_C1_Rules: any[], index: number, rule_type: string): string { + public findDuplicateRules(unique_C0_C1_Rules: rule_object[], index: number, rule_type: string): string { for (let i = 0; i < index - 1; i++) { if ( - ( - (rule_type === "C01") + ((rule_type === "C01") && unique_C0_C1_Rules[i].modifier_key === unique_C0_C1_Rules[index].modifier_key && unique_C0_C1_Rules[i].key === unique_C0_C1_Rules[index].key && - new TextDecoder().decode(unique_C0_C1_Rules[i].deadkeyed_Ch) === new TextDecoder().decode(unique_C0_C1_Rules[index].deadkeyed_Ch) + new TextDecoder().decode(unique_C0_C1_Rules[i].output) === new TextDecoder().decode(unique_C0_C1_Rules[index].output) ) - || (rule_type === "C2" && unique_C0_C1_Rules[i].modifier_deadkey === unique_C0_C1_Rules[index].modifier_deadkey && unique_C0_C1_Rules[i].deadkey === unique_C0_C1_Rules[index].deadkey && unique_C0_C1_Rules[i].modifier_key === unique_C0_C1_Rules[index].modifier_key && unique_C0_C1_Rules[i].key === unique_C0_C1_Rules[index].key - && new TextDecoder().decode(unique_C0_C1_Rules[i].deadkeyed_Ch) === new TextDecoder().decode(unique_C0_C1_Rules[index].deadkeyed_Ch) + && new TextDecoder().decode(unique_C0_C1_Rules[i].output) === new TextDecoder().decode(unique_C0_C1_Rules[index].output) ) - || (rule_type === "C3" && unique_C0_C1_Rules[i].modifier_prev_deadkey === unique_C0_C1_Rules[index].modifier_prev_deadkey && unique_C0_C1_Rules[i].prev_deadkey === unique_C0_C1_Rules[index].prev_deadkey @@ -1450,35 +1483,33 @@ export class KeylayoutToKmnConverter { && unique_C0_C1_Rules[i].deadkey === unique_C0_C1_Rules[index].deadkey && unique_C0_C1_Rules[i].modifier_key === unique_C0_C1_Rules[index].modifier_key && unique_C0_C1_Rules[i].key === unique_C0_C1_Rules[index].key - && new TextDecoder().decode(unique_C0_C1_Rules[i].deadkeyed_Ch) === new TextDecoder().decode(unique_C0_C1_Rules[index].deadkeyed_Ch) + && new TextDecoder().decode(unique_C0_C1_Rules[i].output) === new TextDecoder().decode(unique_C0_C1_Rules[index].output) ) ) return ("duplicate Rule: old: modif[ modi; " + unique_C0_C1_Rules[i].dk_prev + "[" + unique_C0_C1_Rules[i].modifier_prev_deadkey + " " + unique_C0_C1_Rules[i].prev_deadkey + "] > XXX [" + unique_C0_C1_Rules[i].modifier_deadkey + " " + unique_C0_C1_Rules[i].deadkey + "] > YYY [" + unique_C0_C1_Rules[i].modifier_key + " " + unique_C0_C1_Rules[i].key + - "] °°-> \'" + new TextDecoder().decode(unique_C0_C1_Rules[i].deadkeyed_Ch) + "\' <--> ") + "] °°-> \'" + new TextDecoder().decode(unique_C0_C1_Rules[i].output) + "\' <--> ") } return "" } - public findAmbiguousRules(unique_C0_C1_Rules: any[], index: number, rule_type: string): string { + public findAmbiguousRules(unique_C0_C1_Rules: rule_object[], index: number, rule_type: string): string { for (let i = 0; i < index - 1; i++) { if ( ((rule_type === "C01") && unique_C0_C1_Rules[i].modifier_key === unique_C0_C1_Rules[index].modifier_key && unique_C0_C1_Rules[i].key === unique_C0_C1_Rules[index].key && - new TextDecoder().decode(unique_C0_C1_Rules[i].deadkeyed_Ch) !== new TextDecoder().decode(unique_C0_C1_Rules[index].deadkeyed_Ch) + new TextDecoder().decode(unique_C0_C1_Rules[i].output) !== new TextDecoder().decode(unique_C0_C1_Rules[index].output) ) - || (rule_type === "C2" && unique_C0_C1_Rules[i].modifier_key === unique_C0_C1_Rules[index].modifier_key && unique_C0_C1_Rules[i].key === unique_C0_C1_Rules[index].key && unique_C0_C1_Rules[i].modifier_deadkey === unique_C0_C1_Rules[index].modifier_deadkey && unique_C0_C1_Rules[i].deadkey === unique_C0_C1_Rules[index].deadkey - && new TextDecoder().decode(unique_C0_C1_Rules[i].deadkeyed_Ch) !== new TextDecoder().decode(unique_C0_C1_Rules[index].deadkeyed_Ch) + && new TextDecoder().decode(unique_C0_C1_Rules[i].output) !== new TextDecoder().decode(unique_C0_C1_Rules[index].output) ) - || (rule_type === "C3" && unique_C0_C1_Rules[i].modifier_prev_deadkey === unique_C0_C1_Rules[index].modifier_prev_deadkey && unique_C0_C1_Rules[i].prev_deadkey === unique_C0_C1_Rules[index].prev_deadkey @@ -1486,18 +1517,18 @@ export class KeylayoutToKmnConverter { && unique_C0_C1_Rules[i].deadkey === unique_C0_C1_Rules[index].deadkey && unique_C0_C1_Rules[i].modifier_key === unique_C0_C1_Rules[index].modifier_key && unique_C0_C1_Rules[i].key === unique_C0_C1_Rules[index].key - && new TextDecoder().decode(unique_C0_C1_Rules[i].deadkeyed_Ch) !== new TextDecoder().decode(unique_C0_C1_Rules[index].deadkeyed_Ch) + && new TextDecoder().decode(unique_C0_C1_Rules[i].output) !== new TextDecoder().decode(unique_C0_C1_Rules[index].output) ) ) return ("ambiguous Rule: (old:)[" + unique_C0_C1_Rules[i].modifier_prev_deadkey + " " + unique_C0_C1_Rules[i].prev_deadkey + "] | [" + unique_C0_C1_Rules[i].modifier_deadkey + " " + unique_C0_C1_Rules[i].deadkey + "] > XXX [" + unique_C0_C1_Rules[i].modifier_key + " " + unique_C0_C1_Rules[i].key + - "] °°-> \'" + new TextDecoder().decode(unique_C0_C1_Rules[i].deadkeyed_Ch) + "\' <--> (new:) ") + "] °°-> \'" + new TextDecoder().decode(unique_C0_C1_Rules[i].output) + "\' <--> (new:) ") } return "" } - public findUnAvailableRule(unique_Rules: any[], index: number): string { + public findUnAvailableRule(unique_Rules: rule_object[], index: number): string { if ( (((unique_Rules[index].rule_type === "C0") || (unique_Rules[index].rule_type === "C1") || (unique_Rules[index].rule_type === "C4")) && (this.isAcceptableKeymanModifier(unique_Rules[index].modifier_key))) @@ -1586,217 +1617,24 @@ export class KeylayoutToKmnConverter { //---------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------- - - public createData_Deadkeys(data_ukelele: convert_object): string { - - let data: string = "" - // filter for dk values - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // ~~~~ draft print ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - if (KeylayoutToKmnConverter.print_draft) { - data += '\########## OK #################################################################\n' - data += '\nNOW MY C4 RULES **ccc ********* (only to get 02C6 ect) *********************\n\n' - } - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // ~~~~ draft print end ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - const DeadkeyRules = data_ukelele.ArrayOf_Rules.filter((curr) => { - if (curr.isTerminator === true) { - return curr; - } - return "" - }); - - // remove duplicates - const unique_C0_C1_Rules = DeadkeyRules.reduce((unique, o) => { - if (!unique.some((obj: { deadkeyed_Ch: any; rule_type: any; modifier_key: any; key: any }) => - new TextDecoder().decode(obj.deadkeyed_Ch) === new TextDecoder().decode(o.deadkeyed_Ch) - && obj.key === o.key - && obj.rule_type === o.rule_type - && obj.modifier_key === o.modifier_key) - ) { - unique.push(o); - } - return unique; - }, []); - - - for (let i = 0; i < unique_C0_C1_Rules.length; i++) { - let line: string = "" - line = "+ [" + unique_C0_C1_Rules[i].modifier_key + " " + unique_C0_C1_Rules[i].key + "] > dxk(" + this.getHexFromChar(new TextDecoder().decode(unique_C0_C1_Rules[i].deadkeyed_Ch)) + ")" - data += line + '\n' - } - - - //*************************************************************************************************** */ - /* - How to create rules from keylayout data from data_ukelele.ArrayOf_processed_RuleData: - - There are 6 different types of data entries (C0-C4) in data_ukelele.ArrayOf_processed_RuleData e.g. that contain all data to retrieve deadkeys, deadkeyables and deadkeyed characters: - - C0: (size: 4) ['C0', 'RIGHTSHIFT ', 'K_S', 'S' ] - C1: (size: 4) ['C1', 'CAPS', 'K_A', 'A' ], - C2: (size: 5) ['C2', 'CAPS', 'K_A', 'K_N', 'Ã' ], use 2.(K_A) and 4.('Ã') to get name and DEADKEYED - C3: (size: 6) ['C3', 'NCAPS RALT', 'K_8', 'NCAPS RALT', 'K_U', 'ˆ' ], - C4: (size: 4) ['C4', 'NCAPS 0', 'K_SPACE', '' ], - C4: (size: 7) ['C4', 'NCAPS RALT', 'K_N', '˜', 'isTerminator', '˜', '02DC '], use 2.(K_N) , 5. (isTerminator) and 6.('02DC') to get key name and DEADKEY in hex - - To Find a DEADKEY e.g. ^ - 1) look in modifier_C4 with 'isTerminator' included (n = 7) - 2) get 7th entry ===> DEADKEY (e.g. 02DC) - - To Find a DEADKEYABLE ( a character that can be converted to a deadkey e.g. A (-> Ã) ): - 1) C1 CAPS K_A A - 2) C2 CAPS K_A K_N Ã - - Find C2 rule with 5 entries (Deadkeyed) (e.g. C2 CAPS K_A K_N Ã) - - get C1 rule with same second and third entries -> (e.g. C1 CAPS K_A) - - get 2nd entry of C1 rule ===> DEADKEYABLE (e.g. A) - - To Find a DEADKEYED ( a character that has been converted from another character e.g. Ã ): - 1) look in modifier_C2 CAPS K_A K_N Ã - 2) get 3rd entry (='K_A') - 3) get 5th entry ===> DEADKEYED (='Ã') - */ - - - //---------------------------------------------------------------------------------------------------------- - //---------------------------------------------------------------------------------------------------------- - //----- output table goups start ( ToDo remove) ------------------------------------------------------------ - //---------------------------------------------------------------------------------------------------------- - //---------------------------------------------------------------------------------------------------------- - // select only lines for deadkeyables ( entries that contain C1, are not K_SPACE and create chars e.g. from 'C1', 'CAPS', 'K_A', 'A' ]) - const deadkeyables_raw = data_ukelele.ArrayOf_Rules.filter((curr) => { - if ((curr.rule_type === "C1") && (curr.key !== "K_SPACE") && (new TextDecoder().decode(curr.deadkeyed_Ch) !== "")) { - return curr; - } - return "" - }); - - // select only lines for deadkeyed ( entries that contain C2, are not K_SPACE and create a deadkeyed) e.g. from ['C2', 'CAPS', 'K_A', 'K_N', 'Ã' ] - const deadkeyed_raw_multiple = data_ukelele.ArrayOf_Rules.filter((curr) => { - // if ((curr.rule_type === "C2") && (curr.key !== "K_SPACE") && (new TextDecoder().decode(curr.deadkeyed_Ch) !== "")) { - // if ((curr.rule_type === "C2") && (curr.key !== "K_SPACE")) { - if ((curr.rule_type === "C2")) { - return curr; - } - return "" - }); - - // remove duplicates - const deadkeyed_raw = deadkeyed_raw_multiple.reduce((unique, o) => { - if (!unique.some((obj: { rule_type: any; modifier_key: any; key: any; deadkeyed_Ch: any }) => - new TextDecoder().decode(obj.deadkeyed_Ch) === new TextDecoder().decode(o.deadkeyed_Ch) - && obj.key === o.key - && obj.rule_type === o.rule_type - && obj.modifier_key === o.modifier_key) - ) { - unique.push(o); - } - return unique; - }, []); - - const dk_array_comlpete: any[] = [] - - // create 2D array with data of both deadkeyables_raw, deadkeyed_raw and remove possible duplicates - for (let rr = 0; rr < deadkeyables_raw.length; rr++) { - // loop deadkeyed_raw, take Keyname - for (let ss = 0; ss < deadkeyed_raw.length; ss++) { - const dk_array: any[] = [] - //if available ( if both have the same shiftstate and keyname) - if ((deadkeyables_raw[rr].modifier_key === deadkeyed_raw[ss].modifier_key) && - ((deadkeyables_raw[rr].key === deadkeyed_raw[ss].key))) { - - dk_array.push(new TextDecoder().decode(deadkeyables_raw[rr].deadkeyed_Ch)) // deadkeyable e.g. A - dk_array.push(deadkeyed_raw[ss].deadkey) // Keyname dk e.g. K_N - dk_array.push(new TextDecoder().decode(deadkeyed_raw[ss].deadkeyed_Ch)) // deadkeyed e.g. Ã - } - if (dk_array.length > 0) - dk_array_comlpete.push(dk_array) - } - } - - const unique_dk_array_comlpete = dk_array_comlpete.reduce((acc, curr) => { - const [uniq, set] = acc; - if (!set.has(curr.join(','))) { - set.add(curr.join(',')); - uniq.push(curr); - } - return acc; - }, [[], new Set()], - ); - const deadkeyedElement: string[][] = Array.from({ length: unique_C0_C1_Rules.length }, () => new Array(2).fill('')); - const deadkeyablesElement: string[][] = Array.from({ length: unique_C0_C1_Rules.length }, () => new Array(1).fill('')); - - // why is there a set entry???? deadkeyables_raw[0] - for (let i = 0; i < unique_C0_C1_Rules.length; i++) { - for (let j = 0; j < unique_dk_array_comlpete[0].length; j++) { - if (unique_C0_C1_Rules[i].key === unique_dk_array_comlpete[0][j][1]) { - deadkeyablesElement[i][0] = deadkeyablesElement[i][0] + "\'" + unique_dk_array_comlpete[0][j][0] + "\' " - deadkeyedElement[i][0] = deadkeyedElement[i][0] + "\'" + unique_dk_array_comlpete[0][j][2] + "\' " - } - deadkeyedElement[i][1] = this.getHexFromChar(new TextDecoder().decode(unique_C0_C1_Rules[i].deadkeyed_Ch)) - } - } - - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // ~~~~ draft print ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - if (KeylayoutToKmnConverter.print_draft) { - - data += "\n" - data += '\########## OK #################################################################\n' - - data += '\nmatch > use(deadkeys)\n\n' - data += '\ngroup(deadkeys)\n\n' - - for (let i = 0; i < deadkeyablesElement.length; i++) { - data += "\n\ndk: " + deadkeyedElement[i][1] - data += "\ndeadkeyablesArray xx" + deadkeyablesElement[i][0] - data += "\ndeadkeyedArray xx " + deadkeyedElement[i][0] - } - } - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // ~~~~ draft print end ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - else { - data += '\nmatch > use(deadkeys)\n\n' - data += '\ngroup(deadkeys)\n\n' - - for (let i = 0; i < deadkeyablesElement.length; i++) { - data += "\n\ndk: " + deadkeyedElement[i][1] - data += "\ndeadkeyablesArray xx" + deadkeyablesElement[i][0] - data += "\ndeadkeyedArray xx " + deadkeyedElement[i][0] - } - } - - //---------------------------------------------------------------------------------------------------------- - //---------------------------------------------------------------------------------------------------------- - //----- output table goups end ( ToDo remove) -------------------------------------------------------------- - //---------------------------------------------------------------------------------------------------------- - //---------------------------------------------------------------------------------------------------------- - - return data - } - public createData_Rules(data_ukelele: convert_object): string { - const maxkey = 50 + + const isCapsused: boolean = this.checkIfCapsUsed(data_ukelele.ArrayOf_Modifiers) + const maxkey: number = 50 let data: string = "" - let keymarker = "" + let keymarker: string = "" - // prepare data for C0 and C1 .................................. - // select only lines that contain C0 or C1 and create an output character. - const data_C0_C1 = data_ukelele.ArrayOf_Rules.filter((curr) => { - if ((curr.deadkeyed_Ch !== new TextEncoder().encode("") || curr.deadkeyed_Ch !== undefined) + // prepare data for C0 and C1 - select only lines that contain C0 or C1 and create an output character + const data_C0_C1: rule_object[] = data_ukelele.ArrayOf_Rules.filter((curr) => { + if ((curr.output !== new TextEncoder().encode("") || curr.output !== undefined) && (curr.rule_type === "C0") || (curr.rule_type === "C1")) { return curr; } else return "" }); - const unique_C0_C1_Rules = data_C0_C1.reduce((unique, o) => { - if (!unique.some((obj: { deadkeyed_Ch: any; rule_type: any; modifier_key: any; key: any }) => - new TextDecoder().decode(obj.deadkeyed_Ch) === new TextDecoder().decode(o.deadkeyed_Ch) + const unique_C0_C1_Rules: rule_object[] = data_C0_C1.reduce((unique, o) => { + if (!unique.some((obj: { output: Uint8Array; rule_type: string; modifier_key: string; key: string }) => + new TextDecoder().decode(obj.output) === new TextDecoder().decode(o.output) && obj.key === o.key && obj.rule_type === o.rule_type && obj.modifier_key === o.modifier_key @@ -1806,20 +1644,20 @@ export class KeylayoutToKmnConverter { } return unique; }, []); - this.writeDalaset(unique_C0_C1_Rules) - // prepare data for C2 ......................................... - const data_C2 = data_ukelele.ArrayOf_Rules.filter((curr) => { - if ((curr.deadkeyed_Ch !== new TextEncoder().encode("") || curr.deadkeyed_Ch !== undefined) + + // prepare data for C2 - select only lines that contain C2 and create an output character + const data_C2: rule_object[] = data_ukelele.ArrayOf_Rules.filter((curr) => { + if ((curr.output !== new TextEncoder().encode("") || curr.output !== undefined) && (curr.rule_type === "C2")) { return curr; } else return "" }); - const unique_C2_Rules = data_C2.reduce((unique, o) => { - if (!unique.some((obj: { deadkeyed_Ch: any; rule_type: any; modifier_key: any; modifier_deadkey: string; deadkey: any; key: any }) => + const unique_C2_Rules: rule_object[] = data_C2.reduce((unique, o) => { + if (!unique.some((obj: { output: Uint8Array; rule_type: string; modifier_key: string; modifier_deadkey: string; deadkey: string; key: string }) => - new TextDecoder().decode(obj.deadkeyed_Ch) === new TextDecoder().decode(o.deadkeyed_Ch) - && new TextDecoder().decode(obj.deadkeyed_Ch) !== "" + new TextDecoder().decode(obj.output) === new TextDecoder().decode(o.output) + && new TextDecoder().decode(obj.output) !== "" && obj.rule_type === o.rule_type @@ -1835,29 +1673,26 @@ export class KeylayoutToKmnConverter { return unique; }, []); - - // prepare data for C3 ......................................... - const data_C3 = data_ukelele.ArrayOf_Rules.filter((curr) => { - if ((curr.deadkeyed_Ch !== new TextEncoder().encode("") || curr.deadkeyed_Ch !== undefined) + // prepare data for C3 - select only lines that contain C3 and create an output character + const data_C3: rule_object[] = data_ukelele.ArrayOf_Rules.filter((curr) => { + if ((curr.output !== new TextEncoder().encode("") || curr.output !== undefined) && (curr.rule_type === "C3")) { return curr; } else return "" }); - const unique_C3_Rules = data_C3.reduce((unique, o) => { - - if (!unique.some((obj: { deadkeyed_Ch: any; rule_type: any; modifier_key: any; modifier_deadkey: string; prev_deadkey: string; modifier_prev_deadkey: string; deadkey: any; key: any }) => - new TextDecoder().decode(obj.deadkeyed_Ch) === new TextDecoder().decode(o.deadkeyed_Ch) - && new TextDecoder().decode(obj.deadkeyed_Ch) !== "" - && obj.key === o.key + const unique_C3_Rules: rule_object[] = data_C3.reduce((unique, o) => { + if (!unique.some((obj: { output: Uint8Array; rule_type: string; modifier_key: string; modifier_deadkey: string; prev_deadkey: string; modifier_prev_deadkey: string; deadkey: string; key: string }) => + new TextDecoder().decode(obj.output) === new TextDecoder().decode(o.output) && obj.rule_type === o.rule_type - && this.create_kmn_modifier(obj.modifier_key, false) === this.create_kmn_modifier(o.modifier_key, false) + && obj.modifier_key === o.modifier_key + && obj.key === o.key - && this.create_kmn_modifier(obj.modifier_deadkey, false) === this.create_kmn_modifier(o.modifier_deadkey, false) + && obj.modifier_deadkey === o.modifier_deadkey && obj.deadkey === o.deadkey - && this.create_kmn_modifier(obj.modifier_prev_deadkey, false) === this.create_kmn_modifier(o.modifier_prev_deadkey, false) + && obj.modifier_prev_deadkey === o.modifier_prev_deadkey && obj.prev_deadkey === o.prev_deadkey) ) { unique.push(o); @@ -1866,13 +1701,10 @@ export class KeylayoutToKmnConverter { }, []); - console.log(" unique_C3_Rules", this.writeDalaset(unique_C3_Rules)) - - const isCapsused = this.checkIfCapsUsed(data_ukelele.ArrayOf_Modifiers) for (let i = 0; i < unique_C0_C1_Rules.length; i++) { // lookup key nr of the key that is being processed - let keyNr = 0; + let keyNr: number = 0; for (let j = 0; j < maxkey; j++) { if (this.map_UkeleleKC_To_VK(j) === unique_C0_C1_Rules[i].key) keyNr = j @@ -1886,7 +1718,7 @@ export class KeylayoutToKmnConverter { if (unique_C0_C1_Rules[i].key !== keymarker) data += '\n' - let warningtext = "c C0 WARNING: " + let warningtext: string = "c C0 WARNING: " warningtext = warningtext + this.findDuplicateRules(unique_C0_C1_Rules, i, "C01") warningtext = warningtext + this.findAmbiguousRules(unique_C0_C1_Rules, i, "C01") warningtext = warningtext + this.findUnAvailableRule(unique_C0_C1_Rules, i) @@ -1894,20 +1726,20 @@ export class KeylayoutToKmnConverter { // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~ draft print ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - if ((KeylayoutToKmnConverter.print_draft) && (new TextDecoder().decode(unique_C0_C1_Rules[i].deadkeyed_Ch) !== "")) { + if ((KeylayoutToKmnConverter.print_draft) && (new TextDecoder().decode(unique_C0_C1_Rules[i].output) !== "")) { if (warningtext === "c C0 WARNING: ") - data += keyNr + "-(modif:" + unique_C0_C1_Rules[i].rule_type + "-" + unique_C0_C1_Rules[i].dk_prev + `) + [` + (unique_C0_C1_Rules[i].modifier_key + ' ' + unique_C0_C1_Rules[i].key).trim() + `] °°-> \'` + new TextDecoder().decode(unique_C0_C1_Rules[i].deadkeyed_Ch) + '\'\n' + data += unique_C0_C1_Rules[i].rule_type + keyNr + keyNr + "-(modif:" + unique_C0_C1_Rules[i].rule_type + "-" + unique_C0_C1_Rules[i].dk_prev + `) + [` + (unique_C0_C1_Rules[i].modifier_key + ' ' + unique_C0_C1_Rules[i].key).trim() + `] °°-> \'` + new TextDecoder().decode(unique_C0_C1_Rules[i].output) + '\'\n' else - data += warningtext + keyNr + "-(modif:" + unique_C0_C1_Rules[i].rule_type + "-" + unique_C0_C1_Rules[i].dk_prev + `) + [` + (unique_C0_C1_Rules[i].modifier_key + ' ' + unique_C0_C1_Rules[i].key).trim() + `] **°°-> \'` + new TextDecoder().decode(unique_C0_C1_Rules[i].deadkeyed_Ch) + '\'\n' + data += warningtext + keyNr + "-(modif:" + unique_C0_C1_Rules[i].rule_type + "-" + unique_C0_C1_Rules[i].dk_prev + `) + [` + (unique_C0_C1_Rules[i].modifier_key + ' ' + unique_C0_C1_Rules[i].key).trim() + `] **°°-> \'` + new TextDecoder().decode(unique_C0_C1_Rules[i].output) + '\'\n' } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~ draft print end ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ else { if (warningtext === "c C0 WARNING: ") - data += "+ [" + (unique_C0_C1_Rules[i].modifier_key + ' ' + unique_C0_C1_Rules[i].key).trim() + `] > \'` + new TextDecoder().decode(unique_C0_C1_Rules[i].deadkeyed_Ch) + '\'\n' + data += "+ [" + (unique_C0_C1_Rules[i].modifier_key + ' ' + unique_C0_C1_Rules[i].key).trim() + `] > \'` + new TextDecoder().decode(unique_C0_C1_Rules[i].output) + '\'\n' else - data += warningtext + "[" + (unique_C0_C1_Rules[i].modifier_key + ' ' + unique_C0_C1_Rules[i].key).trim() + `] > \'` + new TextDecoder().decode(unique_C0_C1_Rules[i].deadkeyed_Ch) + '\'\n' + data += warningtext + "[" + (unique_C0_C1_Rules[i].modifier_key + ' ' + unique_C0_C1_Rules[i].key).trim() + `] > \'` + new TextDecoder().decode(unique_C0_C1_Rules[i].output) + '\'\n' } keymarker = unique_C0_C1_Rules[i].key } @@ -1927,7 +1759,7 @@ export class KeylayoutToKmnConverter { if ((unique_C2_Rules[k].rule_type === "C2")) { - let warningtext = "c C2 WARNING: " + let warningtext: string = "c C2 WARNING: " warningtext = warningtext + this.findDuplicateRules(unique_C2_Rules, k, "C2") warningtext = warningtext + this.findAmbiguousRules(unique_C2_Rules, k, "C2") warningtext = warningtext + this.findUnAvailableRule(unique_C2_Rules, k) @@ -1938,24 +1770,26 @@ export class KeylayoutToKmnConverter { if (KeylayoutToKmnConverter.print_draft) { if (warningtext === "c C2 WARNING: ") { data += "new: [" + unique_C2_Rules[k].modifier_deadkey + " " + unique_C2_Rules[k].deadkey + "] > XXX" + - " [" + unique_C2_Rules[k].modifier_key + " " + unique_C2_Rules[k].key + "] °°-> \'" + new TextDecoder().decode(unique_C2_Rules[k].deadkeyed_Ch) + "\'" + " [" + unique_C2_Rules[k].modifier_key + " " + unique_C2_Rules[k].key + "] °°-> \'" + new TextDecoder().decode(unique_C2_Rules[k].output) + "\'" } else { data += warningtext + " [" + unique_C2_Rules[k].modifier_deadkey + " " + unique_C2_Rules[k].deadkey + "] > XXX" + - "[" + unique_C2_Rules[k].modifier_key + " " + unique_C2_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_C2_Rules[k].deadkeyed_Ch) + "\'" + "[" + unique_C2_Rules[k].modifier_key + " " + unique_C2_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_C2_Rules[k].output) + "\'" } } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~ draft print end ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ else { + // all OK if (warningtext === "c C2 WARNING: ") { - data += "+ [" + unique_C2_Rules[k].modifier_deadkey + " " + unique_C2_Rules[k].deadkey + "] > dk(C" + String(unique_C2_Rules[k].dk_C2) + ")\n" - data += "dk(C" + String(unique_C2_Rules[k].dk) + ") + [" + unique_C2_Rules[k].modifier_key + " " + unique_C2_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_C2_Rules[k].deadkeyed_Ch) + "\'\n" + data += "now + [" + unique_C2_Rules[k].modifier_deadkey + " " + unique_C2_Rules[k].deadkey + "] > dk(C" + String(unique_C2_Rules[k].dk_C2) + ")\n" + data += "dk(C" + String(unique_C2_Rules[k].dk_C2) + ") + [" + unique_C2_Rules[k].modifier_key + " " + unique_C2_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_C2_Rules[k].output) + "\'\n" } + // warning avail else { data += warningtext + " [" + unique_C2_Rules[k].modifier_deadkey + " " + unique_C2_Rules[k].deadkey + "] > dk(C" + String(unique_C2_Rules[k].dk_C2) + ")\n" - data += warningtext + " dk(C" + String(unique_C2_Rules[k].dk_C2) + ") [" + unique_C2_Rules[k].modifier_key + " " + unique_C2_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_C2_Rules[k].deadkeyed_Ch) + "\'\n" + data += warningtext + " dk(C" + String(unique_C2_Rules[k].dk_C2) + ") [" + unique_C2_Rules[k].modifier_key + " " + unique_C2_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_C2_Rules[k].output) + "\'\n" } } data += "\n" @@ -1975,7 +1809,7 @@ export class KeylayoutToKmnConverter { for (let k = 0; k < unique_C3_Rules.length; k++) { if ((unique_C3_Rules[k].rule_type === "C3")) { - let warningtext = "c C3 WARNING: " + let warningtext: string = "c C3 WARNING: " warningtext = warningtext + this.findDuplicateRules(unique_C3_Rules, k, "C3") // OK warningtext = warningtext + this.findAmbiguousRules(unique_C3_Rules, k, "C3") // OK warningtext = warningtext + this.findUnAvailableRule(unique_C3_Rules, k) // OK @@ -1987,15 +1821,14 @@ export class KeylayoutToKmnConverter { if (warningtext === "c C3 WARNING: ") { data += " [" + unique_C3_Rules[k].modifier_prev_deadkey + " " + unique_C3_Rules[k].prev_deadkey + "] > XXX " + "[" + unique_C3_Rules[k].modifier_deadkey + " " + unique_C3_Rules[k].deadkey + "] > YYY " + - " [" + unique_C3_Rules[k].modifier_key + " " + unique_C3_Rules[k].key + "] °°-> \'" + new TextDecoder().decode(unique_C3_Rules[k].deadkeyed_Ch) + "\'" + " [" + unique_C3_Rules[k].modifier_key + " " + unique_C3_Rules[k].key + "] °°-> \'" + new TextDecoder().decode(unique_C3_Rules[k].output) + "\'" } else { data += warningtext + " [" + unique_C3_Rules[k].modifier_prev_deadkey + " " + unique_C3_Rules[k].prev_deadkey + "] > XXX " + "[" + unique_C3_Rules[k].modifier_deadkey + " " + unique_C3_Rules[k].deadkey + "] > YYY " + - " [" + unique_C3_Rules[k].modifier_key + " " + unique_C3_Rules[k].key + "] °°-> \'" + new TextDecoder().decode(unique_C3_Rules[k].deadkeyed_Ch) + "\'" + " [" + unique_C3_Rules[k].modifier_key + " " + unique_C3_Rules[k].key + "] °°-> \'" + new TextDecoder().decode(unique_C3_Rules[k].output) + "\'" } } - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~ draft print end ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -2003,12 +1836,12 @@ export class KeylayoutToKmnConverter { if (warningtext === "c C3 WARNING: ") { data += "+ [" + this.create_kmn_modifier(unique_C3_Rules[k].modifier_prev_deadkey, isCapsused) + " " + unique_C3_Rules[k].prev_deadkey + "] > dk(A" + String(unique_C3_Rules[k].dk_prev) + ")\n" data += "dk(A" + String(unique_C3_Rules[k].dk_prev) + ") + [" + this.create_kmn_modifier(unique_C3_Rules[k].modifier_deadkey, isCapsused) + " " + unique_C3_Rules[k].deadkey + "] > dk(B" + String(unique_C3_Rules[k].dk) + ")\n" - data += "dk(B" + String(unique_C3_Rules[k].dk) + ") + [" + this.create_kmn_modifier(unique_C3_Rules[k].modifier_key, isCapsused) + " " + unique_C3_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_C3_Rules[k].deadkeyed_Ch) + "\'\n" + data += "dk(B" + String(unique_C3_Rules[k].dk) + ") + [" + this.create_kmn_modifier(unique_C3_Rules[k].modifier_key, isCapsused) + " " + unique_C3_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_C3_Rules[k].output) + "\'\n" } else { data += warningtext + " [" + this.create_kmn_modifier(unique_C3_Rules[k].modifier_prev_deadkey, isCapsused) + " " + unique_C3_Rules[k].prev_deadkey + "] > dk(A" + String(unique_C3_Rules[k].dk_prev) + ")\n" data += warningtext + " dk(A" + String(unique_C3_Rules[k].dk_prev) + ") + [" + this.create_kmn_modifier(unique_C3_Rules[k].modifier_deadkey, isCapsused) + " " + unique_C3_Rules[k].deadkey + "] > dk(B" + String(unique_C3_Rules[k].dk) + ")\n" - data += warningtext + " dk(B" + String(unique_C3_Rules[k].dk) + ") + [" + this.create_kmn_modifier(unique_C3_Rules[k].modifier_key, isCapsused) + " " + unique_C3_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_C3_Rules[k].deadkeyed_Ch) + "\'\n" + data += warningtext + " dk(B" + String(unique_C3_Rules[k].dk) + ") + [" + this.create_kmn_modifier(unique_C3_Rules[k].modifier_key, isCapsused) + " " + unique_C3_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_C3_Rules[k].output) + "\'\n" } } data += "\n" @@ -2018,28 +1851,29 @@ export class KeylayoutToKmnConverter { return data } - /// console log all entries - public writeDalaset(unique_C3_Rules: any) { - for (let i = 0; i < unique_C3_Rules.length; i++) { + /// console log all entries C3 + public writeDalaset(dataRules: rule_object[]) { + for (let i = 0; i < dataRules.length; i++) { - console.log("unique_C3_Rules ", unique_C3_Rules.length, i, + console.log("dataRules ", - unique_C3_Rules[i].rule_type !== "" ? unique_C3_Rules[i].rule_type : "--".padEnd(4, " "), + dataRules[i].rule_type !== "" ? dataRules[i].rule_type : "--".padEnd(4, " ") + , dataRules.length, i, + "| ", (dataRules[i].modifier_prev_deadkey !== "" ? dataRules[i].modifier_prev_deadkey.padEnd(33, " ") : "--".padEnd(33, " ")), + (dataRules[i].prev_deadkey !== "" ? dataRules[i].prev_deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), + (dataRules[i].dk_prev !== 0 ? ("dk(A" + String(dataRules[i].dk_prev) + ")").padEnd(11, " ") : "--".padEnd(11, " ")), - "| ", (unique_C3_Rules[i].modifier_prev_deadkey !== "" ? unique_C3_Rules[i].modifier_prev_deadkey.padEnd(33, " ") : "--".padEnd(33, " ")), - (unique_C3_Rules[i].prev_deadkey !== "" ? unique_C3_Rules[i].prev_deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), - (unique_C3_Rules[i].dk_prev !== 0 ? ("dk(A" + String(unique_C3_Rules[i].dk_prev) + ")").padEnd(11, " ") : "--".padEnd(11, " ")), + (dataRules[i].modifier_deadkey !== "" ? dataRules[i].modifier_deadkey.padEnd(30, " ") : "--".padEnd(30, " ")), + (dataRules[i].deadkey !== "" ? dataRules[i].deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), - (unique_C3_Rules[i].modifier_deadkey !== "" ? unique_C3_Rules[i].modifier_deadkey.padEnd(30, " ") : "--".padEnd(30, " ")), - (unique_C3_Rules[i].deadkey !== "" ? unique_C3_Rules[i].deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), - (unique_C3_Rules[i].dk !== 0 ? ("dk(B" + String(unique_C3_Rules[i].dk) + ")").padEnd(9, " ") : "--".padEnd(9, " ")), + dataRules[i].rule_type === "C2" ? (dataRules[i].dk !== 0 ? ("dk(C" + String(dataRules[i].dk) + ")").padEnd(9, " ") : "--".padEnd(9, " ")) : ((dataRules[i].dk !== 0 ? ("dk(B" + String(dataRules[i].dk) + ")").padEnd(9, " ") : "--".padEnd(9, " "))), - "| ", (unique_C3_Rules[i].modifier_key !== "" ? unique_C3_Rules[i].modifier_key.padEnd(40, " ") : "--".padEnd(40, " ")), - (unique_C3_Rules[i].key !== "" ? unique_C3_Rules[i].key.padEnd(8, " ") : "--".padEnd(8, " ")), - (new TextDecoder().decode(unique_C3_Rules[i].deadkeyed_Ch) !== "" ? new TextDecoder().decode(unique_C3_Rules[i].deadkeyed_Ch).padEnd(10, " ") : ("--" + unique_C3_Rules[i].deadkeyed_Ch) + "--"), + "| ", (dataRules[i].modifier_key !== "" ? dataRules[i].modifier_key.padEnd(40, " ") : "--".padEnd(40, " ")), + (dataRules[i].key !== "" ? dataRules[i].key.padEnd(8, " ") : "--".padEnd(8, " ")), + (new TextDecoder().decode(dataRules[i].output) !== "" ? new TextDecoder().decode(dataRules[i].output).padEnd(10, " ") : ("--" + dataRules[i].output) + "--"), "| °°") } @@ -2103,23 +1937,22 @@ export class KeylayoutToKmnConverter { class Rules { constructor( - public rule_type: string, - public isTerminator: boolean, + public rule_type: string, /* C0, C1, C2, C3, or C4 */ - public modifier_prev_deadkey: string, + public modifier_prev_deadkey: string, /* first key used by C3 rules*/ public prev_deadkey: string, public prev_deadkeys_Ch: Uint8Array, public dk_prev: number, - public modifier_deadkey: string, + public modifier_deadkey: string, /* second key used by C2,C3 rules*/ public deadkey: string, public deadkeys_Ch: Uint8Array, - public dk: number, + public dk: number, //todo remove one public dk_C2: number, - public modifier_key: string, + public modifier_key: string, /* third key used by C0,C1,C2,C3,C4 rules*/ public key: string, - public deadkeyed_Ch: Uint8Array, + public output: Uint8Array, /* output used by C0,C1,C2,C3,C4 rules*/ ) { } From c9a51888023844d6c929ee4639aac40699de8f33 Mon Sep 17 00:00:00 2001 From: Sabine Date: Thu, 6 Feb 2025 15:01:11 +0100 Subject: [PATCH 046/251] feat(developer): kmc-convert new findAmbiguousRules --- .../keylayout-to-kmn-converter.ts | 1002 ++++++++++++++--- 1 file changed, 819 insertions(+), 183 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 6316d6cf3c8..8cdcf890f29 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -67,6 +67,7 @@ import boxXmlArray = util.boxXmlArray;*/ // TODO remove: test files: checkif kmn gats the same output as ukelele file(except for C3 t works well :)) // ToDo needed methods // Filter functions use the same type + // where to put documentation } import { XMLParser } from 'fast-xml-parser'; // for reading a file @@ -140,12 +141,14 @@ export interface rule_object { prev_deadkey: string, /* name of the first key (e.g. K_U) */ prev_deadkeys_Ch: Uint8Array, /* Todo needed?*/ dk_prev: number, /* Todo needed?*/ + uniqueA: number, modifier_deadkey: string, /* string of modifiers for the second key (e.g. "NCAPS RALT CTRL") */ deadkey: string, /* name of the second key */ deadkeys_Ch: Uint8Array, /* Todo needed?*/ dk: number, /* Todo needed?*/ dk_C2: number, + uniqueB: number, modifier_key: string, /* string of modifiers for the third key (e.g. "NCAPS RALT CTRL") */ key: string, /* name of the third key (e.g. K_U) */ @@ -163,7 +166,7 @@ export class KeylayoutToKmnConverter { static readonly OUTPUT_FILE_EXTENSION = '.kmn'; //Todo remove print_draft - static print_draft = true + static print_draft = false static used_Keys_count = 50 // TODO use callbacks what about /*private*/ for options @@ -292,10 +295,10 @@ export class KeylayoutToKmnConverter { // add lower part of kmn file: RULES data += this.createData_Rules(data_ukelele) - console.log("##################################################################################################################\n", - "kmn output looks like that :################################################################################################\n", - data, - "############################################################################################################################\n") + /* console.log("##################################################################################################################\n", + "kmn output looks like that :################################################################################################\n", + data, + "############################################################################################################################\n")*/ /*writeFileSync("data/MyResult.kmn", data, { flag: "w" })*/ this.callbacks.fs.writeFileSync("data/MyResult.kmn", new TextEncoder().encode(data)) // not usable here since it takes UInt8array data @@ -383,12 +386,14 @@ export class KeylayoutToKmnConverter { /* prev_deadkey */ "", /* prev_deadkeys_Ch*/ new TextEncoder().encode(""), /* dk_prev */ 0, + /* unique A */ 0, /* modifier_deadkey */ "", /* deadkey */ "", /* deadkeys_Ch */ new TextEncoder().encode(""), /* dk*/ 0, /* dk for C2*/ 0, + /* unique B */ 0, /* modifier_key*/ this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[i][l], isCapsused), /* key */ this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), @@ -427,12 +432,14 @@ export class KeylayoutToKmnConverter { /* prev_deadkey */ "", /* prev_deadkeys_Ch*/ new TextEncoder().encode(""), /* dk_prev */ 0, + /* unique A */ 0, /* modifier_deadkey */ "", /* deadkey */ "", /* deadkeys_Ch */ new TextEncoder().encode(""), /* dk*/ 0, /* dk for C2*/ 0, + /* unique B */ 0, /* modifier_key*/ resultArraySS_Key_Out[m][5], /* key */ resultArraySS_Key_Out[m][4], @@ -497,12 +504,14 @@ export class KeylayoutToKmnConverter { /* prev_deadkey */ "", /* prev_deadkeys_Ch*/ new TextEncoder().encode(""), /* dk_prev */ 0, + /* unique A */ 0, /* modifier_deadkey */ this.create_kmn_modifier(b4_modifier2D_array[n1][n2], isCapsused), /* deadkey */ this.map_UkeleleKC_To_VK(Number(b4_code_arr[n3])), /* deadkeys_Ch */ new TextEncoder().encode(""), /* dk*/ 0, /* dk for C2*/ dk_counter_C2++, + /* unique B */ 0, /* modifier_key*/ b1_KeyMapModiKeyArray[n4][3], /* key */ b1_KeyMapModiKeyArray[n4][0], @@ -586,12 +595,14 @@ export class KeylayoutToKmnConverter { /* prev_deadkey */ b2_keyname_arr[n3], /* prev_deadkeys_Ch*/ new TextEncoder().encode(""), /* dk_prev */ dk_counter_C3_A++, + /* unique A */ 0, /* modifier_deadkey */ this.create_kmn_modifier(b4_modifier2D_array[n4][n5], isCapsused), /* deadkey */ this.map_UkeleleKC_To_VK(Number(b4_code_arr[n6])), /* deadkeys_Ch */ new TextEncoder().encode(""), /* dk*/ dk_counter_C3_B++, /* dk for C2*/ 0, + /* unique B */ 0, /* modifier_key*/ b1_KeyMapModiKeyArray[n7][3], /* key */ b1_KeyMapModiKeyArray[n7][0], @@ -630,12 +641,14 @@ export class KeylayoutToKmnConverter { /* prev_deadkey */ "", /* prev_deadkeys_Ch*/ new TextEncoder().encode(""), /* dk_prev */ 0, + /* unique A */ 0, /* modifier_deadkey */ "", /* deadkey */ "", /* deadkeys_Ch */ new TextEncoder().encode(""), /* dk*/ 0, /* dk for C2*/ 0, + /* unique B */ 0, /* modifier_key*/ this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[i][l], isCapsused), /* key */ this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), @@ -651,6 +664,120 @@ export class KeylayoutToKmnConverter { } } + // now check for duplicate C2 and C3 rules and prepare for printing + let unique_dkA_count = 0 + let unique_dkB_count = 0 + const unique_ruleArrayC2: string[][] = [] + + //----------------------------------- -dk---------------------------------- + // first rule is always unique + ObjectArray[0].uniqueB = unique_dkB_count + ObjectArray[0].dk_C2 = unique_dkB_count + unique_dkB_count++ + + for (let i = 0; i < ObjectArray.length; i++) { + if ((ObjectArray[i].modifier_deadkey !== "") && (ObjectArray[i].deadkey !== "")) { + let isUnique_dkB: boolean = true + + // check if not used before + for (let j = 0; j < i; j++) { + if ((ObjectArray[i].modifier_deadkey === ObjectArray[j].modifier_deadkey) + && (ObjectArray[i].deadkey === ObjectArray[j].deadkey)) { + isUnique_dkB = isUnique_dkB && false + }/* { + ObjectArray[i].dk_C2 = unique_dkB_count + }*/ + } + + if (isUnique_dkB) { + const ruleArray: string[] = [] + ObjectArray[i].uniqueB = unique_dkB_count + ruleArray.push(ObjectArray[i].modifier_deadkey) + ruleArray.push(ObjectArray[i].deadkey) + ruleArray.push(String(unique_dkB_count)) + unique_dkB_count++ + unique_ruleArrayC2.push(ruleArray) + } + } + } + + //-----------------------------------prev-dk---------------------------------- + + // first rule is always unique + ObjectArray[0].uniqueA = unique_dkA_count + unique_dkA_count++ + + for (let i = 0; i < ObjectArray.length; i++) { + if ((ObjectArray[i].modifier_prev_deadkey !== "") && (ObjectArray[i].prev_deadkey !== "")) { + let isUnique_dkA: boolean = true + + // check if not used before + for (let j = 0; j < i; j++) { + if ((ObjectArray[i].modifier_prev_deadkey === ObjectArray[j].modifier_prev_deadkey) + && (ObjectArray[i].prev_deadkey === ObjectArray[j].prev_deadkey)) { + isUnique_dkA = isUnique_dkA && false + } + } + + if (isUnique_dkA) { + ObjectArray[i].uniqueA = unique_dkA_count + unique_dkA_count++ + // check if second part of C3 rule contains already defined rule + for (let k = 0; k < unique_ruleArrayC2.length; k++) { + if ((unique_ruleArrayC2[k][0] === ObjectArray[i].modifier_deadkey) && ((unique_ruleArrayC2[k][1] === ObjectArray[i].deadkey))) + ObjectArray[i].uniqueB = Number(unique_ruleArrayC2[k][2]) + } + } + + if (isUnique_dkA) { + const ruleArray: string[] = [] + ObjectArray[i].uniqueB = unique_dkB_count + ruleArray.push(ObjectArray[i].modifier_prev_deadkey) + ruleArray.push(ObjectArray[i].prev_deadkey) + ruleArray.push(String(unique_dkB_count)) + unique_dkB_count++ + unique_ruleArrayC2.push(ruleArray) + } + } + } + // console.log("unique_ruleArrayC2 ", unique_ruleArrayC2) + + for (let i = 0; i < ObjectArray.length; i++) { + + for (let j = 0; j < unique_ruleArrayC2.length; j++) { + if ((ObjectArray[i].modifier_prev_deadkey === unique_ruleArrayC2[j][0]) && (ObjectArray[i].prev_deadkey === unique_ruleArrayC2[j][1])) { + // write nr into rule obj + ObjectArray[i].dk_prev = Number(unique_ruleArrayC2[j][2]) + } + if ((ObjectArray[i].modifier_deadkey === unique_ruleArrayC2[j][0]) && (ObjectArray[i].deadkey === unique_ruleArrayC2[j][1])) { + // write nr into rule obj + ObjectArray[i].dk_C2 = Number(unique_ruleArrayC2[j][2]) + } + } + } + + + //--------------------------------------------------------------------- + // print ToDo remove + /* for (let i = 0; i < ObjectArray.length; i++) { + //if ((ObjectArray[i].uniqueA !== 0) || (ObjectArray[i].uniqueB !== 0)) + if ((ObjectArray[i].rule_type === "C3")) + console.log(" ResulT:", "\t", + ObjectArray[i].rule_type, + ObjectArray[i].modifier_prev_deadkey.padEnd(15, " "), + ObjectArray[i].prev_deadkey.padEnd(15, " "), + String(ObjectArray[i].dk_prev).padEnd(15, " "), + String(ObjectArray[i].uniqueA).padEnd(15, " "), + "--", + ObjectArray[i].modifier_deadkey.padEnd(15, " "), + ObjectArray[i].deadkey.padEnd(15, " "), + ObjectArray[i].dk_C2, "--".padEnd(15, " "), + ObjectArray[i].uniqueB, "--".padEnd(15, " "), + new TextDecoder().decode(ObjectArray[i].output), "--".padEnd(15, " "), + + ) + }*/ + //--------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------- @@ -700,6 +827,8 @@ export class KeylayoutToKmnConverter { "testArray_kmn_action_uni_filter:", testArray_kmn_action_uni_filter, "testArray_Ukelele_action_uni_filter:", testArray_Ukelele_action_uni_filter) else console.log("OOOOHHHH DIFFERENT AMOUNTS ")*/ + if (this.create_kmn_modifier("command", false) === "command") console.log("testNr 16 OK "); else console.log("testNr 16 NOT OK - ", (this.create_kmn_modifier("command", false))) + if (this.create_kmn_modifier("XXX", false) === "command") console.log("testNr 16 OK "); else console.log("testNr 16 NOT OK - ", (this.create_kmn_modifier("XXX", false))) @@ -711,8 +840,7 @@ export class KeylayoutToKmnConverter { if (this.create_kmn_modifier("caps", true) === "CAPS") console.log("testNr 5 OK "); else console.log("testNr 5 NOT OK - ", (this.create_kmn_modifier("caps", true))) if (this.create_kmn_modifier("6caps", true) === "CAPS") console.log("testNr 6 OK "); else console.log("testNr 6 NOT OK - ", (this.create_kmn_modifier("6caps", true))) if (this.create_kmn_modifier("rightControl", false) === "CTRL") console.log("testNr 13 OK "); else console.log("testNr 13 NOT OK - ", (this.create_kmn_modifier("rightControl", false))) - if (this.create_kmn_modifier("command", false) === "command") console.log("testNr 16 OK "); else console.log("testNr 16 NOT OK - ", (this.create_kmn_modifier("command", false))) - if (this.create_kmn_modifier("ComMand", false) === "ComMand") console.log("testNr 26 OK "); else console.log("testNr 26 NOT OK - ", (this.create_kmn_modifier("ComMand", false))) + if (this.create_kmn_modifier("ComMand", false) === "ComMand") console.log("testNr 26 OK "); else console.log("testNr 26 NOT OK - ", (this.create_kmn_modifier("ComMand", false))) if (this.create_kmn_modifier("rshift?", false) === "") console.log("testNr 19 OK "); else console.log("testNr 19 NOT OK - ", (this.create_kmn_modifier("Shift?", false))) if (this.create_kmn_modifier("rshift?", true) === "NCAPS") console.log("testNr 20 OK "); else console.log("testNr 20 NOT OK - ", (this.create_kmn_modifier("Shift?", true))) if (this.create_kmn_modifier("rshift", false) === "SHIFT") console.log("testNr 8 OK "); else console.log("testNr 8 NOT OK - ", (this.create_kmn_modifier("rshift", false))) @@ -794,6 +922,11 @@ export class KeylayoutToKmnConverter { if (this.isAcceptableKeymanModifier("abc") === false) console.log("testNr A 9 OK "); else console.log("testNr A 9 NOT OK - ", (this.isAcceptableKeymanModifier("abc"))) if (this.isAcceptableKeymanModifier("ralt") === true) console.log("testNr A 13 OK "); else console.log("testNr A 13 NOT OK - ", (this.isAcceptableKeymanModifier("ralt"))) */ + + + + + //--------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------- @@ -1435,9 +1568,11 @@ export class KeylayoutToKmnConverter { return unique_modifier_array.flat().toString().replace(/,/g, " ") } + public checkIfCapsUsed(keylayout_modifier: string[][]): boolean { return keylayout_modifier.flat().flat().includes("caps") } + public isAcceptableKeymanModifier(keylayout_modifier: string): boolean { let iskKeymanModifier: boolean = true const modifier_single: string[] = keylayout_modifier.split(" "); @@ -1460,74 +1595,448 @@ export class KeylayoutToKmnConverter { } return iskKeymanModifier } - public findDuplicateRules(unique_C0_C1_Rules: rule_object[], index: number, rule_type: string): string { + public findDuplicateRules(rules: rule_object[], index: number, rule_type: string): string { for (let i = 0; i < index - 1; i++) { if ( ((rule_type === "C01") - && unique_C0_C1_Rules[i].modifier_key === unique_C0_C1_Rules[index].modifier_key - && unique_C0_C1_Rules[i].key === unique_C0_C1_Rules[index].key && - new TextDecoder().decode(unique_C0_C1_Rules[i].output) === new TextDecoder().decode(unique_C0_C1_Rules[index].output) + && rules[i].modifier_key === rules[index].modifier_key + && rules[i].key === rules[index].key && + new TextDecoder().decode(rules[i].output) === new TextDecoder().decode(rules[index].output) ) || (rule_type === "C2" - && unique_C0_C1_Rules[i].modifier_deadkey === unique_C0_C1_Rules[index].modifier_deadkey - && unique_C0_C1_Rules[i].deadkey === unique_C0_C1_Rules[index].deadkey - && unique_C0_C1_Rules[i].modifier_key === unique_C0_C1_Rules[index].modifier_key - && unique_C0_C1_Rules[i].key === unique_C0_C1_Rules[index].key - && new TextDecoder().decode(unique_C0_C1_Rules[i].output) === new TextDecoder().decode(unique_C0_C1_Rules[index].output) + && rules[i].modifier_deadkey === rules[index].modifier_deadkey + && rules[i].deadkey === rules[index].deadkey + && rules[i].modifier_key === rules[index].modifier_key + && rules[i].key === rules[index].key + && new TextDecoder().decode(rules[i].output) === new TextDecoder().decode(rules[index].output) ) || (rule_type === "C3" - && unique_C0_C1_Rules[i].modifier_prev_deadkey === unique_C0_C1_Rules[index].modifier_prev_deadkey - && unique_C0_C1_Rules[i].prev_deadkey === unique_C0_C1_Rules[index].prev_deadkey - && unique_C0_C1_Rules[i].modifier_deadkey === unique_C0_C1_Rules[index].modifier_deadkey - && unique_C0_C1_Rules[i].deadkey === unique_C0_C1_Rules[index].deadkey - && unique_C0_C1_Rules[i].modifier_key === unique_C0_C1_Rules[index].modifier_key - && unique_C0_C1_Rules[i].key === unique_C0_C1_Rules[index].key - && new TextDecoder().decode(unique_C0_C1_Rules[i].output) === new TextDecoder().decode(unique_C0_C1_Rules[index].output) + && rules[i].modifier_prev_deadkey === rules[index].modifier_prev_deadkey + && rules[i].prev_deadkey === rules[index].prev_deadkey + && rules[i].modifier_deadkey === rules[index].modifier_deadkey + && rules[i].deadkey === rules[index].deadkey + && rules[i].modifier_key === rules[index].modifier_key + && rules[i].key === rules[index].key + && new TextDecoder().decode(rules[i].output) === new TextDecoder().decode(rules[index].output) ) ) - return ("duplicate Rule: old: modif[ modi; " + unique_C0_C1_Rules[i].dk_prev + "[" + - unique_C0_C1_Rules[i].modifier_prev_deadkey + " " + unique_C0_C1_Rules[i].prev_deadkey + "] > XXX [" + - unique_C0_C1_Rules[i].modifier_deadkey + " " + unique_C0_C1_Rules[i].deadkey + "] > YYY [" + - unique_C0_C1_Rules[i].modifier_key + " " + unique_C0_C1_Rules[i].key + - "] °°-> \'" + new TextDecoder().decode(unique_C0_C1_Rules[i].output) + "\' <--> ") + return ("duplicate Rule: old: modif[ modi; " + rules[i].dk_prev + "[" + + rules[i].modifier_prev_deadkey + " " + rules[i].prev_deadkey + "] > XXX [" + + rules[i].modifier_deadkey + " " + rules[i].deadkey + "] > YYY [" + + rules[i].modifier_key + " " + rules[i].key + + "] °°-> \'" + new TextDecoder().decode(rules[i].output) + "\' <--> ") } return "" } - public findAmbiguousRules(unique_C0_C1_Rules: rule_object[], index: number, rule_type: string): string { - for (let i = 0; i < index - 1; i++) { - if ( - ((rule_type === "C01") - && unique_C0_C1_Rules[i].modifier_key === unique_C0_C1_Rules[index].modifier_key - && unique_C0_C1_Rules[i].key === unique_C0_C1_Rules[index].key && - new TextDecoder().decode(unique_C0_C1_Rules[i].output) !== new TextDecoder().decode(unique_C0_C1_Rules[index].output) - ) - || (rule_type === "C2" - && unique_C0_C1_Rules[i].modifier_key === unique_C0_C1_Rules[index].modifier_key - && unique_C0_C1_Rules[i].key === unique_C0_C1_Rules[index].key - && unique_C0_C1_Rules[i].modifier_deadkey === unique_C0_C1_Rules[index].modifier_deadkey - && unique_C0_C1_Rules[i].deadkey === unique_C0_C1_Rules[index].deadkey - && new TextDecoder().decode(unique_C0_C1_Rules[i].output) !== new TextDecoder().decode(unique_C0_C1_Rules[index].output) - ) - || (rule_type === "C3" - && unique_C0_C1_Rules[i].modifier_prev_deadkey === unique_C0_C1_Rules[index].modifier_prev_deadkey - && unique_C0_C1_Rules[i].prev_deadkey === unique_C0_C1_Rules[index].prev_deadkey - && unique_C0_C1_Rules[i].modifier_deadkey === unique_C0_C1_Rules[index].modifier_deadkey - && unique_C0_C1_Rules[i].deadkey === unique_C0_C1_Rules[index].deadkey - && unique_C0_C1_Rules[i].modifier_key === unique_C0_C1_Rules[index].modifier_key - && unique_C0_C1_Rules[i].key === unique_C0_C1_Rules[index].key - && new TextDecoder().decode(unique_C0_C1_Rules[i].output) !== new TextDecoder().decode(unique_C0_C1_Rules[index].output) - ) + // C0C1 | | | 1 | CAPS K_A > 'A' + // C2 | | 2 | 3 | CAPS K_A > dk(A1) dk(A1) + SHIFT K_B > 'B' + // C3 | 4 | 5 | 6 | CAPS K_X > dk(B1) dk(B1) + SHIFT K_Y > dk(C1) dk(C1) + NCAPS K_Z > 'Z' + + public findAmbiguousRules(rule: rule_object[], index: number): string { + + // ToDo is the return statement/filter func correct??? + + // 1-1 + // find ambiguous C0 or C1 rules vs. C0 or C1 ....................................................................................................... + // e.g. CAPS K_A > 'A' <-> CAPS K_A > 'B' ........................................................................................................ + // ................................................................................................................................................... + const ambiguous_C0C1_vs_C0C1: rule_object[] = rule.filter((curr, idx) => { + if (((rule[index].rule_type === "C0") || (rule[index].rule_type === "C1")) + && ((curr.rule_type === "C0") || (curr.rule_type === "C1")) + && curr.modifier_prev_deadkey === "" + && curr.prev_deadkey === "" + && curr.modifier_deadkey === "" + && curr.deadkey === "" + && curr.modifier_key === rule[index].modifier_key + && curr.key === rule[index].key + && new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output) + && (idx < index) ) - return ("ambiguous Rule: (old:)[" + - unique_C0_C1_Rules[i].modifier_prev_deadkey + " " + unique_C0_C1_Rules[i].prev_deadkey + "] | [" + - unique_C0_C1_Rules[i].modifier_deadkey + " " + unique_C0_C1_Rules[i].deadkey + "] > XXX [" + - unique_C0_C1_Rules[i].modifier_key + " " + unique_C0_C1_Rules[i].key + - "] °°-> \'" + new TextDecoder().decode(unique_C0_C1_Rules[i].output) + "\' <--> (new:) ") - } + return curr; + else return "" + }); + if (ambiguous_C0C1_vs_C0C1.length > 0) + return ("ambiguous 1-1 rule: earlier: [" + + ambiguous_C0C1_vs_C0C1[0].modifier_key + " " + + ambiguous_C0C1_vs_C0C1[0].key + "] > \'" + + new TextDecoder().decode(ambiguous_C0C1_vs_C0C1[0].output) + + "\' here: [") + + // 2-2 + // find ambiguous C2 rules vs. C2 .................................................................................................................... + // e.g. CAPS K_A > dk(A1) <-> CAPS K_A > dk(A2) ................................................................................................... + // ................................................................................................................................................... + const ambiguous_C2_vs_C2: rule_object[] = rule.filter((curr, idx) => { + if (((rule[index].rule_type === "C2")) + && ((curr.rule_type === "C2")) + && curr.modifier_prev_deadkey === "" + && curr.prev_deadkey === "" + && curr.modifier_deadkey === rule[index].modifier_deadkey + && curr.deadkey === rule[index].deadkey + && curr.dk_C2 !== rule[index].dk_C2 + && (idx < index) + ) + return curr; + else return "" + }); + if (ambiguous_C2_vs_C2.length > 0) + return ("ambiguous 2-2 rule: earlier: [" + + ambiguous_C2_vs_C2[0].modifier_deadkey + " " + + ambiguous_C2_vs_C2[0].deadkey + "] > dk( C'" + + ambiguous_C2_vs_C2[0].dk_C2 + + ") here: [") + + /*// 3-3 + // find ambiguous C0 or C1 rules vs. C0 or C1 ....................................................................................................... + // e.g. CAPS K_A > 'A' <-> CAPS K_A > 'B' ........................................................................................................ + // ................................................................................................................................................... + const ambiguous_C2_vs_C2_A: rule_object[] = rule.filter((curr, idx) => { + if (((rule[index].rule_type === "C2")) + && ((curr.rule_type === "C2")) + && curr.modifier_key === rule[index].modifier_key + && curr.key === rule[index].key + && curr.output !== rule[index].output + && curr.uniqueB !== 0 + && (idx < index) + ) + return curr; + else return "" + }); + console.log("ambiguous_C2_vs_C2_A " ) + this.writeDalaset(ambiguous_C2_vs_C2_A) + + if (ambiguous_C2_vs_C2_A.length > 0) + return ("ambiguous 3-3 rule: earlier: [" + + ambiguous_C2_vs_C2_A[0].modifier_key + " " + + ambiguous_C2_vs_C2_A[0].key + "] > \'" + + new TextDecoder().decode(ambiguous_C2_vs_C2_A[0].output) + + ") here: [")*/ + + + + + // 4-4 + // find ambiguous C3 rules vs. C3 .................................................................................................................... + // e.g. CAPS K_A > dk(B1) <-> CAPS K_A > dk(B2) ................................................................................................... + // ................................................................................................................................................... + const ambiguous_C3_vs_C3: rule_object[] = rule.filter((curr, idx) => { + if (((rule[index].rule_type === "C3")) + && ((curr.rule_type === "C3")) + && curr.modifier_prev_deadkey === rule[index].modifier_prev_deadkey + && curr.prev_deadkey === rule[index].prev_deadkey + && curr.dk_prev !== rule[index].dk_prev + && (idx < index) + ) + return curr; + else return "" + }); + if (ambiguous_C2_vs_C2.length > 0) + return ("ambiguous 4-4 rule: earlier: [" + + ambiguous_C3_vs_C3[0].modifier_prev_deadkey + " " + + ambiguous_C3_vs_C3[0].prev_deadkey + "] > dk( C'" + + ambiguous_C3_vs_C3[0].dk_prev + + ") here: [") + + + //6-6 + // find ambiguous C3 rules vs. C3 ................................................................................................................... + // e.g. dk(C1) + NCAPS K_Z > 'Z'' <-> dk(C1) + NCAPS K_Z > 'X' ................................................................................. + // ................................................................................................................................................... + const ambiguous_C3_vs_C3_B: rule_object[] = rule.filter((curr, idx) => { + if (((rule[index].rule_type === "C3")) + && ((curr.rule_type === "C3")) + && curr.modifier_prev_deadkey === rule[index].modifier_prev_deadkey + && curr.prev_deadkey === rule[index].prev_deadkey + && curr.dk_prev !== rule[index].dk_prev + && (idx < index) + ) + return curr; + else return "" + }); + if (ambiguous_C3_vs_C3_B.length > 0) + return ("ambiguous 6-6 rule: earlier: [" + + ambiguous_C3_vs_C3_B[0].modifier_key + " " + + ambiguous_C3_vs_C3_B[0].key + "] > \'" + + new TextDecoder().decode(ambiguous_C3_vs_C3_B[0].output) + + ") here: [") + + // 1-2 + // find ambiguous C0 or C1 rules vs. C2 .............................................................................................................. + // e.g. CAPS K_A > 'A'' <-> CAPS K_A > dk(A2) ..................................................................................................... + // ................................................................................................................................................... + const ambiguous_C1C1_vs_C2: rule_object[] = rule.filter((curr) => { + if ((rule[index].rule_type === "C2") + && ((curr.rule_type === "C0") || (curr.rule_type === "C1")) + && curr.modifier_prev_deadkey === "" + && curr.prev_deadkey === "" + && rule[index].modifier_deadkey === curr.modifier_key + && rule[index].deadkey === curr.key + && (rule[index].uniqueB !== 0) + ) + return curr; + else return "" + }); + if (ambiguous_C1C1_vs_C2.length > 0) + return ("ambiguous 1-2 rule: earlier: [" + + ambiguous_C1C1_vs_C2[0].modifier_key + " " + + ambiguous_C1C1_vs_C2[0].key + "] > \'" + + new TextDecoder().decode(ambiguous_C1C1_vs_C2[0].output) + + "\' here: [") + + // 1-4 + // find ambiguous C0 or C1 rules vs. C3 .............................................................................................................. + // e.g. CAPS K_A > 'A'' <-> CAPS K_A > dk(B2) ..................................................................................................... + // ................................................................................................................................................... + const ambiguous_C0C1_vs_C3: rule_object[] = rule.filter((curr, idx) => { + if ((rule[index].rule_type === "C3") + && ((curr.rule_type === "C0") || (curr.rule_type === "C1")) + && rule[index].modifier_prev_deadkey === curr.modifier_key + && rule[index].prev_deadkey === curr.key + && (rule[index].uniqueA !== 0) + && (idx < index) + ) + return curr; + else return "" + }); + if (ambiguous_C0C1_vs_C3.length > 0) + return ("ambiguous 1-4 rule: earlier: [" + + ambiguous_C0C1_vs_C3[0].modifier_key + " " + + ambiguous_C0C1_vs_C3[0].key + "] > \'" + + new TextDecoder().decode(ambiguous_C0C1_vs_C3[0].output) + + "\' here: [") + + // 3-6 + // find ambiguous C2 rules vs. C3 .................................................................................................................... + // e.g. CAPS K_A > 'A' <-> CAPS K_A > 'B' ......................................................................................................... + // ................................................................................................................................................... + const ambiguous_C2_vs_C3: rule_object[] = rule.filter((curr, idx) => { + if ((rule[index].rule_type === "C3") + && ((curr.rule_type === "C2")) + && rule[index].modifier_prev_deadkey === curr.modifier_deadkey + && rule[index].prev_deadkey === curr.deadkey + && curr.dk_prev !== rule[index].dk_C2 + && (rule[index].uniqueA !== 0) + && (rule[index].uniqueB !== 0) + && (idx < index) + ) + return curr; + else return "" + }); + if (ambiguous_C2_vs_C3.length > 0) + return ("ambiguous 1-6 rule: earlier: [" + + ambiguous_C2_vs_C3[0].modifier_key + " " + + ambiguous_C2_vs_C3[0].key + "] > \'" + + new TextDecoder().decode(ambiguous_C2_vs_C3[0].output) + + "\' here: [") + return "" } + public findDuplicateRules_new(rule: rule_object[], index: number): string { + + // ToDo is the return statement/filter func correct??? + + // 1-1 + // find ambiguous C0 or C1 rules vs. C0 or C1 ....................................................................................................... + // e.g. CAPS K_A > 'A' <-> CAPS K_A > 'B' ........................................................................................................ + // ................................................................................................................................................... + const ambiguous_C0C1_vs_C0C1: rule_object[] = rule.filter((curr, idx) => { + if (((rule[index].rule_type === "C0") || (rule[index].rule_type === "C1")) + && ((curr.rule_type === "C0") || (curr.rule_type === "C1")) + && curr.modifier_prev_deadkey === "" + && curr.prev_deadkey === "" + && curr.modifier_deadkey === "" + && curr.deadkey === "" + && curr.modifier_key === rule[index].modifier_key + && curr.key === rule[index].key + && new TextDecoder().decode(curr.output) === new TextDecoder().decode(rule[index].output) + && (idx < index) + ) + return curr; + else return "" + }); + if (ambiguous_C0C1_vs_C0C1.length > 0) + return ("duplicate 1-1 rule: earlier: [" + + ambiguous_C0C1_vs_C0C1[0].modifier_key + " " + + ambiguous_C0C1_vs_C0C1[0].key + "] > \'" + + new TextDecoder().decode(ambiguous_C0C1_vs_C0C1[0].output) + + "\' here: [") + + // 2-2 + // find ambiguous C2 rules vs. C2 .................................................................................................................... + // e.g. CAPS K_A > dk(A1) <-> CAPS K_A > dk(A2) ................................................................................................... + // ................................................................................................................................................... + const ambiguous_C2_vs_C2: rule_object[] = rule.filter((curr, idx) => { + if (((rule[index].rule_type === "C2")) + && ((curr.rule_type === "C2")) + && curr.modifier_prev_deadkey === "" + && curr.prev_deadkey === "" + && curr.modifier_deadkey === rule[index].modifier_deadkey + && curr.deadkey === rule[index].deadkey + && curr.dk_C2 === rule[index].dk_C2 + && rule[index].uniqueB !== 0 + && (idx < index) + ) + return curr; + else return "" + }); + if( (ambiguous_C2_vs_C2.length > 0)) + return ("duplicate 2-2 ccrule: earlier: [" + + ambiguous_C2_vs_C2[0].modifier_deadkey + " " + + String(ambiguous_C2_vs_C2[0].uniqueB) + + ambiguous_C2_vs_C2[0].deadkey + "] > dk(C" + + ambiguous_C2_vs_C2[0].dk_C2 + + "xx) here: [") + + /*// 3-3 + // find ambiguous C0 or C1 rules vs. C0 or C1 ....................................................................................................... + // e.g. CAPS K_A > 'A' <-> CAPS K_A > 'B' ........................................................................................................ + // ................................................................................................................................................... + const ambiguous_C2_vs_C2_A: rule_object[] = rule.filter((curr, idx) => { + if (((rule[index].rule_type === "C2")) + && ((curr.rule_type === "C2")) + && curr.modifier_key === rule[index].modifier_key + && curr.key === rule[index].key + && curr.output !== rule[index].output + && curr.uniqueB !== 0 + && (idx < index) + ) + return curr; + else return "" + }); + console.log("ambiguous_C2_vs_C2_A " ) + this.writeDalaset(ambiguous_C2_vs_C2_A) + + if (ambiguous_C2_vs_C2_A.length > 0) + return ("ambiguous 3-3 rule: earlier: [" + + ambiguous_C2_vs_C2_A[0].modifier_key + " " + + ambiguous_C2_vs_C2_A[0].key + "] > \'" + + new TextDecoder().decode(ambiguous_C2_vs_C2_A[0].output) + + ") here: [")*/ + + + + + // 4-4 + // find ambiguous C3 rules vs. C3 .................................................................................................................... + // e.g. CAPS K_A > dk(B1) <-> CAPS K_A > dk(B2) ................................................................................................... + // ................................................................................................................................................... + const ambiguous_C3_vs_C3: rule_object[] = rule.filter((curr, idx) => { + if (((rule[index].rule_type === "C3")) + && ((curr.rule_type === "C3")) + && curr.modifier_prev_deadkey === rule[index].modifier_prev_deadkey + && curr.prev_deadkey === rule[index].prev_deadkey + && curr.dk_prev + === rule[index].dk_prev + && (idx < index) + ) + return curr; + else return "" + }); + if (ambiguous_C2_vs_C2.length > 0) + return ("duplicate 4-4 rule: earlier: [" + + ambiguous_C3_vs_C3[0].modifier_prev_deadkey + " " + + ambiguous_C3_vs_C3[0].prev_deadkey + "] > dk( C'" + + ambiguous_C3_vs_C3[0].dk_prev + + ") here: [") + + + //6-6 + // find ambiguous C3 rules vs. C3 ................................................................................................................... + // e.g. dk(C1) + NCAPS K_Z > 'Z'' <-> dk(C1) + NCAPS K_Z > 'X' ................................................................................. + // ................................................................................................................................................... + const ambiguous_C3_vs_C3_B: rule_object[] = rule.filter((curr, idx) => { + if (((rule[index].rule_type === "C3")) + && ((curr.rule_type === "C3")) + && curr.modifier_prev_deadkey === rule[index].modifier_prev_deadkey + && curr.prev_deadkey === rule[index].prev_deadkey + && curr.dk_prev === rule[index].dk_prev + && (idx < index) + ) + return curr; + else return "" + }); + if (ambiguous_C3_vs_C3_B.length > 0) + return ("duplicate 6-6 rule: earlier: [" + + ambiguous_C3_vs_C3_B[0].modifier_key + " " + + ambiguous_C3_vs_C3_B[0].key + "] > \'" + + new TextDecoder().decode(ambiguous_C3_vs_C3_B[0].output) + + ") here: [") + + // 1-2 + // find ambiguous C0 or C1 rules vs. C2 .............................................................................................................. + // e.g. CAPS K_A > 'A'' <-> CAPS K_A > dk(A2) ..................................................................................................... + // ................................................................................................................................................... + const ambiguous_C1C1_vs_C2: rule_object[] = rule.filter((curr) => { + if ((rule[index].rule_type === "C2") + && ((curr.rule_type === "C0") || (curr.rule_type === "C1")) + && curr.modifier_prev_deadkey === "" + && curr.prev_deadkey === "" + && rule[index].modifier_deadkey === curr.modifier_key + && rule[index].deadkey === curr.key + && (rule[index].uniqueB === curr.uniqueB) + ) + return curr; + else return "" + }); + if (ambiguous_C1C1_vs_C2.length > 0) + return ("duplicate 1-2 rule: earlier: [" + + ambiguous_C1C1_vs_C2[0].modifier_key + " " + + ambiguous_C1C1_vs_C2[0].key + "] > \'" + + new TextDecoder().decode(ambiguous_C1C1_vs_C2[0].output) + + "\' here: [") + + // 1-4 + // find ambiguous C0 or C1 rules vs. C3 .............................................................................................................. + // e.g. CAPS K_A > 'A'' <-> CAPS K_A > dk(B2) ..................................................................................................... + // ................................................................................................................................................... + const ambiguous_C0C1_vs_C3: rule_object[] = rule.filter((curr, idx) => { + if ((rule[index].rule_type === "C3") + && ((curr.rule_type === "C0") || (curr.rule_type === "C1")) + && rule[index].modifier_prev_deadkey === curr.modifier_key + && rule[index].prev_deadkey === curr.key + && (rule[index].uniqueA === curr.uniqueA) + && (idx < index) + ) + return curr; + else return "" + }); + if (ambiguous_C0C1_vs_C3.length > 0) + return ("duplicate 1-4 rule: earlier: [" + + ambiguous_C0C1_vs_C3[0].modifier_key + " " + + ambiguous_C0C1_vs_C3[0].key + "] > \'" + + new TextDecoder().decode(ambiguous_C0C1_vs_C3[0].output) + + "\' here: [") + + // 3-6 + // find ambiguous C2 rules vs. C3 .................................................................................................................... + // e.g. CAPS K_A > 'A' <-> CAPS K_A > 'B' ......................................................................................................... + // ................................................................................................................................................... + const ambiguous_C2_vs_C3: rule_object[] = rule.filter((curr, idx) => { + if ((rule[index].rule_type === "C3") + && ((curr.rule_type === "C2")) + && rule[index].modifier_prev_deadkey === curr.modifier_deadkey + && rule[index].prev_deadkey === curr.deadkey + && curr.dk_prev !== rule[index].dk_C2 + && (rule[index].uniqueA === curr.uniqueA) + && (rule[index].uniqueB === curr.uniqueB) + && (idx < index) + ) + return curr; + else return "" + }); + if (ambiguous_C2_vs_C3.length > 0) + return ("duplicate 1-6 rule: earlier: [" + + ambiguous_C2_vs_C3[0].modifier_key + " " + + ambiguous_C2_vs_C3[0].key + "] > \'" + + new TextDecoder().decode(ambiguous_C2_vs_C3[0].output) + + "\' here: [") + + return "" + } + + public findUnAvailableRule(unique_Rules: rule_object[], index: number): string { if ( (((unique_Rules[index].rule_type === "C0") || (unique_Rules[index].rule_type === "C1") || (unique_Rules[index].rule_type === "C4")) @@ -1619,69 +2128,94 @@ export class KeylayoutToKmnConverter { public createData_Rules(data_ukelele: convert_object): string { - const isCapsused: boolean = this.checkIfCapsUsed(data_ukelele.ArrayOf_Modifiers) const maxkey: number = 50 let data: string = "" let keymarker: string = "" // prepare data for C0 and C1 - select only lines that contain C0 or C1 and create an output character - const data_C0_C1: rule_object[] = data_ukelele.ArrayOf_Rules.filter((curr) => { - if ((curr.output !== new TextEncoder().encode("") || curr.output !== undefined) - && (curr.rule_type === "C0") || (curr.rule_type === "C1")) { - return curr; - } - else return "" - }); - const unique_C0_C1_Rules: rule_object[] = data_C0_C1.reduce((unique, o) => { - if (!unique.some((obj: { output: Uint8Array; rule_type: string; modifier_key: string; key: string }) => - new TextDecoder().decode(obj.output) === new TextDecoder().decode(o.output) - && obj.key === o.key - && obj.rule_type === o.rule_type - && obj.modifier_key === o.modifier_key - ) - ) { - unique.push(o); - } - return unique; - }, []); + /* const data_C0_C1: rule_object[] = data_ukelele.ArrayOf_Rules.filter((curr) => { + if ((curr.output !== new TextEncoder().encode("") || curr.output !== undefined) + && (curr.rule_type === "C0") || (curr.rule_type === "C1")) { + return curr; + } + else return "" + }); + const unique_C0_C1_Rules: rule_object[] = data_C0_C1.reduce((unique, o) => { + if (!unique.some((obj: { output: Uint8Array; rule_type: string; modifier_key: string; key: string }) => + new TextDecoder().decode(obj.output) === new TextDecoder().decode(o.output) + && obj.key === o.key + && obj.rule_type === o.rule_type + && obj.modifier_key === o.modifier_key + ) + ) { + unique.push(o); + } + return unique; + }, []);*/ // prepare data for C2 - select only lines that contain C2 and create an output character - const data_C2: rule_object[] = data_ukelele.ArrayOf_Rules.filter((curr) => { - if ((curr.output !== new TextEncoder().encode("") || curr.output !== undefined) - && (curr.rule_type === "C2")) { - return curr; - } - else return "" - }); - const unique_C2_Rules: rule_object[] = data_C2.reduce((unique, o) => { - if (!unique.some((obj: { output: Uint8Array; rule_type: string; modifier_key: string; modifier_deadkey: string; deadkey: string; key: string }) => - - new TextDecoder().decode(obj.output) === new TextDecoder().decode(o.output) - && new TextDecoder().decode(obj.output) !== "" - - && obj.rule_type === o.rule_type - - && obj.modifier_key === o.modifier_key - && obj.key === o.key - - && obj.modifier_deadkey === o.modifier_deadkey - && obj.deadkey === o.deadkey - ) - ) { - unique.push(o); - } - return unique; - }, []); + /* const data_C2: rule_object[] = data_ukelele.ArrayOf_Rules.filter((curr) => { + if ((curr.output !== new TextEncoder().encode("") || curr.output !== undefined) + && (curr.rule_type === "C2")) { + return curr; + } + else return "" + }); + const unique_C2_Rules: rule_object[] = data_C2.reduce((unique, o) => { + if (!unique.some((obj: { output: Uint8Array; rule_type: string; modifier_key: string; modifier_deadkey: string; deadkey: string; key: string }) => + + new TextDecoder().decode(obj.output) === new TextDecoder().decode(o.output) + && new TextDecoder().decode(obj.output) !== "" + + && obj.rule_type === o.rule_type + + && obj.modifier_key === o.modifier_key + && obj.key === o.key + + && obj.modifier_deadkey === o.modifier_deadkey + && obj.deadkey === o.deadkey + ) + ) { + unique.push(o); + } + return unique; + }, []);*/ // prepare data for C3 - select only lines that contain C3 and create an output character - const data_C3: rule_object[] = data_ukelele.ArrayOf_Rules.filter((curr) => { + /* const data_C3: rule_object[] = data_ukelele.ArrayOf_Rules.filter((curr) => { + if ((curr.output !== new TextEncoder().encode("") || curr.output !== undefined) + && (curr.rule_type === "C3")) { + return curr; + } + else return "" + }); + const unique_C3_Rules: rule_object[] = data_C3.reduce((unique, o) => { + if (!unique.some((obj: { output: Uint8Array; rule_type: string; modifier_key: string; modifier_deadkey: string; prev_deadkey: string; modifier_prev_deadkey: string; deadkey: string; key: string }) => + new TextDecoder().decode(obj.output) === new TextDecoder().decode(o.output) + + && obj.rule_type === o.rule_type + && obj.modifier_key === o.modifier_key + && obj.key === o.key + + && obj.modifier_deadkey === o.modifier_deadkey + && obj.deadkey === o.deadkey + + && obj.modifier_prev_deadkey === o.modifier_prev_deadkey + && obj.prev_deadkey === o.prev_deadkey) + ) { + unique.push(o); + } + return unique; + }, []);*/ + + const data_CAll: rule_object[] = data_ukelele.ArrayOf_Rules.filter((curr) => { if ((curr.output !== new TextEncoder().encode("") || curr.output !== undefined) - && (curr.rule_type === "C3")) { + && (curr.rule_type === "C0") || (curr.rule_type === "C1") || (curr.rule_type === "C2") || (curr.rule_type === "C3")) { return curr; } else return "" }); - const unique_C3_Rules: rule_object[] = data_C3.reduce((unique, o) => { + const unique_CAll_Rules: rule_object[] = data_CAll.reduce((unique, o) => { if (!unique.some((obj: { output: Uint8Array; rule_type: string; modifier_key: string; modifier_deadkey: string; prev_deadkey: string; modifier_prev_deadkey: string; deadkey: string; key: string }) => new TextDecoder().decode(obj.output) === new TextDecoder().decode(o.output) @@ -1699,82 +2233,117 @@ export class KeylayoutToKmnConverter { } return unique; }, []); + console.log("xx data_ukelele.ArrayOf_Rules", data_ukelele.ArrayOf_Rules.length) + //console.log("xx data_ukelele.ArrayOf_Rules", this.writeDalaset(data_ukelele.ArrayOf_Rules)) + + console.log("xx unique_CAll_Rules", unique_CAll_Rules.length) + //console.log("xx unique_CAll_Rules", this.writeDalaset(unique_CAll_Rules)) + + /* console.log("xx unique_C0_C1_Rules", unique_C0_C1_Rules.length) + //console.log("xx unique_C0_C1_Rules", this.writeDalaset(unique_C0_C1_Rules)) + + console.log("xx unique_C2_Rules", unique_C2_Rules.length) + //console.log("xx unique_C2_Rules", this.writeDalaset(unique_C2_Rules)) + console.log("xx data_C2", data_C2.length) + + /*console.log("xx data_C3", data_C3.length) + console.log("xx unique_C3_Rules", unique_C3_Rules.length)*/ + //console.log("xx unique_C3_Rules", this.writeDalaset(unique_C3_Rules))*/ + + //................................................ C0 C1 ................................................................ + //................................................ C0 C1 ................................................................ + //................................................ C0 C1 ................................................................ + + for (let i = 0; i < unique_CAll_Rules.length; i++) { + + if ((unique_CAll_Rules[i].rule_type === "C0") || (unique_CAll_Rules[i].rule_type === "C1")) { + // lookup key nr of the key that is being processed + let keyNr: number = 0; + for (let j = 0; j < maxkey; j++) { + if (this.map_UkeleleKC_To_VK(j) === unique_CAll_Rules[i].key) + keyNr = j + } + // skip keyNr 48 ( TAB ) + if (keyNr === 48) + continue - for (let i = 0; i < unique_C0_C1_Rules.length; i++) { - - // lookup key nr of the key that is being processed - let keyNr: number = 0; - for (let j = 0; j < maxkey; j++) { - if (this.map_UkeleleKC_To_VK(j) === unique_C0_C1_Rules[i].key) - keyNr = j - } - - // skip keyNr 48 ( TAB ) - if (keyNr === 48) - continue - - // add a line after rules of each key - if (unique_C0_C1_Rules[i].key !== keymarker) - data += '\n' + // add a line after rules of each key + if (unique_CAll_Rules[i].key !== keymarker) + data += '\n' - let warningtext: string = "c C0 WARNING: " - warningtext = warningtext + this.findDuplicateRules(unique_C0_C1_Rules, i, "C01") - warningtext = warningtext + this.findAmbiguousRules(unique_C0_C1_Rules, i, "C01") - warningtext = warningtext + this.findUnAvailableRule(unique_C0_C1_Rules, i) + let warningtext: string = "c C0 WARNING: " + warningtext = warningtext + this.findDuplicateRules(unique_CAll_Rules, i, "C01") + //warningtext = warningtext + this.findDuplicateRules(unique_CAll_Rules, i) + // warningtext = warningtext + this.findAmbiguousRules_2(unique_CAll_Rules, i, "C01") // todo we do not need C01 ?? + warningtext = warningtext + this.findAmbiguousRules(unique_CAll_Rules, i) // todo we do not need C01 ?? + warningtext = warningtext + this.findUnAvailableRule(unique_CAll_Rules, i) - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // ~~~~ draft print ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - if ((KeylayoutToKmnConverter.print_draft) && (new TextDecoder().decode(unique_C0_C1_Rules[i].output) !== "")) { - if (warningtext === "c C0 WARNING: ") - data += unique_C0_C1_Rules[i].rule_type + keyNr + keyNr + "-(modif:" + unique_C0_C1_Rules[i].rule_type + "-" + unique_C0_C1_Rules[i].dk_prev + `) + [` + (unique_C0_C1_Rules[i].modifier_key + ' ' + unique_C0_C1_Rules[i].key).trim() + `] °°-> \'` + new TextDecoder().decode(unique_C0_C1_Rules[i].output) + '\'\n' - else - data += warningtext + keyNr + "-(modif:" + unique_C0_C1_Rules[i].rule_type + "-" + unique_C0_C1_Rules[i].dk_prev + `) + [` + (unique_C0_C1_Rules[i].modifier_key + ' ' + unique_C0_C1_Rules[i].key).trim() + `] **°°-> \'` + new TextDecoder().decode(unique_C0_C1_Rules[i].output) + '\'\n' - } - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // ~~~~ draft print end ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - else { - if (warningtext === "c C0 WARNING: ") - data += "+ [" + (unique_C0_C1_Rules[i].modifier_key + ' ' + unique_C0_C1_Rules[i].key).trim() + `] > \'` + new TextDecoder().decode(unique_C0_C1_Rules[i].output) + '\'\n' - else - data += warningtext + "[" + (unique_C0_C1_Rules[i].modifier_key + ' ' + unique_C0_C1_Rules[i].key).trim() + `] > \'` + new TextDecoder().decode(unique_C0_C1_Rules[i].output) + '\'\n' + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~ draft print ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ((unique_CAll_Rules[i].rule_type === "C0") || (unique_CAll_Rules[i].rule_type === "C1") + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + if ((KeylayoutToKmnConverter.print_draft) && (new TextDecoder().decode(unique_CAll_Rules[i].output) !== "")) { + if (warningtext === "c C0 WARNING: ") + data += unique_CAll_Rules[i].rule_type + keyNr + keyNr + "-(modif:" + unique_CAll_Rules[i].rule_type + "-" + unique_CAll_Rules[i].dk_prev + `) + [` + (unique_CAll_Rules[i].modifier_key + ' ' + unique_CAll_Rules[i].key).trim() + `] °°-> \'` + new TextDecoder().decode(unique_CAll_Rules[i].output) + '\'\n' + else + data += warningtext + keyNr + "-(modif:" + unique_CAll_Rules[i].rule_type + "-" + unique_CAll_Rules[i].dk_prev + `) + [` + (unique_CAll_Rules[i].modifier_key + ' ' + unique_CAll_Rules[i].key).trim() + `] **°°-> \'` + new TextDecoder().decode(unique_CAll_Rules[i].output) + '\'\n' + } + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~ draft print end ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + else { + if (warningtext === "c C0 WARNING: ") + data += "+ [" + (unique_CAll_Rules[i].modifier_key + ' ' + unique_CAll_Rules[i].key).trim() + `] > \'` + new TextDecoder().decode(unique_CAll_Rules[i].output) + '\'\n' + else + data += warningtext + (unique_CAll_Rules[i].modifier_key + ' ' + unique_CAll_Rules[i].key).trim() + `] > \'` + new TextDecoder().decode(unique_CAll_Rules[i].output) + '\'\n' + } + keymarker = unique_CAll_Rules[i].key } - keymarker = unique_C0_C1_Rules[i].key } - - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~ draft print ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + if (KeylayoutToKmnConverter.print_draft) { data += "\n########## C2 #################################################################\n" } - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // ~~~~ draft print end ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + else + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~ draft print end ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + data += "\n" + + //................................................ C2 ................................................................... + //................................................ C2 ................................................................... + //................................................ C2 ................................................................... + - for (let k = 0; k < unique_C2_Rules.length; k++) { + for (let k = 0; k < unique_CAll_Rules.length; k++) { - if ((unique_C2_Rules[k].rule_type === "C2")) { + if (unique_CAll_Rules[k].rule_type === "C2") { let warningtext: string = "c C2 WARNING: " - warningtext = warningtext + this.findDuplicateRules(unique_C2_Rules, k, "C2") - warningtext = warningtext + this.findAmbiguousRules(unique_C2_Rules, k, "C2") - warningtext = warningtext + this.findUnAvailableRule(unique_C2_Rules, k) + warningtext = warningtext + this.findDuplicateRules(unique_CAll_Rules, k, "C2") + //warningtext = warningtext + this.findDuplicateRules(unique_CAll_Rules, k) + warningtext = warningtext + this.findAmbiguousRules(unique_CAll_Rules, k) + //warningtext = warningtext + this.findAmbiguousRules_2(unique_CAll_Rules, k, "C2") + warningtext = warningtext + this.findUnAvailableRule(unique_CAll_Rules, k) + console.log(" warningtext", warningtext) // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~ draft print ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (KeylayoutToKmnConverter.print_draft) { if (warningtext === "c C2 WARNING: ") { - data += "new: [" + unique_C2_Rules[k].modifier_deadkey + " " + unique_C2_Rules[k].deadkey + "] > XXX" + - " [" + unique_C2_Rules[k].modifier_key + " " + unique_C2_Rules[k].key + "] °°-> \'" + new TextDecoder().decode(unique_C2_Rules[k].output) + "\'" + data += "new: [" + unique_CAll_Rules[k].modifier_deadkey + " " + unique_CAll_Rules[k].deadkey + "] > XXX" + + " [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] °°-> \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'" } else { - data += warningtext + " [" + unique_C2_Rules[k].modifier_deadkey + " " + unique_C2_Rules[k].deadkey + "] > XXX" + - "[" + unique_C2_Rules[k].modifier_key + " " + unique_C2_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_C2_Rules[k].output) + "\'" + data += warningtext + " [" + unique_CAll_Rules[k].modifier_deadkey + " " + unique_CAll_Rules[k].deadkey + "] > XXX" + + "[" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'" } } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -1783,19 +2352,32 @@ export class KeylayoutToKmnConverter { else { // all OK if (warningtext === "c C2 WARNING: ") { - data += "now + [" + unique_C2_Rules[k].modifier_deadkey + " " + unique_C2_Rules[k].deadkey + "] > dk(C" + String(unique_C2_Rules[k].dk_C2) + ")\n" - data += "dk(C" + String(unique_C2_Rules[k].dk_C2) + ") + [" + unique_C2_Rules[k].modifier_key + " " + unique_C2_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_C2_Rules[k].output) + "\'\n" + + if (unique_CAll_Rules[k].uniqueB !== 0) { + data += "+ [" + unique_CAll_Rules[k].modifier_deadkey + " " + unique_CAll_Rules[k].deadkey + "] > dk(C" + String(unique_CAll_Rules[k].dk_C2) + ")\n" + } + //data += "---\n" + data += "dk(C" + String(unique_CAll_Rules[k].dk_C2) + ") + [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'\n" + + + + } // warning avail else { - data += warningtext + " [" + unique_C2_Rules[k].modifier_deadkey + " " + unique_C2_Rules[k].deadkey + "] > dk(C" + String(unique_C2_Rules[k].dk_C2) + ")\n" - data += warningtext + " dk(C" + String(unique_C2_Rules[k].dk_C2) + ") [" + unique_C2_Rules[k].modifier_key + " " + unique_C2_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_C2_Rules[k].output) + "\'\n" + data += warningtext + unique_CAll_Rules[k].modifier_deadkey + " " + unique_CAll_Rules[k].deadkey + "] > dk(C" + String(unique_CAll_Rules[k].dk_C2) + ")\n" + data += " dk(C" + String(unique_CAll_Rules[k].dk_C2) + ") + [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'\n" } + } data += "\n" } } + //................................................ C3 ................................................................... + //................................................ C3 ................................................................... + //................................................ C3 ................................................................... + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~ draft print ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -1806,51 +2388,77 @@ export class KeylayoutToKmnConverter { // ~~~~ draft print end ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - for (let k = 0; k < unique_C3_Rules.length; k++) { - if ((unique_C3_Rules[k].rule_type === "C3")) { + console.log("NOW print C§ ",) - let warningtext: string = "c C3 WARNING: " - warningtext = warningtext + this.findDuplicateRules(unique_C3_Rules, k, "C3") // OK - warningtext = warningtext + this.findAmbiguousRules(unique_C3_Rules, k, "C3") // OK - warningtext = warningtext + this.findUnAvailableRule(unique_C3_Rules, k) // OK + /* for (let k = 0; k < unique_CAll_Rules.length; k++) { + if (unique_CAll_Rules[k].rule_type === "C3") { + this.writeDalasetSingle(unique_CAll_Rules[k]) + } + }*/ + + for (let k = 0; k < unique_CAll_Rules.length; k++) { + + if (unique_CAll_Rules[k].rule_type === "C3") { + + let warningtext: string = "c C3 WARNING: " + warningtext = warningtext + this.findDuplicateRules(unique_CAll_Rules, k, "C3") // OK + //warningtext = warningtext + this.findDuplicateRules(unique_CAll_Rules, k) // OK + warningtext = warningtext + this.findAmbiguousRules(unique_CAll_Rules, k) // OK + warningtext = warningtext + this.findUnAvailableRule(unique_CAll_Rules, k) // OK // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~ draft print ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (KeylayoutToKmnConverter.print_draft) { if (warningtext === "c C3 WARNING: ") { - data += " [" + unique_C3_Rules[k].modifier_prev_deadkey + " " + unique_C3_Rules[k].prev_deadkey + "] > XXX " + - "[" + unique_C3_Rules[k].modifier_deadkey + " " + unique_C3_Rules[k].deadkey + "] > YYY " + - " [" + unique_C3_Rules[k].modifier_key + " " + unique_C3_Rules[k].key + "] °°-> \'" + new TextDecoder().decode(unique_C3_Rules[k].output) + "\'" + data += " [" + unique_CAll_Rules[k].modifier_prev_deadkey + " " + unique_CAll_Rules[k].prev_deadkey + "] > XXX " + + "[" + unique_CAll_Rules[k].modifier_deadkey + " " + unique_CAll_Rules[k].deadkey + "] > YYY " + + " [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] °°-> \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'" } else { - data += warningtext + " [" + unique_C3_Rules[k].modifier_prev_deadkey + " " + unique_C3_Rules[k].prev_deadkey + "] > XXX " + - "[" + unique_C3_Rules[k].modifier_deadkey + " " + unique_C3_Rules[k].deadkey + "] > YYY " + - " [" + unique_C3_Rules[k].modifier_key + " " + unique_C3_Rules[k].key + "] °°-> \'" + new TextDecoder().decode(unique_C3_Rules[k].output) + "\'" + data += warningtext + " [" + unique_CAll_Rules[k].modifier_prev_deadkey + " " + unique_CAll_Rules[k].prev_deadkey + "] > XXX " + + "[" + unique_CAll_Rules[k].modifier_deadkey + " " + unique_CAll_Rules[k].deadkey + "] > YYY " + + " [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] °°-> \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'" } } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // ~~~~ draft print end ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~ draft print end ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ else { if (warningtext === "c C3 WARNING: ") { - data += "+ [" + this.create_kmn_modifier(unique_C3_Rules[k].modifier_prev_deadkey, isCapsused) + " " + unique_C3_Rules[k].prev_deadkey + "] > dk(A" + String(unique_C3_Rules[k].dk_prev) + ")\n" - data += "dk(A" + String(unique_C3_Rules[k].dk_prev) + ") + [" + this.create_kmn_modifier(unique_C3_Rules[k].modifier_deadkey, isCapsused) + " " + unique_C3_Rules[k].deadkey + "] > dk(B" + String(unique_C3_Rules[k].dk) + ")\n" - data += "dk(B" + String(unique_C3_Rules[k].dk) + ") + [" + this.create_kmn_modifier(unique_C3_Rules[k].modifier_key, isCapsused) + " " + unique_C3_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_C3_Rules[k].output) + "\'\n" + + if (unique_CAll_Rules[k].uniqueA !== 0) { + data += "+ [" + unique_CAll_Rules[k].modifier_prev_deadkey + " " + unique_CAll_Rules[k].prev_deadkey + "] > dk(A" + String(unique_CAll_Rules[k].dk_prev) + ")\n" + } + + if ((unique_CAll_Rules[k].uniqueB !== 0) && (unique_CAll_Rules[k].uniqueA !== 0)) { + data += "dk(A" + String(unique_CAll_Rules[k].dk_prev) + ") + [" + unique_CAll_Rules[k].modifier_deadkey + " " + unique_CAll_Rules[k].deadkey + "] > dk(B" + String(unique_CAll_Rules[k].dk) + ")\n" + } + + data += "dk(B" + String(unique_CAll_Rules[k].dk) + ") + [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'\n" + data += "\n" } + else { - data += warningtext + " [" + this.create_kmn_modifier(unique_C3_Rules[k].modifier_prev_deadkey, isCapsused) + " " + unique_C3_Rules[k].prev_deadkey + "] > dk(A" + String(unique_C3_Rules[k].dk_prev) + ")\n" - data += warningtext + " dk(A" + String(unique_C3_Rules[k].dk_prev) + ") + [" + this.create_kmn_modifier(unique_C3_Rules[k].modifier_deadkey, isCapsused) + " " + unique_C3_Rules[k].deadkey + "] > dk(B" + String(unique_C3_Rules[k].dk) + ")\n" - data += warningtext + " dk(B" + String(unique_C3_Rules[k].dk) + ") + [" + this.create_kmn_modifier(unique_C3_Rules[k].modifier_key, isCapsused) + " " + unique_C3_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_C3_Rules[k].output) + "\'\n" + data += warningtext + unique_CAll_Rules[k].modifier_prev_deadkey + " " + unique_CAll_Rules[k].prev_deadkey + "] > dk(A" + String(unique_CAll_Rules[k].dk_prev) + ")\n" + data += "dk(A" + String(unique_CAll_Rules[k].dk_prev) + ") + [" + unique_CAll_Rules[k].modifier_deadkey + " " + unique_CAll_Rules[k].deadkey + "] > dk(B" + String(unique_CAll_Rules[k].dk) + ")\n" + data += "dk(B" + String(unique_CAll_Rules[k].dk) + ") + [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'\n" } } data += "\n" } } + + + + console.log("NOW START C§ 5",) + + data += '\n' return data } + /// console log all entries C3 public writeDalaset(dataRules: rule_object[]) { for (let i = 0; i < dataRules.length; i++) { @@ -1863,12 +2471,13 @@ export class KeylayoutToKmnConverter { "| ", (dataRules[i].modifier_prev_deadkey !== "" ? dataRules[i].modifier_prev_deadkey.padEnd(33, " ") : "--".padEnd(33, " ")), (dataRules[i].prev_deadkey !== "" ? dataRules[i].prev_deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), (dataRules[i].dk_prev !== 0 ? ("dk(A" + String(dataRules[i].dk_prev) + ")").padEnd(11, " ") : "--".padEnd(11, " ")), + (dataRules[i].uniqueA !== 0 ? ("unique(A" + String(dataRules[i].uniqueA) + ")").padEnd(11, " ") : "--".padEnd(11, " ")), (dataRules[i].modifier_deadkey !== "" ? dataRules[i].modifier_deadkey.padEnd(30, " ") : "--".padEnd(30, " ")), (dataRules[i].deadkey !== "" ? dataRules[i].deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), - dataRules[i].rule_type === "C2" ? (dataRules[i].dk !== 0 ? ("dk(C" + String(dataRules[i].dk) + ")").padEnd(9, " ") : "--".padEnd(9, " ")) : ((dataRules[i].dk !== 0 ? ("dk(B" + String(dataRules[i].dk) + ")").padEnd(9, " ") : "--".padEnd(9, " "))), + dataRules[i].rule_type === "C2" ? (dataRules[i].uniqueB !== 0 ? ("unique(C" + String(dataRules[i].uniqueB) + ")").padEnd(9, " ") : "--".padEnd(9, " ")) : ((dataRules[i].uniqueA !== 0 ? ("unique(B" + String(dataRules[i].dk) + ")").padEnd(9, " ") : "--".padEnd(9, " "))), "| ", (dataRules[i].modifier_key !== "" ? dataRules[i].modifier_key.padEnd(40, " ") : "--".padEnd(40, " ")), @@ -1878,6 +2487,31 @@ export class KeylayoutToKmnConverter { "| °°") } + } + public writeDalasetSingle(dataRules: rule_object) { + + console.log("dataRules ", + dataRules.rule_type !== "" ? dataRules.rule_type : "--".padEnd(4, " ") + , + + "| ", (dataRules.modifier_prev_deadkey !== "" ? dataRules.modifier_prev_deadkey.padEnd(33, " ") : "--".padEnd(33, " ")), + (dataRules.prev_deadkey !== "" ? dataRules.prev_deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), + (dataRules.dk_prev !== 0 ? ("dk(A" + String(dataRules.dk_prev) + ")").padEnd(11, " ") : "--".padEnd(11, " ")), + (dataRules.uniqueA !== 0 ? ("unique(A" + String(dataRules.uniqueA) + ")").padEnd(11, " ") : "--".padEnd(11, " ")), + + + (dataRules.modifier_deadkey !== "" ? dataRules.modifier_deadkey.padEnd(30, " ") : "--".padEnd(30, " ")), + (dataRules.deadkey !== "" ? dataRules.deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), + dataRules.rule_type === "C2" ? (dataRules.dk !== 0 ? ("dk(C" + String(dataRules.dk) + ")").padEnd(9, " ") : "--".padEnd(9, " ")) : ((dataRules.dk !== 0 ? ("dk(B" + String(dataRules.dk) + ")").padEnd(9, " ") : "--".padEnd(9, " "))), + dataRules.rule_type === "C2" ? (dataRules.uniqueB !== 0 ? ("unique(C" + String(dataRules.uniqueB) + ")").padEnd(9, " ") : "--".padEnd(9, " ")) : ((dataRules.uniqueA !== 0 ? ("unique(B" + String(dataRules.dk) + ")").padEnd(9, " ") : "--".padEnd(9, " "))), + + + "| ", (dataRules.modifier_key !== "" ? dataRules.modifier_key.padEnd(40, " ") : "--".padEnd(40, " ")), + (dataRules.key !== "" ? dataRules.key.padEnd(8, " ") : "--".padEnd(8, " ")), + (new TextDecoder().decode(dataRules.output) !== "" ? new TextDecoder().decode(dataRules.output).padEnd(10, " ") : ("--" + dataRules.output) + "--"), + + "| °°") + } public createData_Stores(data_ukelele: convert_object): string { @@ -1943,12 +2577,14 @@ class Rules { public prev_deadkey: string, public prev_deadkeys_Ch: Uint8Array, public dk_prev: number, + public uniqueA: number, public modifier_deadkey: string, /* second key used by C2,C3 rules*/ public deadkey: string, public deadkeys_Ch: Uint8Array, public dk: number, //todo remove one public dk_C2: number, + public uniqueB: number, public modifier_key: string, /* third key used by C0,C1,C2,C3,C4 rules*/ public key: string, From d3db314e50998ebbf34979b59ace1472ca63946e Mon Sep 17 00:00:00 2001 From: Sabine Date: Thu, 6 Feb 2025 18:05:35 +0100 Subject: [PATCH 047/251] feat(developer): kmc-convert tidy up; split read() into read + convert() --- .../keylayout-to-kmn-converter.ts | 1058 +++++++---------- 1 file changed, 428 insertions(+), 630 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 8cdcf890f29..15fabac033b 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -12,7 +12,7 @@ import boxXmlArray = util.boxXmlArray;*/ // TODO keylayout->kmn // OK modifiers: The identifier of the element to use for this range of hardware keyboard types. // OK defaultIndex: The table number to use for modifier key combinations which are not explicitly specified by any element within the . - // write read, convert, write + // OK write read, convert, write // tests for 3 functions read write convert // OK add data to object // OK Use filter functions @@ -38,7 +38,7 @@ import boxXmlArray = util.boxXmlArray;*/ // TODO move func outside of class // Functions as object methods? // objects contain only used stuff READ in: -- out: only read arrays / CONVERT in: only read arrays out: return only to write arrays - // Use catch blocks for file read + // OK Use catch blocks for file read // OK read: answer : + [K_A] > 'a' is OK / TODO which format to use in output ? + [K_A] > 'a' (character code) or + [K_A] > U+0061 (virt Keycode) // read TODO which stores? // OK one entry vs several entry in tags @@ -48,88 +48,50 @@ import boxXmlArray = util.boxXmlArray;*/ // OK naming of for-loop var i,j,k?... // warning if contrADICTING RULES E:G: [ 'modifier_C0', 'SHIFT NCAPS', 'K_C', 'c'], vs [ 'modifier_C0', 'SHIFT NCAPS', 'K_C', 'C' ], // OK print NCAPS as the first of the modifiers in create_kmn_modifier - // use boxXmlArray from codebase instead of my own + // OK use boxXmlArray from codebase instead of my own // OK where are rules for action+none ( a, e, u, etc) // OK order of object member var - // readfilesync with paths better way? - // rearrange code to use read, convert, write - // TODO rewrite explanantion for object instead of array - // remove all any types + // OK readfilesync with paths better way? + // OK rearrange code to use read, convert, write + // OK TODO rewrite explanantion for object instead of array + // OK remove all any types // check code for code styles keyman // public dk: number, //todo remove one - // todo use from elsewhere boxXmlArray_S - // prev_deadkeys_Ch: Uint8Array, /* Todo needed?*/ + // OK todo use from elsewhere boxXmlArray_S + // OK prev_deadkeys_Ch: Uint8Array, /* Todo needed?*/ // Todo remove print_draft // TODO throws - // Todo files/path !!! + // OK Todo files/path !!! // TODO need to use export const USVirtualKeyCodes here // start Tests v ToDo remove...................................... - // TODO remove: test files: checkif kmn gats the same output as ukelele file(except for C3 t works well :)) + // TODO remove: test files: checkif kmn gets the same output as ukelele file(except for C3 t works well :)) // ToDo needed methods // Filter functions use the same type // where to put documentation + // dk <-> dk_C2 ??? + // check if we use the same algorithm to get Block1 data + // check uniqueA, uniqueV, dk_prv, dk, dk_C2 } import { XMLParser } from 'fast-xml-parser'; // for reading a file import { readFileSync } from 'fs'; -//import { writeFileSync } from "fs"; // for writing a file -//import * as fs from 'fs'; // what is this/do I need it? - either import all or seperately like above +import { util } from '@keymanapp/common-types'; +import boxXmlArray = util.boxXmlArray; +function boxArrays(source: any) { + boxXmlArray(source.layouts, 'layout'); + boxXmlArray(source.terminators, 'when'); + boxXmlArray(source, 'keyMapSet'); + boxXmlArray(source.keyMapSet, 'keyMap'); + boxXmlArray(source.action, 'actions'); -// todo use from elsewhere -function boxXmlArray_S(o: any, x: string): void { - if (typeof o == 'object' && !Array.isArray(o[x])) { - if (o[x] === null || o[x] === undefined) { - o[x] = []; - } - else { - o[x] = [o[x]]; - } - } -} -/* -// example: - - - - - - - - - - - - - - -then write: -if(source?.keyboard3?.AAA) { - - // parent tag child-tag - boxXmlArray(source?.keyboard3?.AAA, 'BBB'); - for(const BBB_Var of source?.keyboard3?.AAA?.BBB) { - boxXmlArray(BBB_Var, 'CCC'); - } -} -*/ - -// todo use from elsewhere -function boxArrays_S(source: any) { - // parent tag child-tag - boxXmlArray_S(source.layouts, 'layout'); - boxXmlArray_S(source.terminators, 'when'); - boxXmlArray_S(source, 'keyMapSet'); - boxXmlArray_S(source.keyMapSet, 'keyMap'); - boxXmlArray_S(source.action, 'actions'); - - boxXmlArray_S(source?.modifierMap, 'keyMapSelect'); + boxXmlArray(source?.modifierMap, 'keyMapSelect'); for (const keyMapSelect of source?.modifierMap?.keyMapSelect) { - boxXmlArray_S(keyMapSelect, 'modifier'); + boxXmlArray(keyMapSelect, 'modifier'); } - boxXmlArray_S(source?.actions, 'action'); + boxXmlArray(source?.actions, 'action'); for (const action of source?.actions?.action) { - boxXmlArray_S(action, 'when'); + boxXmlArray(action, 'when'); } return source; } @@ -139,13 +101,11 @@ export interface rule_object { modifier_prev_deadkey: string, /* string of modifiers for the first key (e.g. "NCAPS RALT CTRL") */ prev_deadkey: string, /* name of the first key (e.g. K_U) */ - prev_deadkeys_Ch: Uint8Array, /* Todo needed?*/ dk_prev: number, /* Todo needed?*/ uniqueA: number, modifier_deadkey: string, /* string of modifiers for the second key (e.g. "NCAPS RALT CTRL") */ deadkey: string, /* name of the second key */ - deadkeys_Ch: Uint8Array, /* Todo needed?*/ dk: number, /* Todo needed?*/ dk_C2: number, uniqueB: number, @@ -189,14 +149,15 @@ export class KeylayoutToKmnConverter { } console.log(' _S2 first READ file ........................................in:', inputFilename); - const inArray: convert_object = this.read(inputFilename) + const JsonO: object = this.read(inputFilename) - if (!inArray) { + if (!JsonO) { return null; } console.log(' _S2 then CONVERT ........................................'); - const outArray: convert_object = await this.convert(inArray); + //const outArray: convert_object = await this.convert(inArray); + const outArray: convert_object = await this.convert(JsonO); if (!outArray) { return null; @@ -219,41 +180,50 @@ export class KeylayoutToKmnConverter { * member function to read filename ( a .keylayout-file) and write contents into Uint8Array keys_all_Layers * @param filename the ukelele .keylayout-file to be converted * @return in case of success Uint8Array keys_all_Layers; else null - */ - public read(filename: string): convert_object { - - const modifierBehavior: string[][] = [] // modifier for each keymapselect - const RuleObject: rule_object[] = [] // an array of objects which hold data for a kmn rule + */ public read(filename: string): Object { + let xmlFile + let jsonObj = [] - const DataObject: convert_object = { - ArrayOf_Modifiers: modifierBehavior, // e.g. 18 modifiers in 8 KeyMapSelect(behaviors) - ArrayOf_Rules: RuleObject - }; - - console.log("inputFilename read", filename) const options = { ignoreAttributes: false, attributeNamePrefix: '@_' // to access the attribute }; - // Todo files/path !!! - console.log("xmlFile_name", (process.cwd() + "\\data" + filename.substring(filename.lastIndexOf("\\"))).replace(" ", "")) - //const xmlFile = readFileSync(`${process.cwd()}/data/MySample.keylayout`, 'utf8') - const xmlFile = readFileSync((process.cwd() + "\\data" + filename.substring(filename.lastIndexOf("\\"))).replace(" ", ""), 'utf8'); - console.log("xmlFile parsed ") + try { + + //const xmlFile = readFileSync(`${process.cwd()}/data/MySample.keylayout`, 'utf8') + xmlFile = readFileSync((process.cwd() + "\\data" + filename.substring(filename.lastIndexOf("\\"))).replace(" ", ""), 'utf8'); + const parser = new XMLParser(options); + jsonObj = parser.parse(xmlFile); // get plain Object + boxArrays(jsonObj.keyboard);// jsonObj now contains only arrays; no single fields + + console.log("inputFilename read", filename) + } + catch { + // Todo how to break correctly; return what?? + console.log(" FILE NOT FOUND") + } + return jsonObj + } + - // we don`t need file-read with uint8array return - /*const fullPath = (process.cwd() + "\\data" + filename.substring(filename.lastIndexOf("\\"))).replace(" ", "") - const xmlFile1 = this.callbacks.loadFile(fullPath) - console.log("xmlFile1",xmlFile1)*/ + /** + * @brief member function to convert data of .keylayout-file to kmn-file This will convert/rename modifiers, position of Keys and deadkeys and save into an array + * @param take data_ukelele and create a mapping from mac Keycodes to key-names and save to data_ukelele object + * @param data_ukelele (Uint8Array) data of the ukelele .keylayout-file + * @return outArray Uint8Array keys_all_Layers, the converted data for kmn-files if all layers have been converted; else null + */ + public convert(jsonObj: any): convert_object { - const parser = new XMLParser(options); - const jsonObj = parser.parse(xmlFile); // get plain Object + const modifierBehavior: string[][] = [] // modifier for each keymapselect + const RuleObject: rule_object[] = [] // an array of objects which hold data for a kmn rule - // jsonObj now contains only arrays; no single fields - boxArrays_S(jsonObj.keyboard); + const DataObject: convert_object = { + ArrayOf_Modifiers: modifierBehavior, // e.g. 18 modifiersCombinations in 8 KeyMapSelect(behaviors) + ArrayOf_Rules: RuleObject + }; - // MODIFIER MAP: get behaviours(=MapIndex) and modifiers (e.g. shift? leftShift caps? ) + // create an array of modifier Combinations (e.g. shift? leftShift caps? ) for (let j = 0; j < jsonObj.keyboard.modifierMap.keyMapSelect.length; j++) { const singleModifierSet: string[] = [] for (let k = 0; k < jsonObj.keyboard.modifierMap.keyMapSelect[j].modifier.length; k++) { @@ -262,23 +232,10 @@ export class KeylayoutToKmnConverter { modifierBehavior.push(singleModifierSet) } - // Todo ? move to convert? - // TODO review condition return this.createRuleData(DataObject, jsonObj) } - /** - * @brief member function to convert data of .keylayout-file to kmn-file This will convert/rename modifiers, position of Keys and deadkeys and save into an array - * @param take data_ukelele and create a mapping from mac Keycodes to key-names and save to data_ukelele object - * @param data_ukelele (Uint8Array) data of the ukelele .keylayout-file - * @return outArray Uint8Array keys_all_Layers, the converted data for kmn-files if all layers have been converted; else null - */ - public convert(data_ukelele: convert_object): convert_object { - return data_ukelele - } - - /** * @brief member function to write data fro object to file * @param data_ukelele the array holding keyboard data @@ -295,11 +252,6 @@ export class KeylayoutToKmnConverter { // add lower part of kmn file: RULES data += this.createData_Rules(data_ukelele) - /* console.log("##################################################################################################################\n", - "kmn output looks like that :################################################################################################\n", - data, - "############################################################################################################################\n")*/ - /*writeFileSync("data/MyResult.kmn", data, { flag: "w" })*/ this.callbacks.fs.writeFileSync("data/MyResult.kmn", new TextEncoder().encode(data)) // not usable here since it takes UInt8array data @@ -354,12 +306,12 @@ export class KeylayoutToKmnConverter { let action_id: string - const isCapsused: boolean = this.checkIfCapsUsed(data_ukelele.ArrayOf_Modifiers) + const isCapsused: boolean = this.checkIfCapsIsUsed(data_ukelele.ArrayOf_Modifiers) // loop keys 0-50 (= all keys we use) for (let j = 0; j <= KeylayoutToKmnConverter.used_Keys_count; j++) { - // loop behaviors ( in ukelele it is possible to define multiple modifier combinations that behave in the same) + // loop behaviors (in ukelele it is possible to define multiple modifier combinations that behave in the same way) for (let i = 0; i < jsonObj.keyboard.keyMapSet[0].keyMap.length; i++) { let RuleObj: rule_object @@ -371,8 +323,6 @@ export class KeylayoutToKmnConverter { if ((jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] !== undefined)) { - // testArray_kmn.push(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output']) - // testArray_kmn_count++ if (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] !== "") { // loop behaviours @@ -384,13 +334,11 @@ export class KeylayoutToKmnConverter { /* modifier_prev_deadkey*/ "", /* prev_deadkey */ "", - /* prev_deadkeys_Ch*/ new TextEncoder().encode(""), /* dk_prev */ 0, /* unique A */ 0, /* modifier_deadkey */ "", /* deadkey */ "", - /* deadkeys_Ch */ new TextEncoder().encode(""), /* dk*/ 0, /* dk for C2*/ 0, /* unique B */ 0, @@ -430,13 +378,11 @@ export class KeylayoutToKmnConverter { /* modifier_prev_deadkey*/ "", /* prev_deadkey */ "", - /* prev_deadkeys_Ch*/ new TextEncoder().encode(""), /* dk_prev */ 0, /* unique A */ 0, /* modifier_deadkey */ "", /* deadkey */ "", - /* deadkeys_Ch */ new TextEncoder().encode(""), /* dk*/ 0, /* dk for C2*/ 0, /* unique B */ 0, @@ -473,25 +419,21 @@ export class KeylayoutToKmnConverter { /* eg: StateNextID = a16 */ const b5_actionId: string[] = jsonObj.keyboard.actions.action[actionIdIndex2]['@_id'] // ....................................................................................................................................... - // Data of Block Nr 4 .................................................................................................................... /* eg: [ '6', '31', '32' ]*/ const b4_code_arr: string[] = this.get_KeyMap_Code_array__From__KeyMap_Action(jsonObj, b5_actionId) /* eg: [['24', 0], ['24', 3]] */ const b4_keyBehaviour_arr: number[][] = this.get_KeyMap_Code_array__From__ActionID_Action(jsonObj, String(action_id)) /* e.g. [['','caps?'], ['Caps']]*/ const b4_modifier2D_array: string[] = this.get_KeyMap_Modifier_array__From__behaviour_arr(data_ukelele.ArrayOf_Modifiers, b4_keyBehaviour_arr) // ....................................................................................................................................... - // Data of Block Nr 6 .................................................................................................................... /* eg: [ 'a9','1','â'] */ const b6_actionId_arr: string[][] = this.get_ActionID_Output_array__From__ActionID_State(jsonObj, b5_value_next) // ....................................................................................................................................... - // Data of Block Nr 1 .................................................................................................................... /* eg: ['49','K_SPACE','a0','0','Â'] */ const b1_keycode_arr: string[][] = this.get_KeyMap_Code_array__From__KeyMap_Action_array2D(jsonObj, b6_actionId_arr) /* eg: ['K_SPACE','a0','0','NCAPS','Â']*/ const b1_KeyMapModiKeyArray: string[][] = this.get_KeyMapModiKeyArray__from__array(jsonObj, b1_keycode_arr, isCapsused) // ....................................................................................................................................... - for (let n1 = 0; n1 < b4_modifier2D_array.length; n1++) { for (let n2 = 0; n2 < b4_modifier2D_array[n1].length; n2++) { for (let n3 = 0; n3 < b4_code_arr.length; n3++) { @@ -502,16 +444,14 @@ export class KeylayoutToKmnConverter { /* modifier_prev_deadkey*/ "", /* prev_deadkey */ "", - /* prev_deadkeys_Ch*/ new TextEncoder().encode(""), /* dk_prev */ 0, - /* unique A */ 0, + /* unique A */ 0, /* modifier_deadkey */ this.create_kmn_modifier(b4_modifier2D_array[n1][n2], isCapsused), /* deadkey */ this.map_UkeleleKC_To_VK(Number(b4_code_arr[n3])), - /* deadkeys_Ch */ new TextEncoder().encode(""), /* dk*/ 0, /* dk for C2*/ dk_counter_C2++, - /* unique B */ 0, + /* unique B */ 0, /* modifier_key*/ b1_KeyMapModiKeyArray[n4][3], /* key */ b1_KeyMapModiKeyArray[n4][0], @@ -550,31 +490,26 @@ export class KeylayoutToKmnConverter { /* eg: StateNextID = a16 */ const b5_actionId: string[] = jsonObj.keyboard.actions.action[actionIdIndex]['@_id'] // ....................................................................................................................................... - // Data of Block Nr 4 .................................................................................................................... /* eg: [ '6', '31', '32' ]*/ const b4_code_arr: string[] = this.get_KeyMap_Code_array__From__KeyMap_Action(jsonObj, b5_actionId) /* eg: [['24', 0], ['24', 3]] */ const b4_keyBehaviour_arr: number[][] = this.get_KeyMap_Code_array__From__ActionID_Action(jsonObj, String(action_id)) /* e.g. [['','caps?'], ['Caps']]*/ const b4_modifier2D_array: string[] = this.get_KeyMap_Modifier_array__From__behaviour_arr(data_ukelele.ArrayOf_Modifiers, b4_keyBehaviour_arr) // ....................................................................................................................................... - // Data of Block Nr 3 .................................................................................................................... /* eg: actioniD = a17 */ const b3_actionId: string = this.get_ActionID_Id__From__ActionID_next(jsonObj, b5_value_state) // ....................................................................................................................................... - // Data of Block Nr 2 .................................................................................................................... /* eg: ['K_8', 'K_M] */ const b2_keyname_arr: string[] = this.get_KecCode_arr__From__ActionId(jsonObj, b3_actionId) /* eg: index=3 */ const b2_keyBehaviour_arr: number[][] = this.get_KeyMap_Code_array__From__ActionID_Action(jsonObj, String(b3_actionId)) /* e.g. [[ '0','1shift? caps?']]*/ const b2_modifier_arr_all: string[] = this.get_KeyMap_Modifier_array__From__behaviour_arr(data_ukelele.ArrayOf_Modifiers, b2_keyBehaviour_arr) // ....................................................................................................................................... - // Data of Block Nr 6 .................................................................................................................... /* eg: [ 'a9','1','â'] */ const b6_actionId_arr: string[][] = this.get_ActionID_Output_array__From__ActionID_State(jsonObj, b5_value_next) // ....................................................................................................................................... - // Data of Block Nr 1 .................................................................................................................... /* eg: ['49','K_SPACE','a0','0','Â'] */ const b1_keycode_arr: string[][] = this.get_KeyMap_Code_array__From__KeyMap_Action_array2D(jsonObj, b6_actionId_arr) /* eg: ['K_SPACE','a0','0','NCAPS','Â']*/ const b1_KeyMapModiKeyArray: string[][] = this.get_KeyMapModiKeyArray__from__array(jsonObj, b1_keycode_arr, isCapsused) @@ -593,16 +528,14 @@ export class KeylayoutToKmnConverter { /* modifier_prev_deadkey*/ this.create_kmn_modifier(b2_modifier_arr_all[n1][n2], isCapsused), /* prev_deadkey */ b2_keyname_arr[n3], - /* prev_deadkeys_Ch*/ new TextEncoder().encode(""), /* dk_prev */ dk_counter_C3_A++, - /* unique A */ 0, + /* unique A */ 0, /* modifier_deadkey */ this.create_kmn_modifier(b4_modifier2D_array[n4][n5], isCapsused), /* deadkey */ this.map_UkeleleKC_To_VK(Number(b4_code_arr[n6])), - /* deadkeys_Ch */ new TextEncoder().encode(""), /* dk*/ dk_counter_C3_B++, /* dk for C2*/ 0, - /* unique B */ 0, + /* unique B */ 0, /* modifier_key*/ b1_KeyMapModiKeyArray[n7][3], /* key */ b1_KeyMapModiKeyArray[n7][0], @@ -639,16 +572,14 @@ export class KeylayoutToKmnConverter { /* modifier_prev_deadkey*/ "", /* prev_deadkey */ "", - /* prev_deadkeys_Ch*/ new TextEncoder().encode(""), /* dk_prev */ 0, - /* unique A */ 0, + /* unique A */ 0, /* modifier_deadkey */ "", /* deadkey */ "", - /* deadkeys_Ch */ new TextEncoder().encode(""), /* dk*/ 0, /* dk for C2*/ 0, - /* unique B */ 0, + /* unique B */ 0, /* modifier_key*/ this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[i][l], isCapsused), /* key */ this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), @@ -664,8 +595,12 @@ export class KeylayoutToKmnConverter { } } - // now check for duplicate C2 and C3 rules and prepare for printing - let unique_dkA_count = 0 + // --------------------------------------------------------------------------------------------------------------------- + // --------------------------------------------------------------------------------------------------------------------- + // now prepare for printing i.e. check for duplicate C2 and C3 rules and mark first occurance of rule + // add nr to uniqueA, uniqueB if it is the first occurence of declaration of dk e.g. [NCAPS RALT K_8] > dk(C12) + // --------------------------------------------------------------------------------------------------------------------- + // --------------------------------------------------------------------------------------------------------------------- let unique_dkB_count = 0 const unique_ruleArrayC2: string[][] = [] @@ -684,9 +619,7 @@ export class KeylayoutToKmnConverter { if ((ObjectArray[i].modifier_deadkey === ObjectArray[j].modifier_deadkey) && (ObjectArray[i].deadkey === ObjectArray[j].deadkey)) { isUnique_dkB = isUnique_dkB && false - }/* { - ObjectArray[i].dk_C2 = unique_dkB_count - }*/ + } } if (isUnique_dkB) { @@ -702,6 +635,7 @@ export class KeylayoutToKmnConverter { } //-----------------------------------prev-dk---------------------------------- + let unique_dkA_count = 0 // first rule is always unique ObjectArray[0].uniqueA = unique_dkA_count @@ -722,7 +656,7 @@ export class KeylayoutToKmnConverter { if (isUnique_dkA) { ObjectArray[i].uniqueA = unique_dkA_count unique_dkA_count++ - // check if second part of C3 rule contains already defined rule + // check if first part of C3 rule contains already defined rule for (let k = 0; k < unique_ruleArrayC2.length; k++) { if ((unique_ruleArrayC2[k][0] === ObjectArray[i].modifier_deadkey) && ((unique_ruleArrayC2[k][1] === ObjectArray[i].deadkey))) ObjectArray[i].uniqueB = Number(unique_ruleArrayC2[k][2]) @@ -740,13 +674,11 @@ export class KeylayoutToKmnConverter { } } } - // console.log("unique_ruleArrayC2 ", unique_ruleArrayC2) for (let i = 0; i < ObjectArray.length; i++) { - for (let j = 0; j < unique_ruleArrayC2.length; j++) { if ((ObjectArray[i].modifier_prev_deadkey === unique_ruleArrayC2[j][0]) && (ObjectArray[i].prev_deadkey === unique_ruleArrayC2[j][1])) { - // write nr into rule obj + // write unique nr into rule obj ObjectArray[i].dk_prev = Number(unique_ruleArrayC2[j][2]) } if ((ObjectArray[i].modifier_deadkey === unique_ruleArrayC2[j][0]) && (ObjectArray[i].deadkey === unique_ruleArrayC2[j][1])) { @@ -756,27 +688,9 @@ export class KeylayoutToKmnConverter { } } + // --------------------------------------------------------------------------------------------------------------------- + // --------------------------------------------------------------------------------------------------------------------- - //--------------------------------------------------------------------- - // print ToDo remove - /* for (let i = 0; i < ObjectArray.length; i++) { - //if ((ObjectArray[i].uniqueA !== 0) || (ObjectArray[i].uniqueB !== 0)) - if ((ObjectArray[i].rule_type === "C3")) - console.log(" ResulT:", "\t", - ObjectArray[i].rule_type, - ObjectArray[i].modifier_prev_deadkey.padEnd(15, " "), - ObjectArray[i].prev_deadkey.padEnd(15, " "), - String(ObjectArray[i].dk_prev).padEnd(15, " "), - String(ObjectArray[i].uniqueA).padEnd(15, " "), - "--", - ObjectArray[i].modifier_deadkey.padEnd(15, " "), - ObjectArray[i].deadkey.padEnd(15, " "), - ObjectArray[i].dk_C2, "--".padEnd(15, " "), - ObjectArray[i].uniqueB, "--".padEnd(15, " "), - new TextDecoder().decode(ObjectArray[i].output), "--".padEnd(15, " "), - - ) - }*/ //--------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------- @@ -827,105 +741,101 @@ export class KeylayoutToKmnConverter { "testArray_kmn_action_uni_filter:", testArray_kmn_action_uni_filter, "testArray_Ukelele_action_uni_filter:", testArray_Ukelele_action_uni_filter) else console.log("OOOOHHHH DIFFERENT AMOUNTS ")*/ - if (this.create_kmn_modifier("command", false) === "command") console.log("testNr 16 OK "); else console.log("testNr 16 NOT OK - ", (this.create_kmn_modifier("command", false))) - if (this.create_kmn_modifier("XXX", false) === "command") console.log("testNr 16 OK "); else console.log("testNr 16 NOT OK - ", (this.create_kmn_modifier("XXX", false))) // test modifiers /* - if (this.create_kmn_modifier("", true) === "NCAPS") console.log("testNr 1 OK "); else console.log("testNr 1 NOT OK - ", (this.create_kmn_modifier("", true))) - if (this.create_kmn_modifier("", false) === "") console.log("testNr 2 OK "); else console.log("testNr 2 NOT OK - ", (this.create_kmn_modifier("", false))) - if (this.create_kmn_modifier("caps", true) === "CAPS") console.log("testNr 5 OK "); else console.log("testNr 5 NOT OK - ", (this.create_kmn_modifier("caps", true))) - if (this.create_kmn_modifier("6caps", true) === "CAPS") console.log("testNr 6 OK "); else console.log("testNr 6 NOT OK - ", (this.create_kmn_modifier("6caps", true))) - if (this.create_kmn_modifier("rightControl", false) === "CTRL") console.log("testNr 13 OK "); else console.log("testNr 13 NOT OK - ", (this.create_kmn_modifier("rightControl", false))) - if (this.create_kmn_modifier("ComMand", false) === "ComMand") console.log("testNr 26 OK "); else console.log("testNr 26 NOT OK - ", (this.create_kmn_modifier("ComMand", false))) - if (this.create_kmn_modifier("rshift?", false) === "") console.log("testNr 19 OK "); else console.log("testNr 19 NOT OK - ", (this.create_kmn_modifier("Shift?", false))) - if (this.create_kmn_modifier("rshift?", true) === "NCAPS") console.log("testNr 20 OK "); else console.log("testNr 20 NOT OK - ", (this.create_kmn_modifier("Shift?", true))) - if (this.create_kmn_modifier("rshift", false) === "SHIFT") console.log("testNr 8 OK "); else console.log("testNr 8 NOT OK - ", (this.create_kmn_modifier("rshift", false))) - if (this.create_kmn_modifier("rightshift", false) === "SHIFT") console.log("testNr 9 OK "); else console.log("testNr 9 NOT OK - ", (this.create_kmn_modifier("rshift", false))) - if (this.create_kmn_modifier("anyOption", false) === "RALT") console.log("testNr 4 OK "); else console.log("testNr 4 NOT OK - ", (this.create_kmn_modifier("anyOption", false))) - if (this.create_kmn_modifier("anyShift", false) === "SHIFT") console.log("testNr 7 OK "); else console.log("testNr 7NOT OK - ", (this.create_kmn_modifier("anyShift", false))) - if (this.create_kmn_modifier("rightShift? rightOption", false) === "RALT") console.log("testNr 17 OK "); else console.log("testNr 17 NOT OK - ", (this.create_kmn_modifier("rightShift? rightOption", false))) - if (this.create_kmn_modifier("option", false) === "RALT") console.log("testNr 15 OK "); else console.log("testNr 15 NOT OK - ", (this.create_kmn_modifier("option", false))) - if (this.create_kmn_modifier("rightOption", false) === "RALT") console.log("testNr 10 OK "); else console.log("testNr 10 NOT OK - ", (this.create_kmn_modifier("rightOption", false))) - if (this.create_kmn_modifier("anyOption", true) === "NCAPS RALT") console.log("testNr 3 OK "); else console.log("testNr 3 NOT OK - ", (this.create_kmn_modifier("anyOption", true))) - if (this.create_kmn_modifier("shift? caps", true) === "CAPS") console.log("testNr 21 OK "); else console.log("testNr 21 NOT OK - ", (this.create_kmn_modifier("shift? caps", true))) - if (this.create_kmn_modifier("caps?", false) === "") console.log("testNr 11 OK "); else console.log("testNr 11 NOT OK - ", (this.create_kmn_modifier("caps?", false))) - if (this.create_kmn_modifier("caps?", false) === "") console.log("testNr 22 OK "); else console.log("testNr 22 NOT OK - ", (this.create_kmn_modifier("caps?", false))) - if (this.create_kmn_modifier("caps?", true) === "NCAPS") console.log("testNr 12 OK "); else console.log("testNr 12 NOT OK - ", (this.create_kmn_modifier("caps?", true))) - if (this.create_kmn_modifier("shift? caps", true) === "CAPS") console.log("testNr 23 OK "); else console.log("testNr 23 NOT OK - ", (this.create_kmn_modifier("shift? caps", true))) - if (this.create_kmn_modifier("shift? caps", false) === "CAPS") console.log("testNr 24 OK "); else console.log("testNr 24 NOT OK - ", (this.create_kmn_modifier("shift? caps", false))) - if (this.create_kmn_modifier("shift caps?", true) === "SHIFT NCAPS") console.log("testNr 28 OK "); else console.log("testNr 28 NOT OK - ", (this.create_kmn_modifier("shift caps?", true))) - if (this.create_kmn_modifier("shift", true) === "NCAPS SHIFT") console.log("testNr 29 OK "); else console.log("testNr 29 NOT OK - ", (this.create_kmn_modifier("shift", true))) - if (this.create_kmn_modifier("shift", true) === "NCAPS SHIFT") console.log("testNr 30 OK "); else console.log("testNr 30 NOT OK - ", (this.create_kmn_modifier("shift", true))) - if (this.create_kmn_modifier("shift caps?", true) === "SHIFT NCAPS") console.log("testNr 27 OK "); else console.log("testNr 27 NOT OK - ", (this.create_kmn_modifier("shift caps?", true))) - if (this.create_kmn_modifier("rightShift anyOption", false) === "SHIFT RALT") console.log("testNr 18 OK "); else console.log("testNr 18 NOT OK - ", (this.create_kmn_modifier("rightShift anyOption", false))) - if (this.create_kmn_modifier("rightControl", true) === "NCAPS CTRL") console.log("testNr 14 OK "); else console.log("testNr 14 NOT OK - ", (this.create_kmn_modifier("rightControl", true))) - if (this.create_kmn_modifier("Caps", true) === "CAPS") console.log("testNr 28 OK "); else console.log("testNr 28 NOT OK - ", (this.create_kmn_modifier("Caps", true))) - if (this.create_kmn_modifier("caps", true) === "CAPS") console.log("testNr 31 OK "); else console.log("testNr 31 NOT OK - ", (this.create_kmn_modifier("Caps", true))) - if (this.create_kmn_modifier("anyOption", true) === "NCAPS RALT") console.log("testNr 32 OK "); else console.log("testNr 32 NOT OK - ", (this.create_kmn_modifier("anyOption", true))) - if (this.create_kmn_modifier("anyOption", false) === "RALT") console.log("testNr 32 OK "); else console.log("testNr 32 NOT OK - ", (this.create_kmn_modifier("anyOption", false))) - if (this.create_kmn_modifier("Caps", true) === "CAPS") console.log("testNr 33 OK "); else console.log("testNr 33 NOT OK - ", (this.create_kmn_modifier("Caps", true))) - if (this.create_kmn_modifier("caps", false) === "CAPS") console.log("testNr 34 OK "); else console.log("testNr 34 NOT OK - ", (this.create_kmn_modifier("Caps", false))) - if (this.create_kmn_modifier("shift rightShift", false) === "SHIFT") console.log("testNr 25 OK "); else console.log("testNr 25 NOT OK - ", (this.create_kmn_modifier("shift rightShift", false))) - - if (this.create_kmn_modifier("shift? caps?", true) === "NCAPS") console.log("testNr 18 OK "); else console.log("testNr 18 NOT OK - ", (this.create_kmn_modifier("shift? caps?", true))) - if (this.create_kmn_modifier("shift? caps?", false) === "") console.log("testNr 18a OK "); else console.log("testNr 18a NOT OK - ", (this.create_kmn_modifier("shift? caps?", false))) - - if (this.create_kmn_modifier("", true) === "NCAPS") console.log("testNr 40 OK "); else console.log("testNr 40 NOT OK - ", (this.create_kmn_modifier("", true))) - if (this.create_kmn_modifier("shift? caps? ", true) === "NCAPS") console.log("testNr 41 OK "); else console.log("testNr 41 NOT OK - ", (this.create_kmn_modifier("shift? caps? ", true))) - if (this.create_kmn_modifier("anyShift caps?", true) === "SHIFT NCAPS") console.log("testNr 42 OK "); else console.log("testNr 42 NOT OK - ", (this.create_kmn_modifier("anyShift caps?", true))) - if (this.create_kmn_modifier("shift? rightShift caps?", true) === "SHIFT NCAPS") console.log("testNr 44 OK "); else console.log("testNr 44 NOT OK - ", (this.create_kmn_modifier("shift? rightShift caps?", true))) - if (this.create_kmn_modifier("shift? leftShift caps?", true) === "SHIFT NCAPS") console.log("testNr 45 OK "); else console.log("testNr 45 NOT OK - ", (this.create_kmn_modifier("shift? leftShift caps?", true))) - if (this.create_kmn_modifier("shift leftShift caps ", true) === "SHIFT CAPS") console.log("testNr 46 OK "); else console.log("testNr 46 NOT OK - ", (this.create_kmn_modifier("shift leftShift caps ", true))) - if (this.create_kmn_modifier("caps", true) === "CAPS") console.log("testNr 47 OK "); else console.log("testNr 47 NOT OK - ", (this.create_kmn_modifier("caps", true))) - if (this.create_kmn_modifier("anyOption", true) === "NCAPS RALT") console.log("testNr 48 OK "); else console.log("testNr 48 NOT OK - ", (this.create_kmn_modifier("anyOption", true))) - if (this.create_kmn_modifier("Caps", true) === "CAPS") console.log("testNr 49 OK "); else console.log("testNr 49 NOT OK - ", (this.create_kmn_modifier("Caps", true))) - if (this.create_kmn_modifier("anyShift caps? anyOption ?", true) === "SHIFT NCAPS RALT") console.log("testNr 50 OK "); else console.log("testNr 50 NOT OK - ", (this.create_kmn_modifier("anyShift caps? anyOption ?", true))) - if (this.create_kmn_modifier("caps anyOption ?", true) === "CAPS RALT") console.log("testNr 51 OK "); else console.log("testNr 51 NOT OK - ", (this.create_kmn_modifier("caps anyOption ?", true))) - if (this.create_kmn_modifier("anyShift? caps? anyOption? anyControl", true) === "NCAPS CTRL") console.log("testNr 52 OK "); else console.log("testNr 52 NOT OK - ", (this.create_kmn_modifier("anyShift? caps? anyOption? anyControl", true))) - if (this.create_kmn_modifier("anyShift? caps? anyOption anyControl", true) === "NCAPS RALT CTRL") console.log("testNr 53 OK "); else console.log("testNr 53 NOT OK - ", (this.create_kmn_modifier("anyShift? caps? anyOption anyControl", true))) - - - if (this.create_kmn_modifier("", false) === "") console.log("testNr 40 OK "); else console.log("testNr 40 NOT OK - ", (this.create_kmn_modifier("", false))) - if (this.create_kmn_modifier("shift? caps? ", false) === "") console.log("testNr 41 OK "); else console.log("testNr 41 NOT OK - ", (this.create_kmn_modifier("shift? caps? ", false))) - if (this.create_kmn_modifier("anyShift caps?", false) === "SHIFT") console.log("testNr 42 OK "); else console.log("testNr 42 NOT OK - ", (this.create_kmn_modifier("anyShift caps?", false))) - if (this.create_kmn_modifier("shift? rightShift caps?", false) === "SHIFT") console.log("testNr 44 OK "); else console.log("testNr 44 NOT OK - ", (this.create_kmn_modifier("shift? rightShift caps?", false))) - if (this.create_kmn_modifier("shift? leftShift caps?", false) === "SHIFT") console.log("testNr 45 OK "); else console.log("testNr 45 NOT OK - ", (this.create_kmn_modifier("shift? leftShift caps?", false))) - if (this.create_kmn_modifier("shift leftShift caps ", false) === "SHIFT CAPS") console.log("testNr 46 OK "); else console.log("testNr 46 NOT OK - ", (this.create_kmn_modifier("shift leftShift caps ", false))) - if (this.create_kmn_modifier("caps", false) === "CAPS") console.log("testNr 47 OK "); else console.log("testNr 47 NOT OK - ", (this.create_kmn_modifier("caps", false))) - if (this.create_kmn_modifier("anyOption", false) === "RALT") console.log("testNr 48 OK "); else console.log("testNr 48 NOT OK - ", (this.create_kmn_modifier("anyOption", false))) - if (this.create_kmn_modifier("Caps", false) === "CAPS") console.log("testNr 49 OK "); else console.log("testNr 49 NOT OK - ", (this.create_kmn_modifier("Caps", false))) - if (this.create_kmn_modifier("anyShift caps? anyOption ?", false) === "SHIFT RALT") console.log("testNr 50 OK "); else console.log("testNr 50 NOT OK - ", (this.create_kmn_modifier("anyShift caps? anyOption ?", false))) - if (this.create_kmn_modifier("caps anyOption ?", false) === "CAPS RALT") console.log("testNr 51 OK "); else console.log("testNr 51 NOT OK - ", (this.create_kmn_modifier("caps anyOption ?", false))) - if (this.create_kmn_modifier("anyShift? caps? anyOption? anyControl", false) === "CTRL") console.log("testNr 52 OK "); else console.log("testNr 52 NOT OK - ", (this.create_kmn_modifier("anyShift? caps? anyOption? anyControl", false))) - if (this.create_kmn_modifier("anyShift? caps? anyOption anyControl", false) === "RALT CTRL") console.log("testNr 53 OK "); else console.log("testNr 53 NOT OK - ", (this.create_kmn_modifier("anyShift? caps? anyOption anyControl", false))) - if (this.create_kmn_modifier("CAPS", false) === "CAPS") console.log("testNr 531 OK "); else console.log("testNr 531 NOT OK - ", (this.create_kmn_modifier("CAPS", true))) - if (this.create_kmn_modifier("shift leftShift caps", false) === "SHIFT CAPS") console.log("testNr 532 OK "); else console.log("testNr 532 NOT OK - ", (this.create_kmn_modifier("shift leftShift caps", false))) - if (this.create_kmn_modifier("shift leftShift caps", true) === "SHIFT CAPS") console.log("testNr 532 OK "); else console.log("testNr 532 NOT OK - ", (this.create_kmn_modifier("shift leftShift caps", true))) - - console.log("------------------ ") - - if (this.isAcceptableKeymanModifier("SHIFT CAPS") === true) console.log("testNr A 1 OK "); else console.log("testNr A 1 NOT OK - ", (this.isAcceptableKeymanModifier("SHIFT CAPS"))) - if (this.isAcceptableKeymanModifier("SHIFT") === true) console.log("testNr A 2 OK "); else console.log("testNr A 2 NOT OK - ", (this.isAcceptableKeymanModifier("SHIFT"))) - if (this.isAcceptableKeymanModifier("shift") === true) console.log("testNr A 12 OK "); else console.log("testNr A 12 NOT OK - ", (this.isAcceptableKeymanModifier("shift"))) - if (this.isAcceptableKeymanModifier("SHIFT ") === true) console.log("testNr A 3 OK "); else console.log("testNr A 3 NOT OK - ", (this.isAcceptableKeymanModifier("SHIFT "))) - if (this.isAcceptableKeymanModifier(" SHIFT ") === true) console.log("testNr A 10 OK "); else console.log("testNr A 10 NOT OK - ", (this.isAcceptableKeymanModifier(" SHIFT "))) - if (this.isAcceptableKeymanModifier(" SHIFT") === true) console.log("testNr A 11 OK "); else console.log("testNr A 11 NOT OK - ", (this.isAcceptableKeymanModifier(" SHIFT"))) - if (this.isAcceptableKeymanModifier("rightshift") === false) console.log("testNr A 4 OK "); else console.log("testNr A 4 NOT OK - ", (this.isAcceptableKeymanModifier("rightshift"))) - if (this.isAcceptableKeymanModifier("rightshift ") === false) console.log("testNr A 5 OK "); else console.log("testNr A 5 NOT OK - ", (this.isAcceptableKeymanModifier("rightshift "))) - if (this.isAcceptableKeymanModifier(" ") === true) console.log("testNr A 6 OK "); else console.log("testNr A 6 NOT OK - ", (this.isAcceptableKeymanModifier(" "))) - if (this.isAcceptableKeymanModifier("") === true) console.log("testNr A 7 OK "); else console.log("testNr A 7 NOT OK - ", (this.isAcceptableKeymanModifier(""))) - if (this.isAcceptableKeymanModifier("rightoption") === false) console.log("testNr A 8 OK "); else console.log("testNr A 8 NOT OK - ", (this.isAcceptableKeymanModifier("rightoption"))) - if (this.isAcceptableKeymanModifier("abc") === false) console.log("testNr A 9 OK "); else console.log("testNr A 9 NOT OK - ", (this.isAcceptableKeymanModifier("abc"))) - if (this.isAcceptableKeymanModifier("ralt") === true) console.log("testNr A 13 OK "); else console.log("testNr A 13 NOT OK - ", (this.isAcceptableKeymanModifier("ralt"))) - */ - - - - + if (this.create_kmn_modifier("", true) === "NCAPS") console.log("testNr 1 OK "); else console.log("testNr 1 NOT OK - ", (this.create_kmn_modifier("", true))) + if (this.create_kmn_modifier("", false) === "") console.log("testNr 2 OK "); else console.log("testNr 2 NOT OK - ", (this.create_kmn_modifier("", false))) + if (this.create_kmn_modifier("caps", true) === "CAPS") console.log("testNr 5 OK "); else console.log("testNr 5 NOT OK - ", (this.create_kmn_modifier("caps", true))) + if (this.create_kmn_modifier("6caps", true) === "CAPS") console.log("testNr 6 OK "); else console.log("testNr 6 NOT OK - ", (this.create_kmn_modifier("6caps", true))) + if (this.create_kmn_modifier("rightControl", false) === "CTRL") console.log("testNr 13 OK "); else console.log("testNr 13 NOT OK - ", (this.create_kmn_modifier("rightControl", false))) + if (this.create_kmn_modifier("ComMand", false) === "ComMand") console.log("testNr 26 OK "); else console.log("testNr 26 NOT OK - ", (this.create_kmn_modifier("ComMand", false))) + if (this.create_kmn_modifier("rshift?", false) === "") console.log("testNr 19 OK "); else console.log("testNr 19 NOT OK - ", (this.create_kmn_modifier("Shift?", false))) + if (this.create_kmn_modifier("rshift?", true) === "NCAPS") console.log("testNr 20 OK "); else console.log("testNr 20 NOT OK - ", (this.create_kmn_modifier("Shift?", true))) + if (this.create_kmn_modifier("rshift", false) === "SHIFT") console.log("testNr 8 OK "); else console.log("testNr 8 NOT OK - ", (this.create_kmn_modifier("rshift", false))) + if (this.create_kmn_modifier("rightshift", false) === "SHIFT") console.log("testNr 9 OK "); else console.log("testNr 9 NOT OK - ", (this.create_kmn_modifier("rshift", false))) + if (this.create_kmn_modifier("anyOption", false) === "RALT") console.log("testNr 4 OK "); else console.log("testNr 4 NOT OK - ", (this.create_kmn_modifier("anyOption", false))) + if (this.create_kmn_modifier("anyShift", false) === "SHIFT") console.log("testNr 7 OK "); else console.log("testNr 7NOT OK - ", (this.create_kmn_modifier("anyShift", false))) + if (this.create_kmn_modifier("rightShift? rightOption", false) === "RALT") console.log("testNr 17 OK "); else console.log("testNr 17 NOT OK - ", (this.create_kmn_modifier("rightShift? rightOption", false))) + if (this.create_kmn_modifier("option", false) === "RALT") console.log("testNr 15 OK "); else console.log("testNr 15 NOT OK - ", (this.create_kmn_modifier("option", false))) + if (this.create_kmn_modifier("rightOption", false) === "RALT") console.log("testNr 10 OK "); else console.log("testNr 10 NOT OK - ", (this.create_kmn_modifier("rightOption", false))) + if (this.create_kmn_modifier("anyOption", true) === "NCAPS RALT") console.log("testNr 3 OK "); else console.log("testNr 3 NOT OK - ", (this.create_kmn_modifier("anyOption", true))) + if (this.create_kmn_modifier("shift? caps", true) === "CAPS") console.log("testNr 21 OK "); else console.log("testNr 21 NOT OK - ", (this.create_kmn_modifier("shift? caps", true))) + if (this.create_kmn_modifier("caps?", false) === "") console.log("testNr 11 OK "); else console.log("testNr 11 NOT OK - ", (this.create_kmn_modifier("caps?", false))) + if (this.create_kmn_modifier("caps?", false) === "") console.log("testNr 22 OK "); else console.log("testNr 22 NOT OK - ", (this.create_kmn_modifier("caps?", false))) + if (this.create_kmn_modifier("caps?", true) === "NCAPS") console.log("testNr 12 OK "); else console.log("testNr 12 NOT OK - ", (this.create_kmn_modifier("caps?", true))) + if (this.create_kmn_modifier("shift? caps", true) === "CAPS") console.log("testNr 23 OK "); else console.log("testNr 23 NOT OK - ", (this.create_kmn_modifier("shift? caps", true))) + if (this.create_kmn_modifier("shift? caps", false) === "CAPS") console.log("testNr 24 OK "); else console.log("testNr 24 NOT OK - ", (this.create_kmn_modifier("shift? caps", false))) + if (this.create_kmn_modifier("shift caps?", true) === "SHIFT NCAPS") console.log("testNr 28 OK "); else console.log("testNr 28 NOT OK - ", (this.create_kmn_modifier("shift caps?", true))) + if (this.create_kmn_modifier("shift", true) === "NCAPS SHIFT") console.log("testNr 29 OK "); else console.log("testNr 29 NOT OK - ", (this.create_kmn_modifier("shift", true))) + if (this.create_kmn_modifier("shift", true) === "NCAPS SHIFT") console.log("testNr 30 OK "); else console.log("testNr 30 NOT OK - ", (this.create_kmn_modifier("shift", true))) + if (this.create_kmn_modifier("shift caps?", true) === "SHIFT NCAPS") console.log("testNr 27 OK "); else console.log("testNr 27 NOT OK - ", (this.create_kmn_modifier("shift caps?", true))) + if (this.create_kmn_modifier("rightShift anyOption", false) === "SHIFT RALT") console.log("testNr 18 OK "); else console.log("testNr 18 NOT OK - ", (this.create_kmn_modifier("rightShift anyOption", false))) + if (this.create_kmn_modifier("rightControl", true) === "NCAPS CTRL") console.log("testNr 14 OK "); else console.log("testNr 14 NOT OK - ", (this.create_kmn_modifier("rightControl", true))) + if (this.create_kmn_modifier("Caps", true) === "CAPS") console.log("testNr 28 OK "); else console.log("testNr 28 NOT OK - ", (this.create_kmn_modifier("Caps", true))) + if (this.create_kmn_modifier("caps", true) === "CAPS") console.log("testNr 31 OK "); else console.log("testNr 31 NOT OK - ", (this.create_kmn_modifier("Caps", true))) + if (this.create_kmn_modifier("anyOption", true) === "NCAPS RALT") console.log("testNr 32 OK "); else console.log("testNr 32 NOT OK - ", (this.create_kmn_modifier("anyOption", true))) + if (this.create_kmn_modifier("anyOption", false) === "RALT") console.log("testNr 32 OK "); else console.log("testNr 32 NOT OK - ", (this.create_kmn_modifier("anyOption", false))) + if (this.create_kmn_modifier("Caps", true) === "CAPS") console.log("testNr 33 OK "); else console.log("testNr 33 NOT OK - ", (this.create_kmn_modifier("Caps", true))) + if (this.create_kmn_modifier("caps", false) === "CAPS") console.log("testNr 34 OK "); else console.log("testNr 34 NOT OK - ", (this.create_kmn_modifier("Caps", false))) + if (this.create_kmn_modifier("shift rightShift", false) === "SHIFT") console.log("testNr 25 OK "); else console.log("testNr 25 NOT OK - ", (this.create_kmn_modifier("shift rightShift", false))) + + if (this.create_kmn_modifier("shift? caps?", true) === "NCAPS") console.log("testNr 18 OK "); else console.log("testNr 18 NOT OK - ", (this.create_kmn_modifier("shift? caps?", true))) + if (this.create_kmn_modifier("shift? caps?", false) === "") console.log("testNr 18a OK "); else console.log("testNr 18a NOT OK - ", (this.create_kmn_modifier("shift? caps?", false))) + + if (this.create_kmn_modifier("", true) === "NCAPS") console.log("testNr 40 OK "); else console.log("testNr 40 NOT OK - ", (this.create_kmn_modifier("", true))) + if (this.create_kmn_modifier("shift? caps? ", true) === "NCAPS") console.log("testNr 41 OK "); else console.log("testNr 41 NOT OK - ", (this.create_kmn_modifier("shift? caps? ", true))) + if (this.create_kmn_modifier("anyShift caps?", true) === "SHIFT NCAPS") console.log("testNr 42 OK "); else console.log("testNr 42 NOT OK - ", (this.create_kmn_modifier("anyShift caps?", true))) + if (this.create_kmn_modifier("shift? rightShift caps?", true) === "SHIFT NCAPS") console.log("testNr 44 OK "); else console.log("testNr 44 NOT OK - ", (this.create_kmn_modifier("shift? rightShift caps?", true))) + if (this.create_kmn_modifier("shift? leftShift caps?", true) === "SHIFT NCAPS") console.log("testNr 45 OK "); else console.log("testNr 45 NOT OK - ", (this.create_kmn_modifier("shift? leftShift caps?", true))) + if (this.create_kmn_modifier("shift leftShift caps ", true) === "SHIFT CAPS") console.log("testNr 46 OK "); else console.log("testNr 46 NOT OK - ", (this.create_kmn_modifier("shift leftShift caps ", true))) + if (this.create_kmn_modifier("caps", true) === "CAPS") console.log("testNr 47 OK "); else console.log("testNr 47 NOT OK - ", (this.create_kmn_modifier("caps", true))) + if (this.create_kmn_modifier("anyOption", true) === "NCAPS RALT") console.log("testNr 48 OK "); else console.log("testNr 48 NOT OK - ", (this.create_kmn_modifier("anyOption", true))) + if (this.create_kmn_modifier("Caps", true) === "CAPS") console.log("testNr 49 OK "); else console.log("testNr 49 NOT OK - ", (this.create_kmn_modifier("Caps", true))) + if (this.create_kmn_modifier("anyShift caps? anyOption ?", true) === "SHIFT NCAPS RALT") console.log("testNr 50 OK "); else console.log("testNr 50 NOT OK - ", (this.create_kmn_modifier("anyShift caps? anyOption ?", true))) + if (this.create_kmn_modifier("caps anyOption ?", true) === "CAPS RALT") console.log("testNr 51 OK "); else console.log("testNr 51 NOT OK - ", (this.create_kmn_modifier("caps anyOption ?", true))) + if (this.create_kmn_modifier("anyShift? caps? anyOption? anyControl", true) === "NCAPS CTRL") console.log("testNr 52 OK "); else console.log("testNr 52 NOT OK - ", (this.create_kmn_modifier("anyShift? caps? anyOption? anyControl", true))) + if (this.create_kmn_modifier("anyShift? caps? anyOption anyControl", true) === "NCAPS RALT CTRL") console.log("testNr 53 OK "); else console.log("testNr 53 NOT OK - ", (this.create_kmn_modifier("anyShift? caps? anyOption anyControl", true))) + if (this.create_kmn_modifier("command", false) === "command") console.log("testNr 16 OK "); else console.log("testNr 16 NOT OK - ", (this.create_kmn_modifier("command", false))) + if (this.create_kmn_modifier("XXX", false) === "command") console.log("testNr 16 OK "); else console.log("testNr 16 NOT OK - ", (this.create_kmn_modifier("XXX", false))) + + + if (this.create_kmn_modifier("", false) === "") console.log("testNr 40 OK "); else console.log("testNr 40 NOT OK - ", (this.create_kmn_modifier("", false))) + if (this.create_kmn_modifier("shift? caps? ", false) === "") console.log("testNr 41 OK "); else console.log("testNr 41 NOT OK - ", (this.create_kmn_modifier("shift? caps? ", false))) + if (this.create_kmn_modifier("anyShift caps?", false) === "SHIFT") console.log("testNr 42 OK "); else console.log("testNr 42 NOT OK - ", (this.create_kmn_modifier("anyShift caps?", false))) + if (this.create_kmn_modifier("shift? rightShift caps?", false) === "SHIFT") console.log("testNr 44 OK "); else console.log("testNr 44 NOT OK - ", (this.create_kmn_modifier("shift? rightShift caps?", false))) + if (this.create_kmn_modifier("shift? leftShift caps?", false) === "SHIFT") console.log("testNr 45 OK "); else console.log("testNr 45 NOT OK - ", (this.create_kmn_modifier("shift? leftShift caps?", false))) + if (this.create_kmn_modifier("shift leftShift caps ", false) === "SHIFT CAPS") console.log("testNr 46 OK "); else console.log("testNr 46 NOT OK - ", (this.create_kmn_modifier("shift leftShift caps ", false))) + if (this.create_kmn_modifier("caps", false) === "CAPS") console.log("testNr 47 OK "); else console.log("testNr 47 NOT OK - ", (this.create_kmn_modifier("caps", false))) + if (this.create_kmn_modifier("anyOption", false) === "RALT") console.log("testNr 48 OK "); else console.log("testNr 48 NOT OK - ", (this.create_kmn_modifier("anyOption", false))) + if (this.create_kmn_modifier("Caps", false) === "CAPS") console.log("testNr 49 OK "); else console.log("testNr 49 NOT OK - ", (this.create_kmn_modifier("Caps", false))) + if (this.create_kmn_modifier("anyShift caps? anyOption ?", false) === "SHIFT RALT") console.log("testNr 50 OK "); else console.log("testNr 50 NOT OK - ", (this.create_kmn_modifier("anyShift caps? anyOption ?", false))) + if (this.create_kmn_modifier("caps anyOption ?", false) === "CAPS RALT") console.log("testNr 51 OK "); else console.log("testNr 51 NOT OK - ", (this.create_kmn_modifier("caps anyOption ?", false))) + if (this.create_kmn_modifier("anyShift? caps? anyOption? anyControl", false) === "CTRL") console.log("testNr 52 OK "); else console.log("testNr 52 NOT OK - ", (this.create_kmn_modifier("anyShift? caps? anyOption? anyControl", false))) + if (this.create_kmn_modifier("anyShift? caps? anyOption anyControl", false) === "RALT CTRL") console.log("testNr 53 OK "); else console.log("testNr 53 NOT OK - ", (this.create_kmn_modifier("anyShift? caps? anyOption anyControl", false))) + if (this.create_kmn_modifier("CAPS", false) === "CAPS") console.log("testNr 531 OK "); else console.log("testNr 531 NOT OK - ", (this.create_kmn_modifier("CAPS", true))) + if (this.create_kmn_modifier("shift leftShift caps", false) === "SHIFT CAPS") console.log("testNr 532 OK "); else console.log("testNr 532 NOT OK - ", (this.create_kmn_modifier("shift leftShift caps", false))) + if (this.create_kmn_modifier("shift leftShift caps", true) === "SHIFT CAPS") console.log("testNr 532 OK "); else console.log("testNr 532 NOT OK - ", (this.create_kmn_modifier("shift leftShift caps", true))) + + console.log("------------------ ") + + if (this.isAcceptableKeymanModifier("SHIFT CAPS") === true) console.log("testNr A 1 OK "); else console.log("testNr A 1 NOT OK - ", (this.isAcceptableKeymanModifier("SHIFT CAPS"))) + if (this.isAcceptableKeymanModifier("SHIFT") === true) console.log("testNr A 2 OK "); else console.log("testNr A 2 NOT OK - ", (this.isAcceptableKeymanModifier("SHIFT"))) + if (this.isAcceptableKeymanModifier("shift") === true) console.log("testNr A 12 OK "); else console.log("testNr A 12 NOT OK - ", (this.isAcceptableKeymanModifier("shift"))) + if (this.isAcceptableKeymanModifier("SHIFT ") === true) console.log("testNr A 3 OK "); else console.log("testNr A 3 NOT OK - ", (this.isAcceptableKeymanModifier("SHIFT "))) + if (this.isAcceptableKeymanModifier(" SHIFT ") === true) console.log("testNr A 10 OK "); else console.log("testNr A 10 NOT OK - ", (this.isAcceptableKeymanModifier(" SHIFT "))) + if (this.isAcceptableKeymanModifier(" SHIFT") === true) console.log("testNr A 11 OK "); else console.log("testNr A 11 NOT OK - ", (this.isAcceptableKeymanModifier(" SHIFT"))) + if (this.isAcceptableKeymanModifier("rightshift") === false) console.log("testNr A 4 OK "); else console.log("testNr A 4 NOT OK - ", (this.isAcceptableKeymanModifier("rightshift"))) + if (this.isAcceptableKeymanModifier("rightshift ") === false) console.log("testNr A 5 OK "); else console.log("testNr A 5 NOT OK - ", (this.isAcceptableKeymanModifier("rightshift "))) + if (this.isAcceptableKeymanModifier(" ") === true) console.log("testNr A 6 OK "); else console.log("testNr A 6 NOT OK - ", (this.isAcceptableKeymanModifier(" "))) + if (this.isAcceptableKeymanModifier("") === true) console.log("testNr A 7 OK "); else console.log("testNr A 7 NOT OK - ", (this.isAcceptableKeymanModifier(""))) + if (this.isAcceptableKeymanModifier("rightoption") === false) console.log("testNr A 8 OK "); else console.log("testNr A 8 NOT OK - ", (this.isAcceptableKeymanModifier("rightoption"))) + if (this.isAcceptableKeymanModifier("abc") === false) console.log("testNr A 9 OK "); else console.log("testNr A 9 NOT OK - ", (this.isAcceptableKeymanModifier("abc"))) + if (this.isAcceptableKeymanModifier("ralt") === true) console.log("testNr A 13 OK "); else console.log("testNr A 13 NOT OK - ", (this.isAcceptableKeymanModifier("ralt"))) + */ //--------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------- @@ -950,16 +860,6 @@ export class KeylayoutToKmnConverter { } return returnarray } - public get_KeyMap_Code__From__KeyMap_Action(data: any, search: string): number { - for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { - for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { - if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { - return data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'] - } - } - } - return -1 - } public get_KeyMap_Code_array__From__KeyMap_Action(data: any, search: string[]): string[] { const returnarray: string[] = [] for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { @@ -971,35 +871,6 @@ export class KeylayoutToKmnConverter { } return returnarray } - public get_KeyMap_Behaviour_array__From__KeyMap_Action(data: any, search: string[]): string[][] { - const returnarray2D: string[][] = [] - for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { - for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { - const returnarray: string[] = [] - if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { - returnarray.push(this.map_UkeleleKC_To_VK(Number(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']))) - returnarray.push(data.keyboard.keyMapSet[0].keyMap[i]['@_index']) - returnarray.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action']) - } - if (returnarray.length > 0) - returnarray2D.push(returnarray) - } - } - return returnarray2D - } - public get_KeyMap_Code_array__From__KeyMap_Action_array(data: any, search: string[][]): string[] { - const returnarray: string[] = [] - for (let i = 0; i < search.length; i++) { - for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap.length; j++) { - for (let k = 0; k < data.keyboard.keyMapSet[0].keyMap[j].key.length; k++) { - if (data.keyboard.keyMapSet[0].keyMap[j].key[k]['@_action'] === search[i][0]) { - returnarray.push(data.keyboard.keyMapSet[0].keyMap[j].key[k]['@_code']) - } - } - } - } - return returnarray - } public get_KeyMap_Code_array__From__KeyMap_Action_array2D(data: any, search: string[][]): string[][] { const returnarray2D: string[][] = [] for (let k = 0; k < search.length; k++) { @@ -1050,20 +921,6 @@ export class KeylayoutToKmnConverter { } return "" } - public get_ActionID_array__From__ActionID_NoneNext(data: any, search: string): string[] { - const returnarray: string[] = [] - if (search !== "none") { - for (let i = 0; i < data.keyboard.actions.action.length; i++) { - for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { - if (data.keyboard.actions.action[i].when[j]['@_next'] === search) { - if (data.keyboard.actions.action[i].when[j]['@_state'] === "none") - returnarray.push(data.keyboard.actions.action[i]['@_id']) - } - } - } - } - return returnarray - } public get_ActionID_Output_array__From__ActionID_State(data: any, search: string) { const returnarray2D: string[][] = [] for (let i = 0; i < data.keyboard.actions.action.length; i++) { @@ -1093,9 +950,36 @@ export class KeylayoutToKmnConverter { } return OutputValue } + public get_KeyMapModiKeyArray__from__array(data: any, search: string[][], isCAPSused: boolean): string[][] { + const returnarray: string[][] = [] - // in a0 - // out: Array:string[][] a0, K_A, behavi, shiftCombo, out, + for (let i = 0; i < search.length; i++) { + const behaviour: number = Number(search[i][3]) + + for (let j = 0; j < data.keyboard.modifierMap.keyMapSelect[behaviour].modifier.length; j++) { + const returnarray1D: string[] = [] + returnarray1D.push(search[i][1]) /* KeyName*/ + returnarray1D.push(search[i][2]) /* action*/ + returnarray1D.push(search[i][3]) /* behaviour*/ + returnarray1D.push(this.create_kmn_modifier(data.keyboard.modifierMap.keyMapSelect[behaviour].modifier[j]['@_keys'], isCAPSused)) /* modifier */ + returnarray1D.push(search[i][4]) /* char*/ + if (returnarray1D.length > 0) + returnarray.push(returnarray1D) + } + } + // remove duplicates + const [unique_returnarray] = returnarray.reduce((acc, curr) => { + const [uniq, set] = acc; + if (!set.has(curr.join(','))) { + set.add(curr.join(',')); + uniq.push(curr); + } + return acc; + }, + [[], new Set()], + ); + return unique_returnarray + } public get_Datat_array2D__From__ActionID_stateOutput(data: any, modi: any, search: string, outchar: string, isCapsused: boolean): string[][] { const returnarray2D: string[][] = [] @@ -1137,10 +1021,6 @@ export class KeylayoutToKmnConverter { return unique_returnarray } - - - - public get_Terminator_Output__From__Terminator_State(data: any, search: string): string { for (let i = 0; i < data.keyboard.terminators.when.length; i++) { if (data.keyboard.terminators.when[i]['@_state'] === search) { @@ -1149,26 +1029,103 @@ export class KeylayoutToKmnConverter { } return "" } - public get_keyModifierArray__from__Action(data: any, search: string): string[][] { - // search is a9 + public get_KeyMap_Code_array__From__ActionID_Action(data: any, search: string): number[][] { + const mapIndexArray_max: number[][] = [] + for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { + for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { + const mapIndexArrayperKey: number[] = [] + + if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { + mapIndexArrayperKey.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']) + mapIndexArrayperKey.push(i) + } + if (mapIndexArrayperKey.length > 0) + mapIndexArray_max.push(mapIndexArrayperKey) + } + } + return mapIndexArray_max + } + public get_KeyMap_Modifier_array__From__behaviour_arr(data: any, search: number[][]): string[] { + const mapIndexArray_max: string[] = [] + for (let i = 0; i < search.length; i++) { + mapIndexArray_max.push(data[search[i][1]]) + } + return mapIndexArray_max + } + + /* public get_KeyMap_Code__From__KeyMap_Action(data: any, search: string): number { + for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { + for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { + if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { + return data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'] + } + } + } + return -1 + }*/ + /*public get_KeyMap_Behaviour_array__From__KeyMap_Action(data: any, search: string[]): string[][] { const returnarray2D: string[][] = [] for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { const returnarray: string[] = [] if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { - returnarray.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action']) returnarray.push(this.map_UkeleleKC_To_VK(Number(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']))) returnarray.push(data.keyboard.keyMapSet[0].keyMap[i]['@_index']) + returnarray.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action']) } if (returnarray.length > 0) returnarray2D.push(returnarray) } } return returnarray2D - } + }*/ + /*public get_KeyMap_Code_array__From__KeyMap_Action_array(data: any, search: string[][]): string[] { + const returnarray: string[] = [] + for (let i = 0; i < search.length; i++) { + for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap.length; j++) { + for (let k = 0; k < data.keyboard.keyMapSet[0].keyMap[j].key.length; k++) { + if (data.keyboard.keyMapSet[0].keyMap[j].key[k]['@_action'] === search[i][0]) { + returnarray.push(data.keyboard.keyMapSet[0].keyMap[j].key[k]['@_code']) + } + } + } + } + return returnarray + }*/ + /*public get_ActionID_array__From__ActionID_NoneNext(data: any, search: string): string[] { + const returnarray: string[] = [] + if (search !== "none") { + for (let i = 0; i < data.keyboard.actions.action.length; i++) { + for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { + if (data.keyboard.actions.action[i].when[j]['@_next'] === search) { + if (data.keyboard.actions.action[i].when[j]['@_state'] === "none") + returnarray.push(data.keyboard.actions.action[i]['@_id']) + } + } + } + } + return returnarray + }*/ + /* public get_keyModifierArray__from__Action(data: any, search: string): string[][] { + // search is a9 + const returnarray2D: string[][] = [] + for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { + for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { + const returnarray: string[] = [] + if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { + returnarray.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action']) + returnarray.push(this.map_UkeleleKC_To_VK(Number(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']))) + returnarray.push(data.keyboard.keyMapSet[0].keyMap[i]['@_index']) + } + if (returnarray.length > 0) + returnarray2D.push(returnarray) + } + } + return returnarray2D + }*/ // ToDo needed?? - public get_ActionID_Output__From__ActionID_IdState(data: any, search_id: string, search_state: string): Uint8Array { + /*public get_ActionID_Output__From__ActionID_IdState(data: any, search_id: string, search_state: string): Uint8Array { for (let i = 0; i < data.keyboard.actions.action.length; i++) { for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { if ((data.keyboard.actions.action[i]['@_id'] === search_id) && @@ -1178,9 +1135,9 @@ export class KeylayoutToKmnConverter { } } return new TextEncoder().encode("") - } + }*/ // ToDo needed?? - public get_ActionID_Key__From__ActionID_IdState(data: any, search_id: string, search_state: string): Uint8Array { + /*public get_ActionID_Key__From__ActionID_IdState(data: any, search_id: string, search_state: string): Uint8Array { for (let i = 0; i < data.keyboard.actions.action.length; i++) { for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { if ((data.keyboard.actions.action[i]['@_id'] === search_id) && @@ -1190,9 +1147,9 @@ export class KeylayoutToKmnConverter { } } return new TextEncoder().encode("") - } + }*/ // ToDo needed?? - public get_KeyMap_Keymaparray__From__KeyMap_Code_array(data: any, search: string[]): string[][] { + /*public get_KeyMap_Keymaparray__From__KeyMap_Code_array(data: any, search: string[]): string[][] { const returnarray: string[][] = [] for (let k = 0; k < search.length; k++) { const returnarray1D: string[] = [] @@ -1207,8 +1164,8 @@ export class KeylayoutToKmnConverter { returnarray.push(returnarray1D) } return returnarray - } - public get_KeyMap_Keymaparray__From__KeyMap_Action_array(data: any, search: string): string[][] { + }*/ + /*public get_KeyMap_Keymaparray__From__KeyMap_Action_array(data: any, search: string): string[][] { const returnarray: string[][] = [] for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { const returnarray1D: string[] = [] @@ -1234,42 +1191,10 @@ export class KeylayoutToKmnConverter { [[], new Set()], ); return uniqueElements - } - - + }*/ - public get_KeyMapModiKeyArray__from__array(data: any, search: string[][], isCAPSused: boolean): string[][] { - const returnarray: string[][] = [] - - for (let i = 0; i < search.length; i++) { - const behaviour: number = Number(search[i][3]) - - for (let j = 0; j < data.keyboard.modifierMap.keyMapSelect[behaviour].modifier.length; j++) { - const returnarray1D: string[] = [] - returnarray1D.push(search[i][1]) /* KeyName*/ - returnarray1D.push(search[i][2]) /* action*/ - returnarray1D.push(search[i][3]) /* behaviour*/ - returnarray1D.push(this.create_kmn_modifier(data.keyboard.modifierMap.keyMapSelect[behaviour].modifier[j]['@_keys'], isCAPSused)) /* modifier */ - returnarray1D.push(search[i][4]) /* char*/ - if (returnarray1D.length > 0) - returnarray.push(returnarray1D) - } - } - // remove duplicates - const [unique_returnarray] = returnarray.reduce((acc, curr) => { - const [uniq, set] = acc; - if (!set.has(curr.join(','))) { - set.add(curr.join(',')); - uniq.push(curr); - } - return acc; - }, - [[], new Set()], - ); - return unique_returnarray - } // ToDo needed?? - public get_KeyMap_Keymaparray__From__KeyMap_Action(data: any, search: string): string[] { + /*public get_KeyMap_Keymaparray__From__KeyMap_Action(data: any, search: string): string[] { const returnarray: string[] = [] for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { @@ -1279,9 +1204,9 @@ export class KeylayoutToKmnConverter { } } return returnarray - } + }*/ // ToDo needed?? - public get_ActionID_Id_array__From__ActionID_next(data: any, search: string): string[][] { + /*public get_ActionID_Id_array__From__ActionID_next(data: any, search: string): string[][] { const returnarray2D: string[][] = [] if (search !== "none") { for (let i = 0; i < data.keyboard.actions.action.length; i++) { @@ -1296,9 +1221,9 @@ export class KeylayoutToKmnConverter { } } return returnarray2D - } + }*/ // ToDo needed?? get all entries for state= and a given action id - public get_Action2ID_State_arrayState_Array__From__ActionID_Id(data: any, search: string): string[] { + /*public get_Action2ID_State_arrayState_Array__From__ActionID_Id(data: any, search: string): string[] { const returnarray: string[] = [] for (let i = 0; i < data.keyboard.actions.action.length; i++) { if (data.keyboard.actions.action[i]['@_id'] === search) { @@ -1310,27 +1235,27 @@ export class KeylayoutToKmnConverter { } } return returnarray - } + }*/ // ToDo needed?? get all entries for state= and a given action id - public get_ActionID_Id_arrayNext_Array__From__ActionID_StateNext(data: any, search: string): string[] { - const returnarray: string[] = [] - for (let i = 0; i < data.keyboard.actions.action.length; i++) { - for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { - if ((data.keyboard.actions.action[i].when[j]['@_next'] === search) && (data.keyboard.actions.action[i].when[j]['@_state'] !== "none")) { - returnarray.push(data.keyboard.actions.action[i]['@_id']) - } - } - } - return returnarray - } - public map_UkeleleKC_To_VK_array(search: string[]): string[] { + /* public get_ActionID_Id_arrayNext_Array__From__ActionID_StateNext(data: any, search: string): string[] { + const returnarray: string[] = [] + for (let i = 0; i < data.keyboard.actions.action.length; i++) { + for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { + if ((data.keyboard.actions.action[i].when[j]['@_next'] === search) && (data.keyboard.actions.action[i].when[j]['@_state'] !== "none")) { + returnarray.push(data.keyboard.actions.action[i]['@_id']) + } + } + } + return returnarray + }*/ + /*public map_UkeleleKC_To_VK_array(search: string[]): string[] { const returnarray: string[] = [] for (let i = 0; i < search.length; i++) { returnarray.push(this.map_UkeleleKC_To_VK(Number(search[i]))) } return returnarray - } - public get_ActionID_Id__From__ActionID_Next(data: any, search: string) { + }*/ + /*public get_ActionID_Id__From__ActionID_Next(data: any, search: string) { for (let i = 0; i < data.keyboard.actions.action.length; i++) { for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { if ((data.keyboard.actions.action[i].when[j]['@_next'] === search)) { @@ -1339,31 +1264,8 @@ export class KeylayoutToKmnConverter { } } return "" - } - public get_KeyMap_Code_array__From__ActionID_Action(data: any, search: string): number[][] { - const mapIndexArray_max: number[][] = [] - for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { - for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { - const mapIndexArrayperKey: number[] = [] - - if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { - mapIndexArrayperKey.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']) - mapIndexArrayperKey.push(i) - } - if (mapIndexArrayperKey.length > 0) - mapIndexArray_max.push(mapIndexArrayperKey) - } - } - return mapIndexArray_max - } - public get_KeyMap_Modifier_array__From__behaviour_arr(data: any, search: number[][]): string[] { - const mapIndexArray_max: string[] = [] - for (let i = 0; i < search.length; i++) { - mapIndexArray_max.push(data[search[i][1]]) - } - return mapIndexArray_max - } - public get_Modifier_Text__From__Modifier_Index(data: any, search: string): string[] { + }*/ + /*public get_Modifier_Text__From__Modifier_Index(data: any, search: string): string[] { const mapIndexArray_max: string[] = [] const mapIndexArrayperKey: string[] = [] for (let i = 0; i < data[search].length; i++) { @@ -1373,8 +1275,8 @@ export class KeylayoutToKmnConverter { mapIndexArray_max.push(data[search][i]) } return mapIndexArray_max - } - public get_KeyMap_Code__From__ActionID_Action(data: any, search: string): number { + }*/ + /*public get_KeyMap_Code__From__ActionID_Action(data: any, search: string): number { const mapIndexArray_max: number[][] = [] for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { @@ -1389,8 +1291,8 @@ export class KeylayoutToKmnConverter { } } return mapIndexArray_max[0][1] - } - public get_KeyMap_Code__From__ActionID_Action2(data: any, search: string): number { + }*/ + /*public get_KeyMap_Code__From__ActionID_Action2(data: any, search: string): number { const mapIndexArray_max: number[][] = [] for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { @@ -1405,15 +1307,15 @@ export class KeylayoutToKmnConverter { } } return mapIndexArray_max[0][1] - } - public get_ActionID_Next__From__ActionID_Id(data: any, search: string): string { + }*/ + /*public get_ActionID_Next__From__ActionID_Id(data: any, search: string): string { for (let i = 0; i < data.keyboard.actions.action.length; i++) { if ((data.keyboard.actions.action[i]['@_id'] === search)) return data.keyboard.actions.action[i].when[1]['@_next'] } return "" - } - public get_KeyMap_Index__From__KeyMap_Action(data: any, search: string): number { + }*/ + /*public get_KeyMap_Index__From__KeyMap_Action(data: any, search: string): number { for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { @@ -1422,8 +1324,8 @@ export class KeylayoutToKmnConverter { } } return -1 - } - public get_KeyMap_IndexCodeAction_array__From__KeyMap_Action(data: any, search: string): string[][] { + }*/ + /*public get_KeyMap_IndexCodeAction_array__From__KeyMap_Action(data: any, search: string): string[][] { const returnarray2D: string[][] = [] for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { @@ -1439,8 +1341,8 @@ export class KeylayoutToKmnConverter { } } return returnarray2D - } - public get_KeyMap_IndexCodeAction_array__From__KeyMap_Action_Array(data: any, search: string[][]): string[][] { + }*/ + /*public get_KeyMap_IndexCodeAction_array__From__KeyMap_Action_Array(data: any, search: string[][]): string[][] { console.log("search uuuu ", search) const modifierArray: number[] = [] const modifierArray2D: number[][] = [] @@ -1453,8 +1355,8 @@ export class KeylayoutToKmnConverter { returnarray2D.push(this.get_KeyMap_Modifier_array__From__behaviour_arr(data, modifierArray2D)) return returnarray2D - } - public get_KeyMap_ModiIndex_array__From__KeyMap_Action(data: any, search_code: string, search_action: string): string[][] { + }*/ + /*public get_KeyMap_ModiIndex_array__From__KeyMap_Action(data: any, search_code: string, search_action: string): string[][] { const returnarray2D: string[][] = [] for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { @@ -1471,8 +1373,8 @@ export class KeylayoutToKmnConverter { } } return returnarray2D - } - public get_ActionID_Output__From__ActionID_State(data: any, search: string, nextval: string): string { + }*/ + /*public get_ActionID_Output__From__ActionID_State(data: any, search: string, nextval: string): string { for (let i = 0; i < data.keyboard.actions.action.length; i++) { for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { if ((data.keyboard.actions.action[i].when[j]['@_state'] === search) && (data.keyboard.actions.action[i]['@_id'] === nextval)) { @@ -1481,28 +1383,32 @@ export class KeylayoutToKmnConverter { } } return "" - } - public get_KeyMap_Modifier_aray__From__KeyMap_Index(data: any, search: number): string[] { - return data.ArrayOf_Modifiers[search] - } - public get_data_From__KeyMap_Modifier_Index(data: any, search: number): string[] { + }*/ + /* public get_KeyMap_Modifier_aray__From__KeyMap_Index(data: any, search: number): string[] { + return data.ArrayOf_Modifiers[search] + }*/ + + + /*public get_data_From__KeyMap_Modifier_Index(data: any, search: number): string[] { return data[search] - } - public get_dataArray2D__From__KeyMap_Modifier_Index(data: any, search: string[]): string[][] { + }*/ + + /*public get_dataArray2D__From__KeyMap_Modifier_Index(data: any, search: string[]): string[][] { const returnarray: string[][] = [] for (let i = 0; i < search.length; i++) { returnarray.push(data[search[i]]) } return returnarray - } + }*/ /** * @brief member function to return the unicode value of a character * @param character the value that will converted * @return headecimal value of a character */ - public getHexFromChar(character: string): string { + + /* public getHexFromChar(character: string): string { return character.charCodeAt(0).toString(16).slice(-4).toUpperCase().padStart(4, "0") - } + }*/ /** * @brief member function to create a string of modifiers in kmn-style from the modifierMap section of .keylayout-file * @param keylayout_modifier the modifier value used in the .keylayout-file @@ -1569,7 +1475,7 @@ export class KeylayoutToKmnConverter { return unique_modifier_array.flat().toString().replace(/,/g, " ") } - public checkIfCapsUsed(keylayout_modifier: string[][]): boolean { + public checkIfCapsIsUsed(keylayout_modifier: string[][]): boolean { return keylayout_modifier.flat().flat().includes("caps") } @@ -1635,7 +1541,7 @@ export class KeylayoutToKmnConverter { // C3 | 4 | 5 | 6 | CAPS K_X > dk(B1) dk(B1) + SHIFT K_Y > dk(C1) dk(C1) + NCAPS K_Z > 'Z' public findAmbiguousRules(rule: rule_object[], index: number): string { - + // ToDo is the return statement/filter func correct??? // 1-1 @@ -1688,33 +1594,33 @@ export class KeylayoutToKmnConverter { + ambiguous_C2_vs_C2[0].dk_C2 + ") here: [") - /*// 3-3 + // 3-3 // find ambiguous C0 or C1 rules vs. C0 or C1 ....................................................................................................... // e.g. CAPS K_A > 'A' <-> CAPS K_A > 'B' ........................................................................................................ // ................................................................................................................................................... - const ambiguous_C2_vs_C2_A: rule_object[] = rule.filter((curr, idx) => { - if (((rule[index].rule_type === "C2")) - && ((curr.rule_type === "C2")) - && curr.modifier_key === rule[index].modifier_key - && curr.key === rule[index].key - && curr.output !== rule[index].output - && curr.uniqueB !== 0 - && (idx < index) - ) - return curr; - else return "" - }); - console.log("ambiguous_C2_vs_C2_A " ) - this.writeDalaset(ambiguous_C2_vs_C2_A) - - if (ambiguous_C2_vs_C2_A.length > 0) - return ("ambiguous 3-3 rule: earlier: [" - + ambiguous_C2_vs_C2_A[0].modifier_key + " " - + ambiguous_C2_vs_C2_A[0].key + "] > \'" - + new TextDecoder().decode(ambiguous_C2_vs_C2_A[0].output) - + ") here: [")*/ + /* const ambiguous_C2_vs_C2_A: rule_object[] = rule.filter((curr, idx) => { + if (((rule[index].rule_type === "C2")) + && ((curr.rule_type === "C2")) + && curr.modifier_key === rule[index].modifier_key + && curr.key === rule[index].key + && curr.output !== rule[index].output + && curr.uniqueB !== 0 + && (idx < index) + ) + return curr; + else return "" + }); + console.log("ambiguous_C2_vs_C2_A " ) + this.writeDalaset(ambiguous_C2_vs_C2_A) + if (ambiguous_C2_vs_C2_A.length > 0) + return ("ambiguous 3-3 rule: earlier: [" + + ambiguous_C2_vs_C2_A[0].modifier_key + " " + + ambiguous_C2_vs_C2_A[0].key + "] > \'" + + new TextDecoder().decode(ambiguous_C2_vs_C2_A[0].output) + + ") here: [") + */ // 4-4 @@ -1833,8 +1739,9 @@ export class KeylayoutToKmnConverter { return "" } + public findDuplicateRules_new(rule: rule_object[], index: number): string { - + // ToDo is the return statement/filter func correct??? // 1-1 @@ -1874,14 +1781,14 @@ export class KeylayoutToKmnConverter { && curr.prev_deadkey === "" && curr.modifier_deadkey === rule[index].modifier_deadkey && curr.deadkey === rule[index].deadkey - && curr.dk_C2 === rule[index].dk_C2 + && curr.dk_C2 === rule[index].dk_C2 && rule[index].uniqueB !== 0 && (idx < index) ) return curr; else return "" }); - if( (ambiguous_C2_vs_C2.length > 0)) + if ((ambiguous_C2_vs_C2.length > 0)) return ("duplicate 2-2 ccrule: earlier: [" + ambiguous_C2_vs_C2[0].modifier_deadkey + " " + String(ambiguous_C2_vs_C2[0].uniqueB) @@ -1927,7 +1834,7 @@ export class KeylayoutToKmnConverter { && ((curr.rule_type === "C3")) && curr.modifier_prev_deadkey === rule[index].modifier_prev_deadkey && curr.prev_deadkey === rule[index].prev_deadkey - && curr.dk_prev + && curr.dk_prev === rule[index].dk_prev && (idx < index) ) @@ -1975,7 +1882,7 @@ export class KeylayoutToKmnConverter { && curr.prev_deadkey === "" && rule[index].modifier_deadkey === curr.modifier_key && rule[index].deadkey === curr.key - && (rule[index].uniqueB === curr.uniqueB) + && (rule[index].uniqueB === curr.uniqueB) ) return curr; else return "" @@ -2132,83 +2039,7 @@ export class KeylayoutToKmnConverter { let data: string = "" let keymarker: string = "" - // prepare data for C0 and C1 - select only lines that contain C0 or C1 and create an output character - /* const data_C0_C1: rule_object[] = data_ukelele.ArrayOf_Rules.filter((curr) => { - if ((curr.output !== new TextEncoder().encode("") || curr.output !== undefined) - && (curr.rule_type === "C0") || (curr.rule_type === "C1")) { - return curr; - } - else return "" - }); - const unique_C0_C1_Rules: rule_object[] = data_C0_C1.reduce((unique, o) => { - if (!unique.some((obj: { output: Uint8Array; rule_type: string; modifier_key: string; key: string }) => - new TextDecoder().decode(obj.output) === new TextDecoder().decode(o.output) - && obj.key === o.key - && obj.rule_type === o.rule_type - && obj.modifier_key === o.modifier_key - ) - ) { - unique.push(o); - } - return unique; - }, []);*/ - - // prepare data for C2 - select only lines that contain C2 and create an output character - /* const data_C2: rule_object[] = data_ukelele.ArrayOf_Rules.filter((curr) => { - if ((curr.output !== new TextEncoder().encode("") || curr.output !== undefined) - && (curr.rule_type === "C2")) { - return curr; - } - else return "" - }); - const unique_C2_Rules: rule_object[] = data_C2.reduce((unique, o) => { - if (!unique.some((obj: { output: Uint8Array; rule_type: string; modifier_key: string; modifier_deadkey: string; deadkey: string; key: string }) => - - new TextDecoder().decode(obj.output) === new TextDecoder().decode(o.output) - && new TextDecoder().decode(obj.output) !== "" - - && obj.rule_type === o.rule_type - - && obj.modifier_key === o.modifier_key - && obj.key === o.key - - && obj.modifier_deadkey === o.modifier_deadkey - && obj.deadkey === o.deadkey - ) - ) { - unique.push(o); - } - return unique; - }, []);*/ - - // prepare data for C3 - select only lines that contain C3 and create an output character - /* const data_C3: rule_object[] = data_ukelele.ArrayOf_Rules.filter((curr) => { - if ((curr.output !== new TextEncoder().encode("") || curr.output !== undefined) - && (curr.rule_type === "C3")) { - return curr; - } - else return "" - }); - const unique_C3_Rules: rule_object[] = data_C3.reduce((unique, o) => { - if (!unique.some((obj: { output: Uint8Array; rule_type: string; modifier_key: string; modifier_deadkey: string; prev_deadkey: string; modifier_prev_deadkey: string; deadkey: string; key: string }) => - new TextDecoder().decode(obj.output) === new TextDecoder().decode(o.output) - - && obj.rule_type === o.rule_type - && obj.modifier_key === o.modifier_key - && obj.key === o.key - - && obj.modifier_deadkey === o.modifier_deadkey - && obj.deadkey === o.deadkey - - && obj.modifier_prev_deadkey === o.modifier_prev_deadkey - && obj.prev_deadkey === o.prev_deadkey) - ) { - unique.push(o); - } - return unique; - }, []);*/ - - const data_CAll: rule_object[] = data_ukelele.ArrayOf_Rules.filter((curr) => { + const data_CAll: rule_object[] = data_ukelele.ArrayOf_Rules.filter((curr) => { if ((curr.output !== new TextEncoder().encode("") || curr.output !== undefined) && (curr.rule_type === "C0") || (curr.rule_type === "C1") || (curr.rule_type === "C2") || (curr.rule_type === "C3")) { return curr; @@ -2233,23 +2064,13 @@ export class KeylayoutToKmnConverter { } return unique; }, []); + console.log("xx data_ukelele.ArrayOf_Rules", data_ukelele.ArrayOf_Rules.length) //console.log("xx data_ukelele.ArrayOf_Rules", this.writeDalaset(data_ukelele.ArrayOf_Rules)) console.log("xx unique_CAll_Rules", unique_CAll_Rules.length) //console.log("xx unique_CAll_Rules", this.writeDalaset(unique_CAll_Rules)) - /* console.log("xx unique_C0_C1_Rules", unique_C0_C1_Rules.length) - //console.log("xx unique_C0_C1_Rules", this.writeDalaset(unique_C0_C1_Rules)) - - console.log("xx unique_C2_Rules", unique_C2_Rules.length) - //console.log("xx unique_C2_Rules", this.writeDalaset(unique_C2_Rules)) - console.log("xx data_C2", data_C2.length) - - /*console.log("xx data_C3", data_C3.length) - console.log("xx unique_C3_Rules", unique_C3_Rules.length)*/ - //console.log("xx unique_C3_Rules", this.writeDalaset(unique_C3_Rules))*/ - //................................................ C0 C1 ................................................................ //................................................ C0 C1 ................................................................ //................................................ C0 C1 ................................................................ @@ -2275,8 +2096,7 @@ export class KeylayoutToKmnConverter { let warningtext: string = "c C0 WARNING: " warningtext = warningtext + this.findDuplicateRules(unique_CAll_Rules, i, "C01") //warningtext = warningtext + this.findDuplicateRules(unique_CAll_Rules, i) - // warningtext = warningtext + this.findAmbiguousRules_2(unique_CAll_Rules, i, "C01") // todo we do not need C01 ?? - warningtext = warningtext + this.findAmbiguousRules(unique_CAll_Rules, i) // todo we do not need C01 ?? + warningtext = warningtext + this.findAmbiguousRules(unique_CAll_Rules, i) warningtext = warningtext + this.findUnAvailableRule(unique_CAll_Rules, i) // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -2327,11 +2147,8 @@ export class KeylayoutToKmnConverter { let warningtext: string = "c C2 WARNING: " warningtext = warningtext + this.findDuplicateRules(unique_CAll_Rules, k, "C2") - //warningtext = warningtext + this.findDuplicateRules(unique_CAll_Rules, k) warningtext = warningtext + this.findAmbiguousRules(unique_CAll_Rules, k) - //warningtext = warningtext + this.findAmbiguousRules_2(unique_CAll_Rules, k, "C2") warningtext = warningtext + this.findUnAvailableRule(unique_CAll_Rules, k) - console.log(" warningtext", warningtext) // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~ draft print ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -2358,10 +2175,6 @@ export class KeylayoutToKmnConverter { } //data += "---\n" data += "dk(C" + String(unique_CAll_Rules[k].dk_C2) + ") + [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'\n" - - - - } // warning avail else { @@ -2390,20 +2203,13 @@ export class KeylayoutToKmnConverter { console.log("NOW print C§ ",) - /* for (let k = 0; k < unique_CAll_Rules.length; k++) { - if (unique_CAll_Rules[k].rule_type === "C3") { - this.writeDalasetSingle(unique_CAll_Rules[k]) - } - }*/ for (let k = 0; k < unique_CAll_Rules.length; k++) { - if (unique_CAll_Rules[k].rule_type === "C3") { let warningtext: string = "c C3 WARNING: " warningtext = warningtext + this.findDuplicateRules(unique_CAll_Rules, k, "C3") // OK - //warningtext = warningtext + this.findDuplicateRules(unique_CAll_Rules, k) // OK warningtext = warningtext + this.findAmbiguousRules(unique_CAll_Rules, k) // OK warningtext = warningtext + this.findUnAvailableRule(unique_CAll_Rules, k) // OK // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -2449,17 +2255,64 @@ export class KeylayoutToKmnConverter { } } + data += '\n' + return data + } + public createData_Stores(data_ukelele: convert_object): string { + let data: string = "" - console.log("NOW START C§ 5",) + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~ draft print ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + if (KeylayoutToKmnConverter.print_draft) { + data += "c\n" + data += "c Keyman keyboard generated by kmn-convert\n" + data += "c\n" + data += "\n" + data += '\########## OK #################################################################\n' + data += "store(&VERSION) \'10.0\'\n" + data += "store(&TARGETS) \'any\'\n" + data += "store(&KEYBOARDVERSION) \'1.0\'\n" + data += "store(©RIGHT) '© 2024 SIL International\'\n" + // TODO what else ?? - data += '\n' + data += '\########## OK #################################################################\n' + data += "\n" + data += "begin Unicode > use(main)\n\n" + data += "group(main) using keys\n\n" + + data += '\########## OK #################################################################\n' + data += "Tipp: if K_? is replaced by undefined-> no enry in kmn_Key_Name=> add K_? there and it will be shown here\n" + data += "Tipp: keys that are marked with sction do not aoear in ukelele_Array_output->do not appear in kmn\n" + data += "\n" + } + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~ draft print end ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + else { + data += "c\n" + data += "c Keyman keyboard generated by kmn-convert\n" + data += "c\n" + data += "\n" + + data += "store(&VERSION) \'10.0\'\n" + data += "store(&TARGETS) \'any\'\n" + data += "store(&KEYBOARDVERSION) \'1.0\'\n" + data += "store(©RIGHT) '© 2024 SIL International\'\n" + // TODO what else ?? + + data += "\n" + data += "begin Unicode > use(main)\n\n" + data += "group(main) using keys\n\n" + + data += "\n" + } return data } - - /// console log all entries C3 + /// console log all entries C3 TODO remove public writeDalaset(dataRules: rule_object[]) { for (let i = 0; i < dataRules.length; i++) { @@ -2488,6 +2341,7 @@ export class KeylayoutToKmnConverter { } } + // TODO remove public writeDalasetSingle(dataRules: rule_object) { console.log("dataRules ", @@ -2513,75 +2367,19 @@ export class KeylayoutToKmnConverter { "| °°") } - - public createData_Stores(data_ukelele: convert_object): string { - let data: string = "" - - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // ~~~~ draft print ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - if (KeylayoutToKmnConverter.print_draft) { - data += "c\n" - data += "c Keyman keyboard generated by kmn-convert\n" - data += "c\n" - data += "\n" - - data += '\########## OK #################################################################\n' - data += "store(&VERSION) \'10.0\'\n" - data += "store(&TARGETS) \'any\'\n" - data += "store(&KEYBOARDVERSION) \'1.0\'\n" - data += "store(©RIGHT) '© 2024 SIL International\'\n" - // TODO what else ?? - - data += '\########## OK #################################################################\n' - data += "\n" - data += "begin Unicode > use(main)\n\n" - data += "group(main) using keys\n\n" - - data += '\########## OK #################################################################\n' - data += "Tipp: if K_? is replaced by undefined-> no enry in kmn_Key_Name=> add K_? there and it will be shown here\n" - data += "Tipp: keys that are marked with sction do not aoear in ukelele_Array_output->do not appear in kmn\n" - data += "\n" - } - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // ~~~~ draft print end ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - else { - data += "c\n" - data += "c Keyman keyboard generated by kmn-convert\n" - data += "c\n" - data += "\n" - - data += "store(&VERSION) \'10.0\'\n" - data += "store(&TARGETS) \'any\'\n" - data += "store(&KEYBOARDVERSION) \'1.0\'\n" - data += "store(©RIGHT) '© 2024 SIL International\'\n" - // TODO what else ?? - - data += "\n" - data += "begin Unicode > use(main)\n\n" - data += "group(main) using keys\n\n" - - data += "\n" - } - return data - } } class Rules { - constructor( public rule_type: string, /* C0, C1, C2, C3, or C4 */ public modifier_prev_deadkey: string, /* first key used by C3 rules*/ public prev_deadkey: string, - public prev_deadkeys_Ch: Uint8Array, public dk_prev: number, public uniqueA: number, public modifier_deadkey: string, /* second key used by C2,C3 rules*/ public deadkey: string, - public deadkeys_Ch: Uint8Array, public dk: number, //todo remove one public dk_C2: number, public uniqueB: number, From c4d2400525c37282215024e41fdceeaf9b539238 Mon Sep 17 00:00:00 2001 From: Sabine Date: Wed, 12 Feb 2025 15:32:29 +0100 Subject: [PATCH 048/251] feat(developer): kmc-convert ambiguous/duplicate rules across C0-C3 --- .../keylayout-to-kmn-converter.ts | 1390 ++++++++++++----- 1 file changed, 979 insertions(+), 411 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 15fabac033b..0ca71382d75 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -1536,413 +1536,668 @@ export class KeylayoutToKmnConverter { return "" } - // C0C1 | | | 1 | CAPS K_A > 'A' - // C2 | | 2 | 3 | CAPS K_A > dk(A1) dk(A1) + SHIFT K_B > 'B' - // C3 | 4 | 5 | 6 | CAPS K_X > dk(B1) dk(B1) + SHIFT K_Y > dk(C1) dk(C1) + NCAPS K_Z > 'Z' - public findAmbiguousRules(rule: rule_object[], index: number): string { - // ToDo is the return statement/filter func correct??? + public findAmbiguousRules(rule: rule_object[], index: number): string[] { + const returnarray: string[] = Array(3).fill(""); - // 1-1 - // find ambiguous C0 or C1 rules vs. C0 or C1 ....................................................................................................... - // e.g. CAPS K_A > 'A' <-> CAPS K_A > 'B' ........................................................................................................ - // ................................................................................................................................................... - const ambiguous_C0C1_vs_C0C1: rule_object[] = rule.filter((curr, idx) => { - if (((rule[index].rule_type === "C0") || (rule[index].rule_type === "C1")) - && ((curr.rule_type === "C0") || (curr.rule_type === "C1")) + if (rule[index].rule_type === "C0" || rule[index].rule_type === "C1") { + + // filter 1 Text............................................................... + // OK A 1-1 amb dup ............................................................................................................................................ + const ambiguous_C0C1_vs_C0C1 = rule.filter((curr, idx) => + (curr.rule_type === "C0" || curr.rule_type === "C1") && curr.modifier_prev_deadkey === "" && curr.prev_deadkey === "" && curr.modifier_deadkey === "" && curr.deadkey === "" && curr.modifier_key === rule[index].modifier_key && curr.key === rule[index].key - && new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output) - && (idx < index) - ) - return curr; - else return "" - }); - if (ambiguous_C0C1_vs_C0C1.length > 0) - return ("ambiguous 1-1 rule: earlier: [" - + ambiguous_C0C1_vs_C0C1[0].modifier_key + " " - + ambiguous_C0C1_vs_C0C1[0].key + "] > \'" - + new TextDecoder().decode(ambiguous_C0C1_vs_C0C1[0].output) - + "\' here: [") - - // 2-2 - // find ambiguous C2 rules vs. C2 .................................................................................................................... - // e.g. CAPS K_A > dk(A1) <-> CAPS K_A > dk(A2) ................................................................................................... - // ................................................................................................................................................... - const ambiguous_C2_vs_C2: rule_object[] = rule.filter((curr, idx) => { - if (((rule[index].rule_type === "C2")) - && ((curr.rule_type === "C2")) - && curr.modifier_prev_deadkey === "" - && curr.prev_deadkey === "" - && curr.modifier_deadkey === rule[index].modifier_deadkey - && curr.deadkey === rule[index].deadkey - && curr.dk_C2 !== rule[index].dk_C2 - && (idx < index) - ) - return curr; - else return "" - }); - if (ambiguous_C2_vs_C2.length > 0) - return ("ambiguous 2-2 rule: earlier: [" - + ambiguous_C2_vs_C2[0].modifier_deadkey + " " - + ambiguous_C2_vs_C2[0].deadkey + "] > dk( C'" - + ambiguous_C2_vs_C2[0].dk_C2 - + ") here: [") - - // 3-3 - // find ambiguous C0 or C1 rules vs. C0 or C1 ....................................................................................................... - // e.g. CAPS K_A > 'A' <-> CAPS K_A > 'B' ........................................................................................................ - // ................................................................................................................................................... - /* const ambiguous_C2_vs_C2_A: rule_object[] = rule.filter((curr, idx) => { - if (((rule[index].rule_type === "C2")) - && ((curr.rule_type === "C2")) - && curr.modifier_key === rule[index].modifier_key - && curr.key === rule[index].key - && curr.output !== rule[index].output - && curr.uniqueB !== 0 - && (idx < index) - ) - return curr; - else return "" - }); - console.log("ambiguous_C2_vs_C2_A " ) - this.writeDalaset(ambiguous_C2_vs_C2_A) - - if (ambiguous_C2_vs_C2_A.length > 0) - return ("ambiguous 3-3 rule: earlier: [" - + ambiguous_C2_vs_C2_A[0].modifier_key + " " - + ambiguous_C2_vs_C2_A[0].key + "] > \'" - + new TextDecoder().decode(ambiguous_C2_vs_C2_A[0].output) - + ") here: [") - - */ - - - // 4-4 - // find ambiguous C3 rules vs. C3 .................................................................................................................... - // e.g. CAPS K_A > dk(B1) <-> CAPS K_A > dk(B2) ................................................................................................... - // ................................................................................................................................................... - const ambiguous_C3_vs_C3: rule_object[] = rule.filter((curr, idx) => { - if (((rule[index].rule_type === "C3")) - && ((curr.rule_type === "C3")) - && curr.modifier_prev_deadkey === rule[index].modifier_prev_deadkey - && curr.prev_deadkey === rule[index].prev_deadkey - && curr.dk_prev !== rule[index].dk_prev - && (idx < index) - ) - return curr; - else return "" - }); - if (ambiguous_C2_vs_C2.length > 0) - return ("ambiguous 4-4 rule: earlier: [" - + ambiguous_C3_vs_C3[0].modifier_prev_deadkey + " " - + ambiguous_C3_vs_C3[0].prev_deadkey + "] > dk( C'" - + ambiguous_C3_vs_C3[0].dk_prev - + ") here: [") - - - //6-6 - // find ambiguous C3 rules vs. C3 ................................................................................................................... - // e.g. dk(C1) + NCAPS K_Z > 'Z'' <-> dk(C1) + NCAPS K_Z > 'X' ................................................................................. - // ................................................................................................................................................... - const ambiguous_C3_vs_C3_B: rule_object[] = rule.filter((curr, idx) => { - if (((rule[index].rule_type === "C3")) - && ((curr.rule_type === "C3")) - && curr.modifier_prev_deadkey === rule[index].modifier_prev_deadkey - && curr.prev_deadkey === rule[index].prev_deadkey - && curr.dk_prev !== rule[index].dk_prev - && (idx < index) - ) - return curr; - else return "" - }); - if (ambiguous_C3_vs_C3_B.length > 0) - return ("ambiguous 6-6 rule: earlier: [" - + ambiguous_C3_vs_C3_B[0].modifier_key + " " - + ambiguous_C3_vs_C3_B[0].key + "] > \'" - + new TextDecoder().decode(ambiguous_C3_vs_C3_B[0].output) - + ") here: [") - - // 1-2 - // find ambiguous C0 or C1 rules vs. C2 .............................................................................................................. - // e.g. CAPS K_A > 'A'' <-> CAPS K_A > dk(A2) ..................................................................................................... - // ................................................................................................................................................... - const ambiguous_C1C1_vs_C2: rule_object[] = rule.filter((curr) => { - if ((rule[index].rule_type === "C2") - && ((curr.rule_type === "C0") || (curr.rule_type === "C1")) - && curr.modifier_prev_deadkey === "" - && curr.prev_deadkey === "" - && rule[index].modifier_deadkey === curr.modifier_key - && rule[index].deadkey === curr.key - && (rule[index].uniqueB !== 0) - ) - return curr; - else return "" - }); - if (ambiguous_C1C1_vs_C2.length > 0) - return ("ambiguous 1-2 rule: earlier: [" - + ambiguous_C1C1_vs_C2[0].modifier_key + " " - + ambiguous_C1C1_vs_C2[0].key + "] > \'" - + new TextDecoder().decode(ambiguous_C1C1_vs_C2[0].output) - + "\' here: [") - - // 1-4 - // find ambiguous C0 or C1 rules vs. C3 .............................................................................................................. - // e.g. CAPS K_A > 'A'' <-> CAPS K_A > dk(B2) ..................................................................................................... - // ................................................................................................................................................... - const ambiguous_C0C1_vs_C3: rule_object[] = rule.filter((curr, idx) => { - if ((rule[index].rule_type === "C3") - && ((curr.rule_type === "C0") || (curr.rule_type === "C1")) - && rule[index].modifier_prev_deadkey === curr.modifier_key - && rule[index].prev_deadkey === curr.key - && (rule[index].uniqueA !== 0) - && (idx < index) - ) - return curr; - else return "" - }); - if (ambiguous_C0C1_vs_C3.length > 0) - return ("ambiguous 1-4 rule: earlier: [" - + ambiguous_C0C1_vs_C3[0].modifier_key + " " - + ambiguous_C0C1_vs_C3[0].key + "] > \'" - + new TextDecoder().decode(ambiguous_C0C1_vs_C3[0].output) - + "\' here: [") - - // 3-6 - // find ambiguous C2 rules vs. C3 .................................................................................................................... - // e.g. CAPS K_A > 'A' <-> CAPS K_A > 'B' ......................................................................................................... - // ................................................................................................................................................... - const ambiguous_C2_vs_C3: rule_object[] = rule.filter((curr, idx) => { - if ((rule[index].rule_type === "C3") - && ((curr.rule_type === "C2")) - && rule[index].modifier_prev_deadkey === curr.modifier_deadkey - && rule[index].prev_deadkey === curr.deadkey - && curr.dk_prev !== rule[index].dk_C2 - && (rule[index].uniqueA !== 0) - && (rule[index].uniqueB !== 0) - && (idx < index) - ) - return curr; - else return "" - }); - if (ambiguous_C2_vs_C3.length > 0) - return ("ambiguous 1-6 rule: earlier: [" - + ambiguous_C2_vs_C3[0].modifier_key + " " - + ambiguous_C2_vs_C3[0].key + "] > \'" - + new TextDecoder().decode(ambiguous_C2_vs_C3[0].output) - + "\' here: [") - - return "" - } - - public findDuplicateRules_new(rule: rule_object[], index: number): string { + && new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output) // amb + && idx < index + ); - // ToDo is the return statement/filter func correct??? - - // 1-1 - // find ambiguous C0 or C1 rules vs. C0 or C1 ....................................................................................................... - // e.g. CAPS K_A > 'A' <-> CAPS K_A > 'B' ........................................................................................................ - // ................................................................................................................................................... - const ambiguous_C0C1_vs_C0C1: rule_object[] = rule.filter((curr, idx) => { - if (((rule[index].rule_type === "C0") || (rule[index].rule_type === "C1")) - && ((curr.rule_type === "C0") || (curr.rule_type === "C1")) + const duplicate_C0C1_vs_C0C1 = rule.filter((curr, idx) => + (curr.rule_type === "C0" || curr.rule_type === "C1") && curr.modifier_prev_deadkey === "" && curr.prev_deadkey === "" && curr.modifier_deadkey === "" && curr.deadkey === "" && curr.modifier_key === rule[index].modifier_key && curr.key === rule[index].key - && new TextDecoder().decode(curr.output) === new TextDecoder().decode(rule[index].output) - && (idx < index) - ) - return curr; - else return "" - }); - if (ambiguous_C0C1_vs_C0C1.length > 0) - return ("duplicate 1-1 rule: earlier: [" - + ambiguous_C0C1_vs_C0C1[0].modifier_key + " " - + ambiguous_C0C1_vs_C0C1[0].key + "] > \'" - + new TextDecoder().decode(ambiguous_C0C1_vs_C0C1[0].output) - + "\' here: [") - - // 2-2 - // find ambiguous C2 rules vs. C2 .................................................................................................................... - // e.g. CAPS K_A > dk(A1) <-> CAPS K_A > dk(A2) ................................................................................................... - // ................................................................................................................................................... - const ambiguous_C2_vs_C2: rule_object[] = rule.filter((curr, idx) => { - if (((rule[index].rule_type === "C2")) - && ((curr.rule_type === "C2")) - && curr.modifier_prev_deadkey === "" - && curr.prev_deadkey === "" + && new TextDecoder().decode(curr.output) === new TextDecoder().decode(rule[index].output) // dup + && idx < index + ); + + if (ambiguous_C0C1_vs_C0C1.length > 0) { + //Firstsentence + returnarray[0] = returnarray[0] + ( + "ambiguous 1-1 rule: earlier: [" + + ambiguous_C0C1_vs_C0C1[0].modifier_key + " " + + ambiguous_C0C1_vs_C0C1[0].key + "] > \'" + + new TextDecoder().decode(ambiguous_C0C1_vs_C0C1[0].output) + + "\' here: [") + } + + if (duplicate_C0C1_vs_C0C1.length > 0) { + //Firstsentence + returnarray[0] = returnarray[0] + ("duplicate 1-1 rule: earlier: [" + + duplicate_C0C1_vs_C0C1[0].modifier_key + " " + + duplicate_C0C1_vs_C0C1[0].key + "] > \'" + + new TextDecoder().decode(duplicate_C0C1_vs_C0C1[0].output) + + "\' here: [") + } + return returnarray + } + + if (rule[index].rule_type === "C2") { + + // 2-2 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(C1) + const ambiguous_C2_vs_C2 = rule.filter((curr, idx) => + curr.rule_type === "C2" + && curr.modifier_deadkey === rule[index].modifier_deadkey + && curr.deadkey === rule[index].deadkey + && (String(curr.dk_C2) !== String(rule[index].dk_C2) || String(curr.dk) !== String(rule[index].dk)) + && idx < index + ); + + //2-2 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(C11) + const duplicate_C2_vs_C2 = rule.filter((curr, idx) => + curr.rule_type === "C2" && curr.modifier_deadkey === rule[index].modifier_deadkey && curr.deadkey === rule[index].deadkey - && curr.dk_C2 === rule[index].dk_C2 + && String(curr.dk_C2) === String(rule[index].dk_C2) // dup + && String(curr.dk) === String(rule[index].dk) // dup + && idx < index + ); + + //3-3 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'B' + const ambiguous_C2_vs_C2_B2 = rule.filter((curr, idx) => + (curr.rule_type === "C2") + && curr.modifier_key === rule[index].modifier_key + && curr.key === rule[index].key + && String(curr.dk_C2) === String(rule[index].dk_C2) + && (new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output)) // amb && rule[index].uniqueB !== 0 - && (idx < index) - ) - return curr; - else return "" - }); - if ((ambiguous_C2_vs_C2.length > 0)) - return ("duplicate 2-2 ccrule: earlier: [" - + ambiguous_C2_vs_C2[0].modifier_deadkey + " " - + String(ambiguous_C2_vs_C2[0].uniqueB) - + ambiguous_C2_vs_C2[0].deadkey + "] > dk(C" - + ambiguous_C2_vs_C2[0].dk_C2 - + "xx) here: [") - - /*// 3-3 - // find ambiguous C0 or C1 rules vs. C0 or C1 ....................................................................................................... - // e.g. CAPS K_A > 'A' <-> CAPS K_A > 'B' ........................................................................................................ - // ................................................................................................................................................... - const ambiguous_C2_vs_C2_A: rule_object[] = rule.filter((curr, idx) => { - if (((rule[index].rule_type === "C2")) - && ((curr.rule_type === "C2")) + && idx < index + ); + + //3-3 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'Ã' + const duplicate_C2_vs_C2_B2 = rule.filter((curr, idx) => + (curr.rule_type === "C2") && curr.modifier_key === rule[index].modifier_key && curr.key === rule[index].key - && curr.output !== rule[index].output - && curr.uniqueB !== 0 - && (idx < index) - ) - return curr; - else return "" - }); - console.log("ambiguous_C2_vs_C2_A " ) - this.writeDalaset(ambiguous_C2_vs_C2_A) + && String(curr.dk_C2) === String(rule[index].dk_C2) // dup + && new TextDecoder().decode(curr.output) === new TextDecoder().decode(rule[index].output) // dup + && rule[index].uniqueB === 0 + && idx < index + ); + + + //1-2 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > 'Ñ' + const ambibguous_C2_vs_C1 = rule.filter((curr, idx) => + ((curr.rule_type === "C0") || (curr.rule_type === "C1")) + + && curr.modifier_key === rule[index].modifier_deadkey + && curr.key === rule[index].deadkey + //&& rule[index].uniqueB === 0 // without this there will be no warning for first + //&& (idx < index) // without this there will be no warning for first + ); + + if (duplicate_C2_vs_C2.length > 0) { + //Firstsentence + returnarray[0] = returnarray[0] + ("FIRSTTEXT " + "duplicate 2-2 rule: earlier: [" + duplicate_C2_vs_C2[0].modifier_deadkey + " " + duplicate_C2_vs_C2[0].deadkey + "] > dk(C" + duplicate_C2_vs_C2[0].dk_C2 + "here: )\'") + } + if (ambiguous_C2_vs_C2.length > 0) { + //Firstsentence + returnarray[0] = returnarray[0] + ("FIRSTTEXT " + "ambiguous 2-2 rule: earlier: [" + ambiguous_C2_vs_C2[0].modifier_deadkey + " " + ambiguous_C2_vs_C2[0].deadkey + "] > dk(C" + ambiguous_C2_vs_C2[0].dk_C2 + "here: )\'") + } + if (ambibguous_C2_vs_C1.length > 0) { + //Firstsentence + returnarray[0] = returnarray[0] + ("FIRSTTEXT " + "ambiguous 1-2 rule: earlier: [" + ambibguous_C2_vs_C1[0].modifier_key + " " + ambibguous_C2_vs_C1[0].key + "] > \'" + new TextDecoder().decode(ambibguous_C2_vs_C1[0].output) + "\' here: ") + } + + if (duplicate_C2_vs_C2_B2.length > 0) { + //Secondsentence + returnarray[1] = returnarray[1] + ("SECONDTEXT " + "duplicate y 3-3 rule: earlier: dk(C" + duplicate_C2_vs_C2_B2[0].dk_C2 + ") + [" + duplicate_C2_vs_C2_B2[0].modifier_key + " " + duplicate_C2_vs_C2_B2[0].key + "] > \'" + new TextDecoder().decode(duplicate_C2_vs_C2_B2[0].output) + "\' here: ") + } + if (ambiguous_C2_vs_C2_B2.length > 0) { + //Secondsentence + returnarray[1] = returnarray[1] + ("SECONDTEXT " + "duplicate y 3-3 rule: earlier: dk(C" + ambiguous_C2_vs_C2_B2[0].dk_C2 + ") + [" + ambiguous_C2_vs_C2_B2[0].modifier_key + " " + ambiguous_C2_vs_C2_B2[0].key + "] > \'" + new TextDecoder().decode(ambiguous_C2_vs_C2_B2[0].output) + "\' here: ") + } + return returnarray + } + + if (rule[index].rule_type === "C3") { + returnarray[0] = "" + returnarray[1] = "" + returnarray[2] = "" + // A 4-1 amb dup ........................................................... + + + //1-4 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > 'Ñ' + const ambibguous_C3_vs_C1 = rule.filter((curr, idx) => + ((curr.rule_type === "C0") || (curr.rule_type === "C1")) + + && curr.modifier_key === rule[index].modifier_prev_deadkey + && curr.key === rule[index].prev_deadkey + //&& rule[index].uniqueA === 0 // without this there will be no warning + //&& (idx < index) + ); + + // A 4-2 amb dup ........................................................... + + //2-4 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(C1) + const ambibguous_C3_vs_C2_B = rule.filter((curr, idx) => + ((curr.rule_type === "C2")) - if (ambiguous_C2_vs_C2_A.length > 0) - return ("ambiguous 3-3 rule: earlier: [" - + ambiguous_C2_vs_C2_A[0].modifier_key + " " - + ambiguous_C2_vs_C2_A[0].key + "] > \'" - + new TextDecoder().decode(ambiguous_C2_vs_C2_A[0].output) - + ") here: [")*/ + && curr.modifier_deadkey === rule[index].modifier_prev_deadkey + && curr.deadkey === rule[index].prev_deadkey + && String(curr.dk_C2) === String(rule[index].dk_prev) // dup + // && rule[index].uniqueA === 0 // without this there will be no warning + //&& (idx < index) + ); + // A 6-3 amb dup ........................................................... + //6-3 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'B' + const ambiguous_C3_vs_C2_B2 = rule.filter((curr, idx) => + (curr.rule_type === "C2") + && curr.modifier_key === rule[index].modifier_key + && curr.key === rule[index].key + && String(curr.dk_prev) === String(rule[index].dk_prev) // amb + && (new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output)) // amb + // && rule[index].uniqueB !== 0 + // && idx < index + ); + + //6-3 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'Ã' + const duplicate_C3_vs_C2_B2 = rule.filter((curr, idx) => + (curr.rule_type === "C2") + && curr.modifier_key === rule[index].modifier_key + && curr.key === rule[index].key + && String(curr.dk_prev) === String(rule[index].dk_prev) // dup + && new TextDecoder().decode(curr.output) === new TextDecoder().decode(rule[index].output) // dup + // && rule[index].uniqueB === 0 + // && idx < index + ); + // A 4-4 amb dup ........................................................... - // 4-4 - // find ambiguous C3 rules vs. C3 .................................................................................................................... - // e.g. CAPS K_A > dk(B1) <-> CAPS K_A > dk(B2) ................................................................................................... - // ................................................................................................................................................... - const ambiguous_C3_vs_C3: rule_object[] = rule.filter((curr, idx) => { - if (((rule[index].rule_type === "C3")) - && ((curr.rule_type === "C3")) + // 4-4 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > 'dk(C1)' + const ambiguous_C3_vs_C3 = rule.filter((curr, idx) => + curr.rule_type === "C3" && curr.modifier_prev_deadkey === rule[index].modifier_prev_deadkey && curr.prev_deadkey === rule[index].prev_deadkey - && curr.dk_prev - === rule[index].dk_prev - && (idx < index) - ) - return curr; - else return "" - }); - if (ambiguous_C2_vs_C2.length > 0) - return ("duplicate 4-4 rule: earlier: [" - + ambiguous_C3_vs_C3[0].modifier_prev_deadkey + " " - + ambiguous_C3_vs_C3[0].prev_deadkey + "] > dk( C'" - + ambiguous_C3_vs_C3[0].dk_prev - + ") here: [") - - - //6-6 - // find ambiguous C3 rules vs. C3 ................................................................................................................... - // e.g. dk(C1) + NCAPS K_Z > 'Z'' <-> dk(C1) + NCAPS K_Z > 'X' ................................................................................. - // ................................................................................................................................................... - const ambiguous_C3_vs_C3_B: rule_object[] = rule.filter((curr, idx) => { - if (((rule[index].rule_type === "C3")) - && ((curr.rule_type === "C3")) + && (String(curr.dk_prev) !== String(rule[index].dk_prev)) + && rule[index].uniqueA !== 0 + && idx < index + ); + + // 4-4 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(C11) + const duplicate_C3_vs_C3 = rule.filter((curr, idx) => + curr.rule_type === "C3" && curr.modifier_prev_deadkey === rule[index].modifier_prev_deadkey && curr.prev_deadkey === rule[index].prev_deadkey - && curr.dk_prev === rule[index].dk_prev - && (idx < index) - ) - return curr; - else return "" - }); - if (ambiguous_C3_vs_C3_B.length > 0) - return ("duplicate 6-6 rule: earlier: [" - + ambiguous_C3_vs_C3_B[0].modifier_key + " " - + ambiguous_C3_vs_C3_B[0].key + "] > \'" - + new TextDecoder().decode(ambiguous_C3_vs_C3_B[0].output) - + ") here: [") - - // 1-2 - // find ambiguous C0 or C1 rules vs. C2 .............................................................................................................. - // e.g. CAPS K_A > 'A'' <-> CAPS K_A > dk(A2) ..................................................................................................... - // ................................................................................................................................................... - const ambiguous_C1C1_vs_C2: rule_object[] = rule.filter((curr) => { - if ((rule[index].rule_type === "C2") - && ((curr.rule_type === "C0") || (curr.rule_type === "C1")) - && curr.modifier_prev_deadkey === "" - && curr.prev_deadkey === "" - && rule[index].modifier_deadkey === curr.modifier_key - && rule[index].deadkey === curr.key - && (rule[index].uniqueB === curr.uniqueB) - ) - return curr; - else return "" - }); - if (ambiguous_C1C1_vs_C2.length > 0) - return ("duplicate 1-2 rule: earlier: [" - + ambiguous_C1C1_vs_C2[0].modifier_key + " " - + ambiguous_C1C1_vs_C2[0].key + "] > \'" - + new TextDecoder().decode(ambiguous_C1C1_vs_C2[0].output) - + "\' here: [") - - // 1-4 - // find ambiguous C0 or C1 rules vs. C3 .............................................................................................................. - // e.g. CAPS K_A > 'A'' <-> CAPS K_A > dk(B2) ..................................................................................................... - // ................................................................................................................................................... - const ambiguous_C0C1_vs_C3: rule_object[] = rule.filter((curr, idx) => { - if ((rule[index].rule_type === "C3") - && ((curr.rule_type === "C0") || (curr.rule_type === "C1")) - && rule[index].modifier_prev_deadkey === curr.modifier_key - && rule[index].prev_deadkey === curr.key - && (rule[index].uniqueA === curr.uniqueA) - && (idx < index) - ) - return curr; - else return "" - }); - if (ambiguous_C0C1_vs_C3.length > 0) - return ("duplicate 1-4 rule: earlier: [" - + ambiguous_C0C1_vs_C3[0].modifier_key + " " - + ambiguous_C0C1_vs_C3[0].key + "] > \'" - + new TextDecoder().decode(ambiguous_C0C1_vs_C3[0].output) - + "\' here: [") - - // 3-6 - // find ambiguous C2 rules vs. C3 .................................................................................................................... - // e.g. CAPS K_A > 'A' <-> CAPS K_A > 'B' ......................................................................................................... - // ................................................................................................................................................... - const ambiguous_C2_vs_C3: rule_object[] = rule.filter((curr, idx) => { - if ((rule[index].rule_type === "C3") - && ((curr.rule_type === "C2")) - && rule[index].modifier_prev_deadkey === curr.modifier_deadkey - && rule[index].prev_deadkey === curr.deadkey - && curr.dk_prev !== rule[index].dk_C2 - && (rule[index].uniqueA === curr.uniqueA) - && (rule[index].uniqueB === curr.uniqueB) - && (idx < index) - ) - return curr; - else return "" - }); - if (ambiguous_C2_vs_C3.length > 0) - return ("duplicate 1-6 rule: earlier: [" - + ambiguous_C2_vs_C3[0].modifier_key + " " - + ambiguous_C2_vs_C3[0].key + "] > \'" - + new TextDecoder().decode(ambiguous_C2_vs_C3[0].output) - + "\' here: [") + && (String(curr.dk_prev) === String(rule[index].dk_prev)) + && rule[index].uniqueA !== 0 + && idx < index + ); + + // A 6-6 amb dup ........................................................... + // 6-6 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'B' + const ambiguous_C3_vs_C3_C = rule.filter((curr, idx) => + (curr.rule_type === "C3") + && curr.modifier_key === rule[index].modifier_key + && curr.key === rule[index].key + && String(curr.dk_C2) === String(rule[index].dk_C2) // no need to convert to string + && String(curr.dk) === String(rule[index].dk) + && (new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output)) // amb + && rule[index].uniqueA !== 0 + && idx < index + ); + + // 6-6 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'Ã' + const duplicate_C3_vs_C3_C = rule.filter((curr, idx) => + (curr.rule_type === "C3") + && curr.modifier_key === rule[index].modifier_key + && curr.key === rule[index].key + + && curr.modifier_deadkey === rule[index].modifier_deadkey + && curr.deadkey === rule[index].deadkey + + && curr.modifier_prev_deadkey === rule[index].modifier_prev_deadkey + && curr.prev_deadkey === rule[index].prev_deadkey + + && new TextDecoder().decode(curr.output) === new TextDecoder().decode(rule[index].output) // dup + + && String(curr.dk_prev) === String(rule[index].dk_prev) // dup + /* && String(curr.dk) === String(rule[index].dk) + && String(curr.dk_C2) === String(rule[index].dk_C2) // dup*/ + //&& rule[index].uniqueA === 0 + // && idx < index + /* + // dup*/ + + ); + console.log(".writeDalaset(duplicate_C3_ ", ) + + // 5-5 + const ambiguous_C3_vs_C3_B = rule.filter((curr, idx) => + (curr.rule_type === "C3") + && curr.modifier_key === rule[index].modifier_key + && curr.key === rule[index].key + && String(curr.dk_C2) === String(rule[index].dk_C2) // no need to convert to string + && String(curr.dk) === String(rule[index].dk) + && (new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output)) // amb + && rule[index].uniqueA !== 0 + && idx < index + ); + + // 5-5 + const duplicate_C3_vs_C3_B = rule.filter((curr, idx) => + (curr.rule_type === "C3") + && curr.modifier_deadkey === rule[index].modifier_deadkey + && curr.deadkey === rule[index].deadkey + + && String(curr.dk_prev) === String(rule[index].dk_prev) // no need to convert to string + && String(curr.dk_C2) === String(rule[index].dk_C2) // no need to convert to string + && String(curr.dk) === String(rule[index].dk) + && rule[index].uniqueA !== 0 + && idx < index + ); + + + this.writeDalasetSingle(rule[index]) + this.writeDalaset(duplicate_C3_vs_C3_C) + + if (ambibguous_C3_vs_C1.length > 0) { + //FIR TEXT + returnarray[0] = returnarray[0] + ("FIRSTTEXT " + "ambiguous 1-4 rule: earlier: [" + ambibguous_C3_vs_C1[0].modifier_key + " " + ambibguous_C3_vs_C1[0].key + "] > \'" + new TextDecoder().decode(ambibguous_C3_vs_C1[0].output) + "\' here: ") + } + + /* if (ambibguous_C3_vs_C2.length > 0) { + //FIR TEXT + returnarray[0] = returnarray[0] + ("FIRSTTEXT " + "ambiguous 2-4 rule: earlier: [" + ambibguous_C3_vs_C2[0].modifier_key + " " + ambibguous_C3_vs_C2[0].key + "] > \'" + new TextDecoder().decode(ambibguous_C3_vs_C2[0].output) + "\' here: ") + }*/ + + + + if (ambibguous_C3_vs_C2_B.length > 0) { + //FIR TEXT + returnarray[0] = returnarray[0] + ("FIRSTTEXT " + "ambiguous 2-4 rule: earlier: [" + ambibguous_C3_vs_C2_B[0].modifier_deadkey + " " + ambibguous_C3_vs_C2_B[0].deadkey + "] > dk(C" + ambibguous_C3_vs_C2_B[0].dk_C2 + ") here: )\'") + } + + + + if (duplicate_C3_vs_C3.length > 0) { + //Firstsentence + returnarray[0] = returnarray[0] + ("FIRSTTEXT " + "duplicate 4-4 rule: earlier: [" + duplicate_C3_vs_C3[0].modifier_deadkey + " " + duplicate_C3_vs_C3[0].deadkey + "] > dk(C" + duplicate_C3_vs_C3[0].dk_C2 + "here: )\'") + } + if (ambiguous_C3_vs_C3.length > 0) { + //Firstsentence + returnarray[0] = returnarray[0] + ("FIRSTTEXT " + "ambiguous 4-4 rule: earlier: [" + ambiguous_C3_vs_C3[0].modifier_deadkey + " " + ambiguous_C3_vs_C3[0].deadkey + "] > dk(C" + ambiguous_C3_vs_C3[0].dk_C2 + "here: )\'") + } + + if (duplicate_C3_vs_C3_C.length > 0) { + //THI TEXT + returnarray[2] = returnarray[2] + ("THIRDTEXT " + "duplicate y 6-6 rule: earlier: dk(C" + duplicate_C3_vs_C3_C[0].dk_C2 + ") + [" + duplicate_C3_vs_C3_C[0].modifier_key + " " + duplicate_C3_vs_C3_C[0].key + "] > \'" + new TextDecoder().decode(duplicate_C3_vs_C3_C[0].output) + "\' here: ") + } + if (ambiguous_C3_vs_C3_C.length > 0) { + //THI TEXT + returnarray[2] = returnarray[2] + ("THIRDTEXT " + "ambiguous y 6-6 rule: earlier: dk(C" + ambiguous_C3_vs_C3_C[0].dk_C2 + ") + [" + ambiguous_C3_vs_C3_C[0].modifier_key + " " + ambiguous_C3_vs_C3_C[0].key + "] > \'" + new TextDecoder().decode(ambiguous_C3_vs_C3_C[0].output) + "\' here: ") + } + + if (duplicate_C3_vs_C2_B2.length > 0) { + //Secondsentence + returnarray[2] = returnarray[2] + ("SECONDTEXT " + "duplicate y 6-3 rule: earlier: dk(C" + duplicate_C3_vs_C2_B2[0].dk_C2 + ") + [" + duplicate_C3_vs_C2_B2[0].modifier_key + " " + duplicate_C3_vs_C2_B2[0].key + "] > \'" + new TextDecoder().decode(duplicate_C3_vs_C2_B2[0].output) + "\' here: ") + } + if (ambiguous_C3_vs_C2_B2.length > 0) { + //Secondsentence + returnarray[2] = returnarray[2] + ("SECONDTEXT " + "ambiguous y 6-3 rule: earlier: dk(C" + ambiguous_C3_vs_C2_B2[0].dk_C2 + ") + [" + ambiguous_C3_vs_C2_B2[0].modifier_key + " " + ambiguous_C3_vs_C2_B2[0].key + "] > \'" + new TextDecoder().decode(ambiguous_C3_vs_C2_B2[0].output) + "\' here: ") + } + + if (duplicate_C3_vs_C3_B.length > 0) { + //THI TEXT + returnarray[1] = returnarray[1] + ("THIRDTEXT " + "duplicate y 5-5 rule: earlier: dk(C" + duplicate_C3_vs_C3_B[0].dk_C2 + ") + [" + duplicate_C3_vs_C3_B[0].modifier_key + " " + duplicate_C3_vs_C3_B[0].key + "] > dk(" + duplicate_C3_vs_C3_B[0].dk_C2 + ") here: ") + } + if (ambiguous_C3_vs_C3_B.length > 0) { + //THI TEXT + returnarray[1] = returnarray[1] + ("THIRDTEXT " + "ambiguous y 5-5 rule: earlier: dk(C" + ambiguous_C3_vs_C3_B[0].dk_C2 + ") + [" + ambiguous_C3_vs_C3_B[0].modifier_key + " " + ambiguous_C3_vs_C3_B[0].key + "] > dk(" + ambiguous_C3_vs_C3_B[0].dk_C2 + ") here: ") + } + + + + } + // A 5-5 amb dup ........................................................... + + + + // filter 3 text .............................................................. + // OK C 1-4 amb............................................................................................................................................ + /* const ambiguous_C0C1_vs_C3 = rule.filter((curr, idx) => + (curr.rule_type === "C0" || curr.rule_type === "C1") + && (rule[index].rule_type === "C3") + + && curr.modifier_key === rule[index].modifier_prev_deadkey + && curr.key === rule[index].prev_deadkey + //&& rule[index].uniqueA !== 0 + && rule[index].uniqueB !== 0 + ); + + if (ambiguous_C0C1_vs_C3.length > 0) { + //Firstsentence + returnarray.push("ambiguous 1-4 rule: earlier: [" + + ambiguous_C0C1_vs_C3[0].modifier_key + " " + + ambiguous_C0C1_vs_C3[0].key + "] > \'" + + new TextDecoder().decode(ambiguous_C0C1_vs_C3[0].output) + + "\' here: [") + + return returnarray + }*/ + + + // E 2-4 amb................................................................................................................................................ + /* const ambiguous_C2_vs_C3 = rule.filter((curr, idx) => + (curr.rule_type === "C2") + && (rule[index].rule_type === "C3") + + && curr.modifier_deadkey === rule[index].modifier_prev_deadkey + && curr.deadkey === rule[index].prev_deadkey + //&& rule[index].uniqueA !== 0 + //&& rule[index].uniqueB !== 0 + ); + + if (ambiguous_C2_vs_C3.length > 0) + return ("ambiguous 2-4 rule: earlier: [" + + ambiguous_C2_vs_C3[0].modifier_deadkey + " " + + ambiguous_C2_vs_C3[0].deadkey + "] > dk(C" + + ambiguous_C2_vs_C3[0].dk_C2 + + "\' here: [")*/ + + + + /* const duplicate_C2_vs_C3 = rule.filter((curr, idx) => + (curr.rule_type === "C2") + && (rule[index].rule_type === "C3") + + + && curr.modifier_deadkey === rule[index].modifier_prev_deadkey + && curr.deadkey === rule[index].prev_deadkey + //&& rule[index].uniqueB !== 0 + && (idx < index) + // only amb here since no dup possible Mod K_A> A <-> Mod K_A> dk(dk1) + ); + console.log("duplicate_C2_vs_C3 ",) + this.writeDalaset(duplicate_C2_vs_C3) + + + if (duplicate_C2_vs_C3.length > 0) + return ("duplicate 2-4 rule: earlier: [" + + duplicate_C2_vs_C3[0].modifier_deadkey + " " + + duplicate_C2_vs_C3[0].modifier_deadkey + "] > \'" + + duplicate_C2_vs_C3[0].dk_prev + + "\' here: [")*/ + + + + /* + + const ambiguous_C0C1_vs_C2 = rule.filter((curr, idx) => + (curr.rule_type === "C0" || curr.rule_type === "C1") + && (rule[index].rule_type === "C2") + + + && curr.modifier_key === rule[index].modifier_deadkey + && curr.key === rule[index].deadkey + //&& rule[index].uniqueB !== 0 + && (idx < index) + // only amb here since no dup possible Mod K_A> A <-> Mod K_A> dk(dk1) + ); + console.log("ambiguous_C0C1_vs_C2 ", ) + this.writeDalaset(ambiguous_C0C1_vs_C2) + + + if (ambiguous_C0C1_vs_C2.length > 0) + return ("ambiguous 1-2 rule: earlier: [" + + + ambiguous_C0C1_vs_C2[0].modifier_key + " " + + ambiguous_C0C1_vs_C2[0].key + "] > \'" + + new TextDecoder().decode(ambiguous_C0C1_vs_C2[0].output) + + "\' here: [") + + */ + + + + + + + + // F 3-3 ................................................................................................................................................ + + /*const ambiguous_C2_vs_C2_B = rule.filter((curr, idx) => + (curr.rule_type === "C2") + + && curr.modifier_deadkey === rule[index].modifier_deadkey + && curr.deadkey === rule[index].deadkey + + && curr.modifier_key === rule[index].modifier_key + && curr.key === rule[index].key + && new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output) // amb + + && rule[index].uniqueB === 0 + && idx < index + ); + + if (ambiguous_C2_vs_C2_B.length > 0) { + //Firstsentence + returnarray.push("FIRSTTEXT 3-3 " + "ambiguous xy 3-3 rule: earlier: [" + + ambiguous_C2_vs_C2_B[0].modifier_deadkey + " " + + ambiguous_C2_vs_C2_B[0].deadkey + "] > dk(C" + + ambiguous_C2_vs_C2_B[0].dk_C2 + + ")\'" + + "here: ") + //Secondsentence + returnarray.push("SECONDTEXT 3-3 " + "ambiguous yx 3-3 rule: earlier: dk(C" + + ambiguous_C2_vs_C2_B[0].dk_C2 + ") + [" + + ambiguous_C2_vs_C2_B[0].modifier_key + " " + + ambiguous_C2_vs_C2_B[0].key + "] \'" + + new TextDecoder().decode(ambiguous_C2_vs_C2_B[0].output) + + "here: ") + + return returnarray + }*/ + + + + /*const duplicate_C2_vs_C2_B = rule.filter((curr, idx) => + (curr.rule_type === "C2") + + && curr.modifier_deadkey === rule[index].modifier_deadkey + && curr.deadkey === rule[index].deadkey + + && curr.modifier_key === rule[index].modifier_key + && curr.key === rule[index].key + && new TextDecoder().decode(curr.output) === new TextDecoder().decode(rule[index].output) // amb + + && rule[index].uniqueB === 0 + && idx < index + ); + if (duplicate_C2_vs_C2_B.length > 0) + console.log("duplicate_C2_vs_C2_B.length ", duplicate_C2_vs_C2_B.length, index) + if ((duplicate_C2_vs_C2_B.length > 0) && (duplicate_C2_vs_C2_B.length < 33)) + this.writeDalaset(duplicate_C2_vs_C2_B) +*/ + /* + console.log("curr.rule_type ", rule[368].rule_type, rule[397].rule_type, rule[368].rule_type === rule[397].rule_type) + console.log("curr.modifier_prev_deadkey ", rule[368].modifier_prev_deadkey, rule[397].modifier_prev_deadkey, rule[368].modifier_prev_deadkey === rule[397].modifier_prev_deadkey) + console.log("curr.prev_deadkey ", rule[368].prev_deadkey, rule[397].prev_deadkey, rule[368].prev_deadkey === rule[397].prev_deadkey) + console.log("curr.dk_prev ", rule[368].dk_prev, rule[397].dk_prev, rule[368].dk_prev === rule[397].dk_prev) + console.log("curr.uniqueA ", rule[368].uniqueA, rule[397].uniqueA, rule[368].uniqueA === rule[397].uniqueA) + + console.log("curr.modifier_deadkey ", rule[368].modifier_deadkey, rule[397].modifier_deadkey, rule[368].modifier_deadkey === rule[397].modifier_deadkey) + console.log("curr.deadkey ", rule[368].deadkey, rule[397].deadkey, rule[368].deadkey === rule[397].deadkey) + console.log("curr.dk ", rule[368].dk, rule[397].dk, rule[368].dk === rule[397].dk) + console.log("curr.dk_C2 ", rule[368].dk_C2, rule[397].dk_C2, rule[368].dk_C2 === rule[397].dk_C2) + console.log("curr.uniqueB ", rule[368].uniqueB, rule[397].uniqueB, rule[368].uniqueB === rule[397].uniqueB) + + console.log("curr.modifier_key ", rule[368].modifier_key, rule[397].modifier_key, rule[368].modifier_key === rule[397].modifier_key) + console.log("curr.key ", rule[368].key, rule[397].key, rule[368].key === rule[397].key) + console.log("curr.output ", new TextDecoder().decode(rule[368].output), new TextDecoder().decode(rule[397].output), + (new TextDecoder().decode(rule[368].output) === new TextDecoder().decode(rule[397].output))) + //------------------------------------------- + console.log("curr.rule_type ", rule[397].rule_type, rule[426].rule_type, rule[397].rule_type === rule[426].rule_type) + console.log("curr.modifier_prev_deadkey ", rule[397].modifier_prev_deadkey, rule[426].modifier_prev_deadkey, rule[397].modifier_prev_deadkey === rule[426].modifier_prev_deadkey) + console.log("curr.prev_deadkey ", rule[397].prev_deadkey, rule[426].prev_deadkey, rule[397].prev_deadkey === rule[426].prev_deadkey) + console.log("curr.dk_prev ", rule[397].dk_prev, rule[426].dk_prev, rule[397].dk_prev === rule[426].dk_prev) + console.log("curr.uniqueA ", rule[397].uniqueA, rule[426].uniqueA, rule[397].uniqueA === rule[426].uniqueA) + + console.log("curr.modifier_deadkey ", rule[397].modifier_deadkey, rule[426].modifier_deadkey, rule[397].modifier_deadkey === rule[426].modifier_deadkey) + console.log("curr.deadkey ", rule[397].deadkey, rule[426].deadkey, rule[397].deadkey === rule[426].deadkey) + console.log("curr.dk ", rule[397].dk, rule[426].dk, rule[397].dk === rule[426].dk) + console.log("curr.dk_C2 ", rule[397].dk_C2, rule[426].dk_C2, rule[397].dk_C2 === rule[426].dk_C2) + console.log("curr.uniqueB ", rule[397].uniqueB, rule[426].uniqueB, rule[397].uniqueB === rule[426].uniqueB) + + console.log("curr.modifier_key ", rule[397].modifier_key, rule[426].modifier_key, rule[397].modifier_key === rule[426].modifier_key) + console.log("curr.key ", rule[397].key, rule[426].key, rule[397].key === rule[426].key) + console.log("curr.output ", new TextDecoder().decode(rule[397].output), new TextDecoder().decode(rule[426].output), + (new TextDecoder().decode(rule[397].output) === new TextDecoder().decode(rule[426].output))) + + + */ + + /*console.log(" rule[539]", rule[539]) + console.log(" rule[540]", rule[540]) + console.log(" rule[541]", rule[541])*/ + + + /* if (duplicate_C2_vs_C2_B.length > 0) { + //Firstsentence + returnarray.push("FIRSTTEXT 3-3 " + "duplicate 3-3 rule: earlier: [" + + duplicate_C2_vs_C2_B[0].modifier_deadkey + " " + + duplicate_C2_vs_C2_B[0].deadkey + "] > dk(C" + + duplicate_C2_vs_C2_B[0].dk_C2 + + ")\'" + + "here: ") + //Secondsentence + returnarray.push("SECONDTEXT 3-3 " + "duplicate 3-3 rule: earlier: dk(C" + + duplicate_C2_vs_C2_B[0].dk_C2 + ") + [" + + duplicate_C2_vs_C2_B[0].modifier_key + " " + + duplicate_C2_vs_C2_B[0].key + "] \'" + + new TextDecoder().decode(duplicate_C2_vs_C2_B[0].output) + + "here: ") + + return returnarray + }*/ + + + + + /*const duplicate_C3_vs_C3 = rule.filter((curr, idx) => + (rule[index].rule_type === "C2") + && (curr.rule_type === "C2") + + && curr.modifier_deadkey === rule[index].modifier_deadkey + && curr.deadkey === rule[index].deadkey + + && curr.modifier_key === rule[index].modifier_key + && curr.key === rule[index].key + // && new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output) // amb + && new TextDecoder().decode(curr.output) === new TextDecoder().decode(rule[index].output) // dup + + && rule[index].uniqueB === 0 + && idx < index + + + ); + if (duplicate_C3_vs_C3.length > 0) { + const text1: string = "FIRSTTEXT 3-3 " + "duplicate 3-3 rule: earlier: [" + + duplicate_C3_vs_C3[0].modifier_deadkey + " " + + duplicate_C3_vs_C3[0].deadkey + "] > dk(C" + + duplicate_C3_vs_C3[0].dk_C2 + + ")\'" + const text2: string = "SECONDTEXT 3-3 " + "duplicate 3-3 rule: earlier: dk(C" + + duplicate_C3_vs_C3[0].dk_C2 + ") + [" + + duplicate_C3_vs_C3[0].modifier_key + " " + + duplicate_C3_vs_C3[0].key + "] \'" + + new TextDecoder().decode(duplicate_C3_vs_C3[0].output) + + return (text1 + text2 + "\' here: [") + }*/ + // G 3-6 ................................................................................................................................................ + // H 4-4 ................................................................................................................................................ + // I 5-5 ................................................................................................................................................ + // J 6-6 ................................................................................................................................................ + + /* const ambiguous_C3_vs_C3_C = rule.filter((curr, idx) => + (rule[index].rule_type === "C2") + && (curr.rule_type === "C2") + + && curr.modifier_deadkey === rule[index].modifier_deadkey + && curr.deadkey === rule[index].deadkey + + && curr.modifier_key === rule[index].modifier_key + && curr.key === rule[index].key + && new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output) // amb + + && rule[index].uniqueB === 0 + && idx < index + ); + + if (ambiguous_C3_vs_C3_C.length > 0) { + const text1: string = "FIRSTTEXT 3-3 " + "duplicate 3-3 rule: earlier: [" + + ambiguous_C3_vs_C3_C[0].modifier_deadkey + " " + + ambiguous_C3_vs_C3_C[0].deadkey + "] > dk(C" + + ambiguous_C3_vs_C3_C[0].dk_C2 + + ")\'" + const text2: string = "SECONDTEXT 3-3 " + "duplicate 3-3 rule: earlier: dk(C" + + ambiguous_C3_vs_C3_C[0].dk_C2 + ") + [" + + ambiguous_C3_vs_C3_C[0].modifier_key + " " + + ambiguous_C3_vs_C3_C[0].key + "] \'" + + new TextDecoder().decode(ambiguous_C3_vs_C3_C[0].output) + + return (text1 + text2 + "\' here: [") + } + + + const duplicate_C3_vs_C3_C = rule.filter((curr, idx) => + (rule[index].rule_type === "C2") + && (curr.rule_type === "C2") + + && curr.modifier_deadkey === rule[index].modifier_deadkey + && curr.deadkey === rule[index].deadkey + + && curr.modifier_key === rule[index].modifier_key + && curr.key === rule[index].key + // && new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output) // amb + && new TextDecoder().decode(curr.output) === new TextDecoder().decode(rule[index].output) // dup + + && rule[index].uniqueB === 0 + && idx < index); + + if (duplicate_C3_vs_C3_C.length > 0) { + const text1: string = "FIRSTTEXT 6-6 " + "duplicate 3-3 rule: earlier: [" + + duplicate_C3_vs_C3_C[0].modifier_deadkey + " " + + duplicate_C3_vs_C3_C[0].deadkey + "] > dk(C" + + duplicate_C3_vs_C3_C[0].dk_C2 + + ")\'" + const text2: string = "SECONDTEXT 6-6 " + "duplicate 3-3 rule: earlier: dk(C" + + duplicate_C3_vs_C3_C[0].dk_C2 + ") + [" + + duplicate_C3_vs_C3_C[0].modifier_key + " " + + duplicate_C3_vs_C3_C[0].key + "] \'" + + new TextDecoder().decode(duplicate_C3_vs_C3_C[0].output) + + return (text1 + text2 + "\' here: [") + }*/ + + + + //} - return "" - } + return returnarray + } public findUnAvailableRule(unique_Rules: rule_object[], index: number): string { if ( @@ -2034,42 +2289,323 @@ export class KeylayoutToKmnConverter { //---------------------------------------------------------------------------------------------------- public createData_Rules(data_ukelele: convert_object): string { + let warningtextArray: string[] = Array(3).fill(""); + //console.log("warningtextArray ", warningtextArray) const maxkey: number = 50 let data: string = "" let keymarker: string = "" + /* + const data_CAll: rule_object[] = data_ukelele.ArrayOf_Rules.filter((curr) => { + if ((curr.output !== new TextEncoder().encode("") || curr.output !== undefined) + && (curr.rule_type === "C0") || (curr.rule_type === "C1") || (curr.rule_type === "C2") || (curr.rule_type === "C3")) { + return curr; + } + else return "" + }); + const unique_CAll_Rules: rule_object[] = data_CAll.reduce((unique, o) => { + if (!unique.some((obj: { output: Uint8Array; rule_type: string; modifier_key: string; modifier_deadkey: string; prev_deadkey: string; modifier_prev_deadkey: string; deadkey: string; key: string }) => + new TextDecoder().decode(obj.output) === new TextDecoder().decode(o.output) + + && obj.rule_type === o.rule_type + && obj.modifier_key === o.modifier_key + && obj.key === o.key + + && obj.modifier_deadkey === o.modifier_deadkey + && obj.deadkey === o.deadkey + + && obj.modifier_prev_deadkey === o.modifier_prev_deadkey + && obj.prev_deadkey === o.prev_deadkey) + ) { + unique.push(o); + } + return unique; + }, []);*/ + const unique_CAll_Rules: rule_object[] = data_ukelele.ArrayOf_Rules + + console.log("xx data_ukelele.ArrayOf_Rules", data_ukelele.ArrayOf_Rules.length) + //console.log("xx data_ukelele.ArrayOf_Rules", this.writeDalaset(data_ukelele.ArrayOf_Rules)) + + console.log("xx unique_CAll_Rules", unique_CAll_Rules.length) + console.log("xx unique_CAll_Rules", this.writeDalaset(unique_CAll_Rules)) + + //................................................ C0 C1 ................................................................ + //................................................ C0 C1 ................................................................ + //................................................ C0 C1 ................................................................ + + for (let i = 0; i < unique_CAll_Rules.length; i++) { + + if ((unique_CAll_Rules[i].rule_type === "C0") || (unique_CAll_Rules[i].rule_type === "C1")) { + // lookup key nr of the key that is being processed + let keyNr: number = 0; + for (let j = 0; j < maxkey; j++) { + if (this.map_UkeleleKC_To_VK(j) === unique_CAll_Rules[i].key) + keyNr = j + } + + // skip keyNr 48 ( TAB ) + if (keyNr === 48) + continue + + // add a line after rules of each key + if (unique_CAll_Rules[i].key !== keymarker) + data += '\n' + //--------------------------------------------------------------------------------------------- - const data_CAll: rule_object[] = data_ukelele.ArrayOf_Rules.filter((curr) => { - if ((curr.output !== new TextEncoder().encode("") || curr.output !== undefined) - && (curr.rule_type === "C0") || (curr.rule_type === "C1") || (curr.rule_type === "C2") || (curr.rule_type === "C3")) { - return curr; + warningtextArray = this.findAmbiguousRules(unique_CAll_Rules, i) + // todo return string[] of findUnAvailableRule + warningtextArray[0] = warningtextArray[0] + this.findUnAvailableRule(unique_CAll_Rules, i) + + if (new TextDecoder().decode(unique_CAll_Rules[i].output) !== "") { + // if no warning + if (warningtextArray[0] === "") + data += "+ [" + (unique_CAll_Rules[i].modifier_key + ' ' + unique_CAll_Rules[i].key).trim() + `] > \'` + new TextDecoder().decode(unique_CAll_Rules[i].output) + '\'\n' + else + // if warning available + data += "c C0 WARNING: " + warningtextArray[0] + (unique_CAll_Rules[i].modifier_key + ' ' + unique_CAll_Rules[i].key).trim() + `] > \'` + new TextDecoder().decode(unique_CAll_Rules[i].output) + '\'\n' + } + keymarker = unique_CAll_Rules[i].key } - else return "" - }); - const unique_CAll_Rules: rule_object[] = data_CAll.reduce((unique, o) => { - if (!unique.some((obj: { output: Uint8Array; rule_type: string; modifier_key: string; modifier_deadkey: string; prev_deadkey: string; modifier_prev_deadkey: string; deadkey: string; key: string }) => - new TextDecoder().decode(obj.output) === new TextDecoder().decode(o.output) - - && obj.rule_type === o.rule_type - && obj.modifier_key === o.modifier_key - && obj.key === o.key - - && obj.modifier_deadkey === o.modifier_deadkey - && obj.deadkey === o.deadkey - - && obj.modifier_prev_deadkey === o.modifier_prev_deadkey - && obj.prev_deadkey === o.prev_deadkey) - ) { - unique.push(o); + } + data += "\n c ########## C2 #################################################################\n" + + //................................................ C2 ................................................................... + //................................................ C2 ................................................................... + //................................................ C2 ................................................................... + for (let k = 0; k < unique_CAll_Rules.length; k++) { + + if (unique_CAll_Rules[k].rule_type === "C2") { + + // todo + //warningtext = warningtext + this.findDuplicateRules(unique_CAll_Rules, k, "C2") + // warningtext = warningtext + this.findAmbiguousRules(unique_CAll_Rules, k) + // warningtext = warningtext + this.findUnAvailableRule(unique_CAll_Rules, k) + + + warningtextArray = this.findAmbiguousRules(unique_CAll_Rules, k) + // console.log("warningtextArray ", warningtextArray) + + // unique First unique second + if ((warningtextArray[0] === "") && (warningtextArray[1] === "")) { + if (unique_CAll_Rules[k].uniqueB !== 0) { + data += "+ [" + unique_CAll_Rules[k].modifier_deadkey + " " + unique_CAll_Rules[k].deadkey + "] > dk(C" + String(unique_CAll_Rules[k].dk_C2) + ")\n" + } + data += "dk(C" + String(unique_CAll_Rules[k].dk_C2) + ") + [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'\n" + } + + + // dup First unique second + if ((warningtextArray[0] !== "") && (warningtextArray[1] === "")) { + if (unique_CAll_Rules[k].uniqueB !== 0) { + data += "C WARNING C2 xx" + warningtextArray[0] + "+ [" + unique_CAll_Rules[k].modifier_deadkey + " " + unique_CAll_Rules[k].deadkey + "] > dk(C" + String(unique_CAll_Rules[k].dk_C2) + ")\n" + } + data += "dk(C" + String(unique_CAll_Rules[k].dk_C2) + ") + [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'\n" + } + + + // unique First dup second + if ((warningtextArray[0] === "") && (warningtextArray[1] !== "")) { + if (unique_CAll_Rules[k].uniqueB !== 0) { + data += "+ [" + unique_CAll_Rules[k].modifier_deadkey + " " + unique_CAll_Rules[k].deadkey + "] > dk(C" + String(unique_CAll_Rules[k].dk_C2) + ")\n" + } + if (unique_CAll_Rules[k].uniqueB !== 0) { + data += "C WARNING C2 yy" + warningtextArray[1] + "dk(C" + String(unique_CAll_Rules[k].dk_C2) + ") + [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'\n" + } + } + + + // dup First dup second + if ((warningtextArray[0] !== "") && (warningtextArray[1] !== "")) { + if (unique_CAll_Rules[k].uniqueB !== 0) { + data += "C WARNING C2 xx" + warningtextArray[0] + "+ [" + unique_CAll_Rules[k].modifier_deadkey + " " + unique_CAll_Rules[k].deadkey + "] > dk(C" + String(unique_CAll_Rules[k].dk_C2) + ")\n" + } if (unique_CAll_Rules[k].uniqueB !== 0) { + data += "C WARNING C2 yy" + warningtextArray[1] + "dk(C" + String(unique_CAll_Rules[k].dk_C2) + ") + [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'\n" + } + } + data += "\n" } - return unique; - }, []); + } + + //................................................ C3 ................................................................... + //................................................ C3 ................................................................... + //................................................ C3 ................................................................... + + data += "\nc ########## C3 #################################################################\n" + + + for (let k = 0; k < unique_CAll_Rules.length; k++) { + + if (unique_CAll_Rules[k].rule_type === "C3") { + + // const warningtext: string = "c C3 WARNING: " + // warningtext = warningtext + this.findDuplicateRules(unique_CAll_Rules, k, "C3") // OK + // warningtext = warningtext + this.findAmbiguousRules(unique_CAll_Rules, k) // OK + //warningtext = warningtext + this.findUnAvailableRule(unique_CAll_Rules, k) // OK + + warningtextArray = this.findAmbiguousRules(unique_CAll_Rules, k) + console.log(" warningtextArray", warningtextArray) + + + + // warningtext1 1 unique - warningtext1 2 unique - warningtext1 3 unique + if ((warningtextArray[0] === "") && (warningtextArray[1] === "") && (warningtextArray[2] === "")) { + if (unique_CAll_Rules[k].uniqueA !== 0) { + data += "+ [" + unique_CAll_Rules[k].modifier_prev_deadkey + " " + unique_CAll_Rules[k].prev_deadkey + "] > dk(A" + String(unique_CAll_Rules[k].dk_prev) + ")\n" + } + if ((unique_CAll_Rules[k].uniqueB !== 0) && (unique_CAll_Rules[k].uniqueA !== 0)) { + data += "dk(A" + String(unique_CAll_Rules[k].dk_prev) + ") + [" + unique_CAll_Rules[k].modifier_deadkey + " " + unique_CAll_Rules[k].deadkey + "] > dk(B" + String(unique_CAll_Rules[k].dk_C2) + ")\n" + } + data += "dk(B" + String(unique_CAll_Rules[k].dk_C2) + ") + [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'\n" + data += "\n" + } + //-----------------------------------OK + + + // warningtext1 1 dup - warningtext1 2 unique - warningtext1 3 unique + if ((warningtextArray[0] !== "") && (warningtextArray[1] === "") && (warningtextArray[2] === "")) { + if (unique_CAll_Rules[k].uniqueA !== 0) { + data += "C WARNING C3 xx A" + warningtextArray[0] + "+ [" + unique_CAll_Rules[k].modifier_prev_deadkey + " " + unique_CAll_Rules[k].prev_deadkey + "] > dk(A" + String(unique_CAll_Rules[k].dk_prev) + ")\n" + } + if ((unique_CAll_Rules[k].uniqueB !== 0) && (unique_CAll_Rules[k].uniqueA !== 0)) { + data += "dk(A" + String(unique_CAll_Rules[k].dk_prev) + ") + [" + unique_CAll_Rules[k].modifier_deadkey + " " + unique_CAll_Rules[k].deadkey + "] > dk(B" + String(unique_CAll_Rules[k].dk_C2) + ")\n" + } + data += "dk(B" + String(unique_CAll_Rules[k].dk_C2) + ") + [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'\n" + data += "\n" + } + // warningtext1 1 unique - warningtext1 2 dup - warningtext1 3 unique + if ((warningtextArray[0] === "") && (warningtextArray[1] !== "") && (warningtextArray[2] === "")) { + if (unique_CAll_Rules[k].uniqueA !== 0) { + data += "C WARNING C3 xx B" + warningtextArray[0] + "+ [" + unique_CAll_Rules[k].modifier_prev_deadkey + " " + unique_CAll_Rules[k].prev_deadkey + "] > dk(A" + String(unique_CAll_Rules[k].dk_prev) + ")\n" + } + if ((unique_CAll_Rules[k].uniqueB !== 0) && (unique_CAll_Rules[k].uniqueA !== 0)) { + data += "C WARNING C3 yy" + warningtextArray[1] + "dk(A" + String(unique_CAll_Rules[k].dk_prev) + ") + [" + unique_CAll_Rules[k].modifier_deadkey + " " + unique_CAll_Rules[k].deadkey + "] > dk(B" + String(unique_CAll_Rules[k].dk_C2) + ")\n" + } + data += "dk(B" + String(unique_CAll_Rules[k].dk_C2) + ") + [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'\n" + data += "\n" + } + // warningtext1 1 dup - warningtext1 2 dup - warningtext1 3 unique + if ((warningtextArray[0] !== "") && (warningtextArray[1] !== "") && (warningtextArray[2] === "")) { + if (unique_CAll_Rules[k].uniqueA !== 0) { + data += "C WARNING C3 xx C" + warningtextArray[0] + "+ [" + unique_CAll_Rules[k].modifier_prev_deadkey + " " + unique_CAll_Rules[k].prev_deadkey + "] > dk(A" + String(unique_CAll_Rules[k].dk_prev) + ")\n" + } + if ((unique_CAll_Rules[k].uniqueB !== 0) && (unique_CAll_Rules[k].uniqueA !== 0)) { + data += "C WARNING C3 yy" + warningtextArray[1] + "dk(A" + String(unique_CAll_Rules[k].dk_prev) + ") + [" + unique_CAll_Rules[k].modifier_deadkey + " " + unique_CAll_Rules[k].deadkey + "] > dk(B" + String(unique_CAll_Rules[k].dk_C2) + ")\n" + } + data += "dk(B" + String(unique_CAll_Rules[k].dk_C2) + ") + [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'\n" + data += "\n" + } + // warningtext1 1 unique - warningtext1 2 unique - warningtext1 3 dup + if ((warningtextArray[0] === "") && (warningtextArray[1] === "") && (warningtextArray[2] !== "")) { + if (unique_CAll_Rules[k].uniqueA !== 0) { + data += "+ [" + unique_CAll_Rules[k].modifier_prev_deadkey + " " + unique_CAll_Rules[k].prev_deadkey + "] > dk(A" + String(unique_CAll_Rules[k].dk_prev) + ")\n" + } + if ((unique_CAll_Rules[k].uniqueB !== 0) && (unique_CAll_Rules[k].uniqueA !== 0)) { + data += "dk(A" + String(unique_CAll_Rules[k].dk_prev) + ") + [" + unique_CAll_Rules[k].modifier_deadkey + " " + unique_CAll_Rules[k].deadkey + "] > dk(B" + String(unique_CAll_Rules[k].dk_C2) + ")\n" + } + data += "C WARNING C3 yy" + warningtextArray[2] + "dk(B" + String(unique_CAll_Rules[k].dk_C2) + ") + [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'\n" + data += "\n" + } + // warningtext1 1 dup - warningtext1 2 unique - warningtext1 3 dup + if ((warningtextArray[0] !== "") && (warningtextArray[1] === "") && (warningtextArray[2] !== "")) { + if (unique_CAll_Rules[k].uniqueA !== 0) { + data += "C WARNING C3 xx" + warningtextArray[0] + "+ [" + unique_CAll_Rules[k].modifier_prev_deadkey + " " + unique_CAll_Rules[k].prev_deadkey + "] > dk(A" + String(unique_CAll_Rules[k].dk_prev) + ")\n" + } + if ((unique_CAll_Rules[k].uniqueB !== 0) && (unique_CAll_Rules[k].uniqueA !== 0)) { + data += "dk(A" + String(unique_CAll_Rules[k].dk_prev) + ") + [" + unique_CAll_Rules[k].modifier_deadkey + " " + unique_CAll_Rules[k].deadkey + "] > dk(B" + String(unique_CAll_Rules[k].dk_C2) + ")\n" + } + data += "C WARNING C3 yy" + warningtextArray[2] + "dk(B" + String(unique_CAll_Rules[k].dk_C2) + ") + [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'\n" + data += "\n" + } + // warningtext1 1 unique - warningtext1 2 dup - warningtext1 3 dup + if ((warningtextArray[0] === "") && (warningtextArray[1] !== "") && (warningtextArray[2] !== "")) { + if (unique_CAll_Rules[k].uniqueA !== 0) { + data += "+ [" + unique_CAll_Rules[k].modifier_prev_deadkey + " " + unique_CAll_Rules[k].prev_deadkey + "] > dk(A" + String(unique_CAll_Rules[k].dk_prev) + ")\n" + } + if ((unique_CAll_Rules[k].uniqueB !== 0) && (unique_CAll_Rules[k].uniqueA !== 0)) { + data += "C WARNING C3 yy" + warningtextArray[1] + "dk(A" + String(unique_CAll_Rules[k].dk_prev) + ") + [" + unique_CAll_Rules[k].modifier_deadkey + " " + unique_CAll_Rules[k].deadkey + "] > dk(B" + String(unique_CAll_Rules[k].dk_C2) + ")\n" + } + data += "C WARNING C3 yy" + warningtextArray[2] + "dk(B" + String(unique_CAll_Rules[k].dk_C2) + ") + [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'\n" + data += "\n" + } + // warningtext1 1 dup - warningtext1 2 dup - warningtext1 3 dup + if ((warningtextArray[0] !== "") && (warningtextArray[1] !== "") && (warningtextArray[2] !== "")) { + if (unique_CAll_Rules[k].uniqueA !== 0) { + data += "C WARNING C3 yy" + warningtextArray[1] + "C WARNING C2 xx" + warningtextArray[0] + "+ [" + unique_CAll_Rules[k].modifier_prev_deadkey + " " + unique_CAll_Rules[k].prev_deadkey + "] > dk(A" + String(unique_CAll_Rules[k].dk_prev) + ")\n" + } + if ((unique_CAll_Rules[k].uniqueB !== 0) && (unique_CAll_Rules[k].uniqueA !== 0)) { + data += "dk(A" + String(unique_CAll_Rules[k].dk_prev) + ") + [" + unique_CAll_Rules[k].modifier_deadkey + " " + unique_CAll_Rules[k].deadkey + "] > dk(B" + String(unique_CAll_Rules[k].dk_C2) + ")\n" + } + data += "C WARNING C3 yy" + warningtextArray[2] + "dk(B" + String(unique_CAll_Rules[k].dk_C2) + ") + [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'\n" + data += "\n" + } + + + /* if (warningtext === "c C3 WARNING: ") { + + if (unique_CAll_Rules[k].uniqueA !== 0) { + data += "+ [" + unique_CAll_Rules[k].modifier_prev_deadkey + " " + unique_CAll_Rules[k].prev_deadkey + "] > dk(A" + String(unique_CAll_Rules[k].dk_prev) + ")\n" + } + + if ((unique_CAll_Rules[k].uniqueB !== 0) && (unique_CAll_Rules[k].uniqueA !== 0)) { + data += "dk(A" + String(unique_CAll_Rules[k].dk_prev) + ") + [" + unique_CAll_Rules[k].modifier_deadkey + " " + unique_CAll_Rules[k].deadkey + "] > dk(B" + String(unique_CAll_Rules[k].dk) + ")\n" + } + + data += "dk(B" + String(unique_CAll_Rules[k].dk) + ") + [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'\n" + data += "\n" + } + + else { + data += warningtext + unique_CAll_Rules[k].modifier_prev_deadkey + " " + unique_CAll_Rules[k].prev_deadkey + "] > dk(A" + String(unique_CAll_Rules[k].dk_prev) + ")\n" + data += "dk(A" + String(unique_CAll_Rules[k].dk_prev) + ") + [" + unique_CAll_Rules[k].modifier_deadkey + " " + unique_CAll_Rules[k].deadkey + "] > dk(B" + String(unique_CAll_Rules[k].dk) + ")\n" + data += "dk(B" + String(unique_CAll_Rules[k].dk) + ") + [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'\n" + }*/ + + data += "\n" + } + } + + data += '\n' + return data + } + + public createData_Rules_old(data_ukelele: convert_object): string { + + const maxkey: number = 50 + let data: string = "" + let keymarker: string = "" + /* + const data_CAll: rule_object[] = data_ukelele.ArrayOf_Rules.filter((curr) => { + if ((curr.output !== new TextEncoder().encode("") || curr.output !== undefined) + && (curr.rule_type === "C0") || (curr.rule_type === "C1") || (curr.rule_type === "C2") || (curr.rule_type === "C3")) { + return curr; + } + else return "" + }); + const unique_CAll_Rules: rule_object[] = data_CAll.reduce((unique, o) => { + if (!unique.some((obj: { output: Uint8Array; rule_type: string; modifier_key: string; modifier_deadkey: string; prev_deadkey: string; modifier_prev_deadkey: string; deadkey: string; key: string }) => + new TextDecoder().decode(obj.output) === new TextDecoder().decode(o.output) + + && obj.rule_type === o.rule_type + && obj.modifier_key === o.modifier_key + && obj.key === o.key + + && obj.modifier_deadkey === o.modifier_deadkey + && obj.deadkey === o.deadkey + + && obj.modifier_prev_deadkey === o.modifier_prev_deadkey + && obj.prev_deadkey === o.prev_deadkey) + ) { + unique.push(o); + } + return unique; + }, []);*/ + const unique_CAll_Rules: rule_object[] = data_ukelele.ArrayOf_Rules console.log("xx data_ukelele.ArrayOf_Rules", data_ukelele.ArrayOf_Rules.length) //console.log("xx data_ukelele.ArrayOf_Rules", this.writeDalaset(data_ukelele.ArrayOf_Rules)) console.log("xx unique_CAll_Rules", unique_CAll_Rules.length) - //console.log("xx unique_CAll_Rules", this.writeDalaset(unique_CAll_Rules)) + console.log("xx unique_CAll_Rules", this.writeDalaset(unique_CAll_Rules)) //................................................ C0 C1 ................................................................ //................................................ C0 C1 ................................................................ @@ -2093,11 +2629,16 @@ export class KeylayoutToKmnConverter { if (unique_CAll_Rules[i].key !== keymarker) data += '\n' + let warningtext: string = "c C0 WARNING: " - warningtext = warningtext + this.findDuplicateRules(unique_CAll_Rules, i, "C01") + // warningtext = warningtext + this.findDuplicateRules(unique_CAll_Rules, i, "C01") //warningtext = warningtext + this.findDuplicateRules(unique_CAll_Rules, i) - warningtext = warningtext + this.findAmbiguousRules(unique_CAll_Rules, i) - warningtext = warningtext + this.findUnAvailableRule(unique_CAll_Rules, i) + warningtext = warningtext + this.findAmbiguousRules(unique_CAll_Rules, i)[0] + //const warningtextArray: string[] = this.findAmbiguousRules(unique_CAll_Rules, i) + // console.log("warningtextArrayOUT ", warningtextArray) + + warningtext = warningtext + this.findUnAvailableRule(unique_CAll_Rules, i)[0] + // todo what about empty returns -> undefined??? // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~ draft print ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -2140,16 +2681,20 @@ export class KeylayoutToKmnConverter { //................................................ C2 ................................................................... //................................................ C2 ................................................................... - + data += "\nc ########## C2 #################################################################\n" for (let k = 0; k < unique_CAll_Rules.length; k++) { if (unique_CAll_Rules[k].rule_type === "C2") { let warningtext: string = "c C2 WARNING: " - warningtext = warningtext + this.findDuplicateRules(unique_CAll_Rules, k, "C2") + //warningtext = warningtext + this.findDuplicateRules(unique_CAll_Rules, k, "C2") warningtext = warningtext + this.findAmbiguousRules(unique_CAll_Rules, k) warningtext = warningtext + this.findUnAvailableRule(unique_CAll_Rules, k) + const warningtextArray: string[] = this.findAmbiguousRules(unique_CAll_Rules, k) + console.log(" warningtextArray", warningtextArray[0], warningtextArray[1], warningtextArray) + + // console.log("warningtext C2", warningtext) // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~ draft print ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -2177,9 +2722,26 @@ export class KeylayoutToKmnConverter { data += "dk(C" + String(unique_CAll_Rules[k].dk_C2) + ") + [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'\n" } // warning avail - else { - data += warningtext + unique_CAll_Rules[k].modifier_deadkey + " " + unique_CAll_Rules[k].deadkey + "] > dk(C" + String(unique_CAll_Rules[k].dk_C2) + ")\n" - data += " dk(C" + String(unique_CAll_Rules[k].dk_C2) + ") + [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'\n" + if (warningtextArray[0] !== "") { + + console.log(" warningtext XXX ", typeof (warningtext), warningtext[0], warningtext[1]) + const secondline = warningtext[1] + const posSecond = warningtext.indexOf("SECONDTEXT") + const firsttext = warningtext[1] + const secondtext = warningtext[0] + console.log("secondline ", secondline, posSecond, firsttext, "---", secondtext) + + data += firsttext + "+ [" + unique_CAll_Rules[k].modifier_deadkey + " " + unique_CAll_Rules[k].deadkey + "] > dk(C" + String(unique_CAll_Rules[k].dk_C2) + ")\n" + if (secondline) + data += "c " + secondtext + "dk(C" + String(unique_CAll_Rules[k].dk_C2) + ") + [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'\n" + else + data += "dk(C" + String(unique_CAll_Rules[k].dk_C2) + ") + [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'\n" + + + + + // data += warningtext + unique_CAll_Rules[k].modifier_deadkey + " " + unique_CAll_Rules[k].deadkey + "] > dk(C" + String(unique_CAll_Rules[k].dk_C2) + ")\n" + // data += " dk(C" + String(unique_CAll_Rules[k].dk_C2) + ") + [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'\n" } } @@ -2200,8 +2762,7 @@ export class KeylayoutToKmnConverter { // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~ draft print end ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - console.log("NOW print C§ ",) + data += "\nc ########## C3 #################################################################\n" for (let k = 0; k < unique_CAll_Rules.length; k++) { @@ -2323,8 +2884,11 @@ export class KeylayoutToKmnConverter { "| ", (dataRules[i].modifier_prev_deadkey !== "" ? dataRules[i].modifier_prev_deadkey.padEnd(33, " ") : "--".padEnd(33, " ")), (dataRules[i].prev_deadkey !== "" ? dataRules[i].prev_deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), - (dataRules[i].dk_prev !== 0 ? ("dk(A" + String(dataRules[i].dk_prev) + ")").padEnd(11, " ") : "--".padEnd(11, " ")), - (dataRules[i].uniqueA !== 0 ? ("unique(A" + String(dataRules[i].uniqueA) + ")").padEnd(11, " ") : "--".padEnd(11, " ")), + //(dataRules[i].dk_prev !== 0 ? ("dk(A" + String(dataRules[i].dk_prev) + ")").padEnd(11, " ") : "--".padEnd(11, " ")), + //(dataRules[i].uniqueA !== 0 ? ("unique(A" + String(dataRules[i].uniqueA) + ")").padEnd(11, " ") : "--".padEnd(11, " ")), + + (("dk(A-B-C " + String(dataRules[i].dk_prev) + "-" + String(dataRules[i].dk)).padEnd(9, "-") + (String(dataRules[i].dk_C2) + ")").padEnd(9, " ")), + ("unique(AB " + String(dataRules[i].uniqueA) + "-" + String(dataRules[i].uniqueB) + ")"), (dataRules[i].modifier_deadkey !== "" ? dataRules[i].modifier_deadkey.padEnd(30, " ") : "--".padEnd(30, " ")), @@ -2333,6 +2897,10 @@ export class KeylayoutToKmnConverter { dataRules[i].rule_type === "C2" ? (dataRules[i].uniqueB !== 0 ? ("unique(C" + String(dataRules[i].uniqueB) + ")").padEnd(9, " ") : "--".padEnd(9, " ")) : ((dataRules[i].uniqueA !== 0 ? ("unique(B" + String(dataRules[i].dk) + ")").padEnd(9, " ") : "--".padEnd(9, " "))), + // dataRules[i].rule_type === "C2" ? (dataRules[i].dk !== 0 ? ("dk(C" + String(dataRules[i].dk) + ")").padEnd(9, " ") : "--".padEnd(9, " ")) : ((dataRules[i].dk !== 0 ? ("dk(B" + String(dataRules[i].dk) + ")").padEnd(9, " ") : "--".padEnd(9, " "))), + // dataRules[i].rule_type === "C2" ? (dataRules[i].uniqueB !== 0 ? ("unique(C" + String(dataRules[i].uniqueB) + ")").padEnd(9, " ") : "--".padEnd(9, " ")) : ((dataRules[i].uniqueA !== 0 ? ("unique(B" + String(dataRules[i].dk) + ")").padEnd(9, " ") : "--".padEnd(9, " "))), + + "| ", (dataRules[i].modifier_key !== "" ? dataRules[i].modifier_key.padEnd(40, " ") : "--".padEnd(40, " ")), (dataRules[i].key !== "" ? dataRules[i].key.padEnd(8, " ") : "--".padEnd(8, " ")), (new TextDecoder().decode(dataRules[i].output) !== "" ? new TextDecoder().decode(dataRules[i].output).padEnd(10, " ") : ("--" + dataRules[i].output) + "--"), From 099b0c00f8c13cce320e66549d30e2e5998d9e47 Mon Sep 17 00:00:00 2001 From: Sabine Date: Thu, 13 Feb 2025 13:05:57 +0100 Subject: [PATCH 049/251] feat(developer): kmc-convert more ambiguous/duplicate rules across C0-C3 --- .../keylayout-to-kmn-converter.ts | 608 ++++-------------- 1 file changed, 121 insertions(+), 487 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 0ca71382d75..7746bd19137 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -71,8 +71,13 @@ import boxXmlArray = util.boxXmlArray;*/ // dk <-> dk_C2 ??? // check if we use the same algorithm to get Block1 data // check uniqueA, uniqueV, dk_prv, dk, dk_C2 -} + // check duplicate rule conditions which do I need; which can go + // when I run german with uniqueCAll why will there be [ ] without key anf modifier + + + +} import { XMLParser } from 'fast-xml-parser'; // for reading a file import { readFileSync } from 'fs'; import { util } from '@keymanapp/common-types'; @@ -101,14 +106,14 @@ export interface rule_object { modifier_prev_deadkey: string, /* string of modifiers for the first key (e.g. "NCAPS RALT CTRL") */ prev_deadkey: string, /* name of the first key (e.g. K_U) */ - dk_prev: number, /* Todo needed?*/ - uniqueA: number, + dk_prev: number, /* dk count for prev-deadkeys */ + uniqueA: number, /* ToDo */ modifier_deadkey: string, /* string of modifiers for the second key (e.g. "NCAPS RALT CTRL") */ deadkey: string, /* name of the second key */ dk: number, /* Todo needed?*/ - dk_C2: number, - uniqueB: number, + dk_C2: number, /* dk count for deadkeys */ + uniqueB: number, /* ToDo */ modifier_key: string, /* string of modifiers for the third key (e.g. "NCAPS RALT CTRL") */ key: string, /* name of the third key (e.g. K_U) */ @@ -243,7 +248,6 @@ export class KeylayoutToKmnConverter { */ //TODO need to use export const USVirtualKeyCodes here public write(data_ukelele: convert_object): boolean { - console.log("\n###################################################\n") let data: string = "\n" // add top part of kmn file: STORES @@ -1479,6 +1483,7 @@ export class KeylayoutToKmnConverter { return keylayout_modifier.flat().flat().includes("caps") } + // todo check conditions command comes through which should not! public isAcceptableKeymanModifier(keylayout_modifier: string): boolean { let iskKeymanModifier: boolean = true const modifier_single: string[] = keylayout_modifier.split(" "); @@ -1499,6 +1504,7 @@ export class KeylayoutToKmnConverter { ) { iskKeymanModifier = iskKeymanModifier && true } else { iskKeymanModifier = iskKeymanModifier && false } } +console.log(" modifier_single",modifier_single, iskKeymanModifier ) return iskKeymanModifier } public findDuplicateRules(rules: rule_object[], index: number, rule_type: string): string { @@ -1541,10 +1547,10 @@ export class KeylayoutToKmnConverter { public findAmbiguousRules(rule: rule_object[], index: number): string[] { const returnarray: string[] = Array(3).fill(""); + // filter 1 Text............................................................... if (rule[index].rule_type === "C0" || rule[index].rule_type === "C1") { - // filter 1 Text............................................................... - // OK A 1-1 amb dup ............................................................................................................................................ + // OK A 1-1 + [CAPS K_N] > 'N' <-> + [CAPS K_N] > 'A' const ambiguous_C0C1_vs_C0C1 = rule.filter((curr, idx) => (curr.rule_type === "C0" || curr.rule_type === "C1") && curr.modifier_prev_deadkey === "" @@ -1556,7 +1562,7 @@ export class KeylayoutToKmnConverter { && new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output) // amb && idx < index ); - + //+ [CAPS K_N] > 'N' <-> + [CAPS K_N] > 'N' const duplicate_C0C1_vs_C0C1 = rule.filter((curr, idx) => (curr.rule_type === "C0" || curr.rule_type === "C1") && curr.modifier_prev_deadkey === "" @@ -1590,6 +1596,7 @@ export class KeylayoutToKmnConverter { return returnarray } + // filter 2 Text............................................................... if (rule[index].rule_type === "C2") { // 2-2 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(C1) @@ -1614,56 +1621,48 @@ export class KeylayoutToKmnConverter { //3-3 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'B' const ambiguous_C2_vs_C2_B2 = rule.filter((curr, idx) => (curr.rule_type === "C2") + && String(curr.dk_C2) === String(rule[index].dk_C2) + && rule[index].uniqueB !== 0 && curr.modifier_key === rule[index].modifier_key && curr.key === rule[index].key - && String(curr.dk_C2) === String(rule[index].dk_C2) && (new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output)) // amb - && rule[index].uniqueB !== 0 && idx < index ); - + //da stimmt noch was nicht //3-3 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'Ã' const duplicate_C2_vs_C2_B2 = rule.filter((curr, idx) => (curr.rule_type === "C2") + && String(curr.dk_C2) === String(rule[index].dk_C2) // dup + && rule[index].uniqueB === 0 && curr.modifier_key === rule[index].modifier_key && curr.key === rule[index].key - && String(curr.dk_C2) === String(rule[index].dk_C2) // dup && new TextDecoder().decode(curr.output) === new TextDecoder().decode(rule[index].output) // dup - && rule[index].uniqueB === 0 && idx < index ); - //1-2 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > 'Ñ' const ambibguous_C2_vs_C1 = rule.filter((curr, idx) => ((curr.rule_type === "C0") || (curr.rule_type === "C1")) - && curr.modifier_key === rule[index].modifier_deadkey && curr.key === rule[index].deadkey //&& rule[index].uniqueB === 0 // without this there will be no warning for first //&& (idx < index) // without this there will be no warning for first ); - if (duplicate_C2_vs_C2.length > 0) { - //Firstsentence - returnarray[0] = returnarray[0] + ("FIRSTTEXT " + "duplicate 2-2 rule: earlier: [" + duplicate_C2_vs_C2[0].modifier_deadkey + " " + duplicate_C2_vs_C2[0].deadkey + "] > dk(C" + duplicate_C2_vs_C2[0].dk_C2 + "here: )\'") - } if (ambiguous_C2_vs_C2.length > 0) { - //Firstsentence returnarray[0] = returnarray[0] + ("FIRSTTEXT " + "ambiguous 2-2 rule: earlier: [" + ambiguous_C2_vs_C2[0].modifier_deadkey + " " + ambiguous_C2_vs_C2[0].deadkey + "] > dk(C" + ambiguous_C2_vs_C2[0].dk_C2 + "here: )\'") } - if (ambibguous_C2_vs_C1.length > 0) { - //Firstsentence - returnarray[0] = returnarray[0] + ("FIRSTTEXT " + "ambiguous 1-2 rule: earlier: [" + ambibguous_C2_vs_C1[0].modifier_key + " " + ambibguous_C2_vs_C1[0].key + "] > \'" + new TextDecoder().decode(ambibguous_C2_vs_C1[0].output) + "\' here: ") + if (duplicate_C2_vs_C2.length > 0) { + returnarray[0] = returnarray[0] + ("FIRSTTEXT " + "duplicate 2-2 rule: earlier: [" + duplicate_C2_vs_C2[0].modifier_deadkey + " " + duplicate_C2_vs_C2[0].deadkey + "] > dk(C" + duplicate_C2_vs_C2[0].dk_C2 + "here: )\'") + } + if (ambiguous_C2_vs_C2_B2.length > 0) { + returnarray[1] = returnarray[1] + ("SECONDTEXT " + "duplicate y 3-3 rule: earlier: dk(C" + ambiguous_C2_vs_C2_B2[0].dk_C2 + ") + [" + ambiguous_C2_vs_C2_B2[0].modifier_key + " " + ambiguous_C2_vs_C2_B2[0].key + "] > \'" + new TextDecoder().decode(ambiguous_C2_vs_C2_B2[0].output) + "\' here: ") } - if (duplicate_C2_vs_C2_B2.length > 0) { - //Secondsentence returnarray[1] = returnarray[1] + ("SECONDTEXT " + "duplicate y 3-3 rule: earlier: dk(C" + duplicate_C2_vs_C2_B2[0].dk_C2 + ") + [" + duplicate_C2_vs_C2_B2[0].modifier_key + " " + duplicate_C2_vs_C2_B2[0].key + "] > \'" + new TextDecoder().decode(duplicate_C2_vs_C2_B2[0].output) + "\' here: ") } - if (ambiguous_C2_vs_C2_B2.length > 0) { - //Secondsentence - returnarray[1] = returnarray[1] + ("SECONDTEXT " + "duplicate y 3-3 rule: earlier: dk(C" + ambiguous_C2_vs_C2_B2[0].dk_C2 + ") + [" + ambiguous_C2_vs_C2_B2[0].modifier_key + " " + ambiguous_C2_vs_C2_B2[0].key + "] > \'" + new TextDecoder().decode(ambiguous_C2_vs_C2_B2[0].output) + "\' here: ") + if (ambibguous_C2_vs_C1.length > 0) { + returnarray[0] = returnarray[0] + ("FIRSTTEXT " + "ambiguous 1-2 rule: earlier: [" + ambibguous_C2_vs_C1[0].modifier_key + " " + ambibguous_C2_vs_C1[0].key + "] > \'" + new TextDecoder().decode(ambibguous_C2_vs_C1[0].output) + "\' here: ") } return returnarray } @@ -1672,25 +1671,19 @@ export class KeylayoutToKmnConverter { returnarray[0] = "" returnarray[1] = "" returnarray[2] = "" - // A 4-1 amb dup ........................................................... - - //1-4 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > 'Ñ' + // 1-4 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > 'Ñ' const ambibguous_C3_vs_C1 = rule.filter((curr, idx) => ((curr.rule_type === "C0") || (curr.rule_type === "C1")) - && curr.modifier_key === rule[index].modifier_prev_deadkey && curr.key === rule[index].prev_deadkey //&& rule[index].uniqueA === 0 // without this there will be no warning //&& (idx < index) ); - // A 4-2 amb dup ........................................................... - - //2-4 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(C1) + // 2-4 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(C1) const ambibguous_C3_vs_C2_B = rule.filter((curr, idx) => ((curr.rule_type === "C2")) - && curr.modifier_deadkey === rule[index].modifier_prev_deadkey && curr.deadkey === rule[index].prev_deadkey && String(curr.dk_C2) === String(rule[index].dk_prev) // dup @@ -1698,38 +1691,34 @@ export class KeylayoutToKmnConverter { //&& (idx < index) ); - // A 6-3 amb dup ........................................................... - - //6-3 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'B' + // 6-3 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'B' const ambiguous_C3_vs_C2_B2 = rule.filter((curr, idx) => (curr.rule_type === "C2") + && String(curr.dk_prev) === String(rule[index].dk_prev) // amb && curr.modifier_key === rule[index].modifier_key && curr.key === rule[index].key - && String(curr.dk_prev) === String(rule[index].dk_prev) // amb && (new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output)) // amb // && rule[index].uniqueB !== 0 // && idx < index ); - //6-3 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'Ã' + // 6-3 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'Ã' const duplicate_C3_vs_C2_B2 = rule.filter((curr, idx) => (curr.rule_type === "C2") + && String(curr.dk_prev) === String(rule[index].dk_prev) // dup && curr.modifier_key === rule[index].modifier_key && curr.key === rule[index].key - && String(curr.dk_prev) === String(rule[index].dk_prev) // dup && new TextDecoder().decode(curr.output) === new TextDecoder().decode(rule[index].output) // dup // && rule[index].uniqueB === 0 // && idx < index ); - // A 4-4 amb dup ........................................................... - // 4-4 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > 'dk(C1)' const ambiguous_C3_vs_C3 = rule.filter((curr, idx) => curr.rule_type === "C3" && curr.modifier_prev_deadkey === rule[index].modifier_prev_deadkey - && curr.prev_deadkey === rule[index].prev_deadkey && (String(curr.dk_prev) !== String(rule[index].dk_prev)) + && curr.prev_deadkey === rule[index].prev_deadkey && rule[index].uniqueA !== 0 && idx < index ); @@ -1744,46 +1733,43 @@ export class KeylayoutToKmnConverter { && idx < index ); - // A 6-6 amb dup ........................................................... // 6-6 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'B' const ambiguous_C3_vs_C3_C = rule.filter((curr, idx) => (curr.rule_type === "C3") - && curr.modifier_key === rule[index].modifier_key - && curr.key === rule[index].key && String(curr.dk_C2) === String(rule[index].dk_C2) // no need to convert to string + && rule[index].uniqueA !== 0 && String(curr.dk) === String(rule[index].dk) + && curr.modifier_key === rule[index].modifier_key + && curr.key === rule[index].key && (new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output)) // amb - && rule[index].uniqueA !== 0 + && idx < index ); // 6-6 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'Ã' const duplicate_C3_vs_C3_C = rule.filter((curr, idx) => - (curr.rule_type === "C3") - && curr.modifier_key === rule[index].modifier_key - && curr.key === rule[index].key - - && curr.modifier_deadkey === rule[index].modifier_deadkey - && curr.deadkey === rule[index].deadkey - - && curr.modifier_prev_deadkey === rule[index].modifier_prev_deadkey - && curr.prev_deadkey === rule[index].prev_deadkey - - && new TextDecoder().decode(curr.output) === new TextDecoder().decode(rule[index].output) // dup - - && String(curr.dk_prev) === String(rule[index].dk_prev) // dup - /* && String(curr.dk) === String(rule[index].dk) - && String(curr.dk_C2) === String(rule[index].dk_C2) // dup*/ - //&& rule[index].uniqueA === 0 - // && idx < index - /* - // dup*/ - + ((curr.rule_type === "C3") + && curr.modifier_key === rule[index].modifier_key + && curr.key === rule[index].key + && curr.modifier_deadkey === rule[index].modifier_deadkey + && curr.deadkey === rule[index].deadkey + && curr.modifier_prev_deadkey !== "" + && curr.prev_deadkey !== "" + && curr.dk_prev !== 0 + && new TextDecoder().decode(curr.output) === new TextDecoder().decode(rule[index].output) // dup + && rule[index].uniqueB !== 0 + && idx < index) + || + ((curr.rule_type === "C3") + && curr.dk_C2 === rule[index].dk_C2 + && curr.modifier_key === rule[index].modifier_key + && curr.key === rule[index].key + && new TextDecoder().decode(curr.output) === new TextDecoder().decode(rule[index].output) // dup + && idx < index) ); - console.log(".writeDalaset(duplicate_C3_ ", ) - // 5-5 - const ambiguous_C3_vs_C3_B = rule.filter((curr, idx) => + // 5-5 + const ambiguous_C3_vs_C3_B = rule.filter((curr, idx) => (curr.rule_type === "C3") && curr.modifier_key === rule[index].modifier_key && curr.key === rule[index].key @@ -1794,12 +1780,11 @@ export class KeylayoutToKmnConverter { && idx < index ); - // 5-5 - const duplicate_C3_vs_C3_B = rule.filter((curr, idx) => + // 5-5 + const duplicate_C3_vs_C3_B = rule.filter((curr, idx) => (curr.rule_type === "C3") && curr.modifier_deadkey === rule[index].modifier_deadkey && curr.deadkey === rule[index].deadkey - && String(curr.dk_prev) === String(rule[index].dk_prev) // no need to convert to string && String(curr.dk_C2) === String(rule[index].dk_C2) // no need to convert to string && String(curr.dk) === String(rule[index].dk) @@ -1807,399 +1792,53 @@ export class KeylayoutToKmnConverter { && idx < index ); - - this.writeDalasetSingle(rule[index]) - this.writeDalaset(duplicate_C3_vs_C3_C) - if (ambibguous_C3_vs_C1.length > 0) { - //FIR TEXT returnarray[0] = returnarray[0] + ("FIRSTTEXT " + "ambiguous 1-4 rule: earlier: [" + ambibguous_C3_vs_C1[0].modifier_key + " " + ambibguous_C3_vs_C1[0].key + "] > \'" + new TextDecoder().decode(ambibguous_C3_vs_C1[0].output) + "\' here: ") } - /* if (ambibguous_C3_vs_C2.length > 0) { - //FIR TEXT - returnarray[0] = returnarray[0] + ("FIRSTTEXT " + "ambiguous 2-4 rule: earlier: [" + ambibguous_C3_vs_C2[0].modifier_key + " " + ambibguous_C3_vs_C2[0].key + "] > \'" + new TextDecoder().decode(ambibguous_C3_vs_C2[0].output) + "\' here: ") - }*/ - - - if (ambibguous_C3_vs_C2_B.length > 0) { - //FIR TEXT returnarray[0] = returnarray[0] + ("FIRSTTEXT " + "ambiguous 2-4 rule: earlier: [" + ambibguous_C3_vs_C2_B[0].modifier_deadkey + " " + ambibguous_C3_vs_C2_B[0].deadkey + "] > dk(C" + ambibguous_C3_vs_C2_B[0].dk_C2 + ") here: )\'") } + if (ambiguous_C3_vs_C2_B2.length > 0) { + returnarray[2] = returnarray[2] + ("SECONDTEXT " + "ambiguous y 6-3 rule: earlier: dk(C" + ambiguous_C3_vs_C2_B2[0].dk_C2 + ") + [" + ambiguous_C3_vs_C2_B2[0].modifier_key + " " + ambiguous_C3_vs_C2_B2[0].key + "] > \'" + new TextDecoder().decode(ambiguous_C3_vs_C2_B2[0].output) + "\' here: ") + } - - if (duplicate_C3_vs_C3.length > 0) { - //Firstsentence - returnarray[0] = returnarray[0] + ("FIRSTTEXT " + "duplicate 4-4 rule: earlier: [" + duplicate_C3_vs_C3[0].modifier_deadkey + " " + duplicate_C3_vs_C3[0].deadkey + "] > dk(C" + duplicate_C3_vs_C3[0].dk_C2 + "here: )\'") + if (duplicate_C3_vs_C2_B2.length > 0) { + returnarray[2] = returnarray[2] + ("SECONDTEXT " + "duplicate y 6-3 rule: earlier: dk(C" + duplicate_C3_vs_C2_B2[0].dk_C2 + ") + [" + duplicate_C3_vs_C2_B2[0].modifier_key + " " + duplicate_C3_vs_C2_B2[0].key + "] > \'" + new TextDecoder().decode(duplicate_C3_vs_C2_B2[0].output) + "\' here: ") } + if (ambiguous_C3_vs_C3.length > 0) { - //Firstsentence returnarray[0] = returnarray[0] + ("FIRSTTEXT " + "ambiguous 4-4 rule: earlier: [" + ambiguous_C3_vs_C3[0].modifier_deadkey + " " + ambiguous_C3_vs_C3[0].deadkey + "] > dk(C" + ambiguous_C3_vs_C3[0].dk_C2 + "here: )\'") } - - if (duplicate_C3_vs_C3_C.length > 0) { - //THI TEXT - returnarray[2] = returnarray[2] + ("THIRDTEXT " + "duplicate y 6-6 rule: earlier: dk(C" + duplicate_C3_vs_C3_C[0].dk_C2 + ") + [" + duplicate_C3_vs_C3_C[0].modifier_key + " " + duplicate_C3_vs_C3_C[0].key + "] > \'" + new TextDecoder().decode(duplicate_C3_vs_C3_C[0].output) + "\' here: ") + if (duplicate_C3_vs_C3.length > 0) { + returnarray[0] = returnarray[0] + ("FIRSTTEXT " + "duplicate 4-4 rule: earlier: [" + duplicate_C3_vs_C3[0].modifier_deadkey + " " + duplicate_C3_vs_C3[0].deadkey + "] > dk(C" + duplicate_C3_vs_C3[0].dk_C2 + "here: )\'") } + if (ambiguous_C3_vs_C3_C.length > 0) { - //THI TEXT - returnarray[2] = returnarray[2] + ("THIRDTEXT " + "ambiguous y 6-6 rule: earlier: dk(C" + ambiguous_C3_vs_C3_C[0].dk_C2 + ") + [" + ambiguous_C3_vs_C3_C[0].modifier_key + " " + ambiguous_C3_vs_C3_C[0].key + "] > \'" + new TextDecoder().decode(ambiguous_C3_vs_C3_C[0].output) + "\' here: ") + returnarray[2] = returnarray[2] + ("THIRDTEXT " + "ambiguous y 6-6 rule: earlier: dk(B" + ambiguous_C3_vs_C3_C[0].dk_C2 + ") + [" + ambiguous_C3_vs_C3_C[0].modifier_key + " " + ambiguous_C3_vs_C3_C[0].key + "] > \'" + new TextDecoder().decode(ambiguous_C3_vs_C3_C[0].output) + "\' here: ") } - if (duplicate_C3_vs_C2_B2.length > 0) { - //Secondsentence - returnarray[2] = returnarray[2] + ("SECONDTEXT " + "duplicate y 6-3 rule: earlier: dk(C" + duplicate_C3_vs_C2_B2[0].dk_C2 + ") + [" + duplicate_C3_vs_C2_B2[0].modifier_key + " " + duplicate_C3_vs_C2_B2[0].key + "] > \'" + new TextDecoder().decode(duplicate_C3_vs_C2_B2[0].output) + "\' here: ") - } - if (ambiguous_C3_vs_C2_B2.length > 0) { - //Secondsentence - returnarray[2] = returnarray[2] + ("SECONDTEXT " + "ambiguous y 6-3 rule: earlier: dk(C" + ambiguous_C3_vs_C2_B2[0].dk_C2 + ") + [" + ambiguous_C3_vs_C2_B2[0].modifier_key + " " + ambiguous_C3_vs_C2_B2[0].key + "] > \'" + new TextDecoder().decode(ambiguous_C3_vs_C2_B2[0].output) + "\' here: ") + if (duplicate_C3_vs_C3_C.length > 0) { + returnarray[2] = returnarray[2] + ("THIRDTEXT " + "duplicate y 6-6 rule: earlier: dk(B" + duplicate_C3_vs_C3_C[0].dk_C2 + ") + [" + duplicate_C3_vs_C3_C[0].modifier_key + " " + duplicate_C3_vs_C3_C[0].key + "] > \'" + new TextDecoder().decode(duplicate_C3_vs_C3_C[0].output) + "\' here: ") } - if (duplicate_C3_vs_C3_B.length > 0) { - //THI TEXT - returnarray[1] = returnarray[1] + ("THIRDTEXT " + "duplicate y 5-5 rule: earlier: dk(C" + duplicate_C3_vs_C3_B[0].dk_C2 + ") + [" + duplicate_C3_vs_C3_B[0].modifier_key + " " + duplicate_C3_vs_C3_B[0].key + "] > dk(" + duplicate_C3_vs_C3_B[0].dk_C2 + ") here: ") - } if (ambiguous_C3_vs_C3_B.length > 0) { - //THI TEXT returnarray[1] = returnarray[1] + ("THIRDTEXT " + "ambiguous y 5-5 rule: earlier: dk(C" + ambiguous_C3_vs_C3_B[0].dk_C2 + ") + [" + ambiguous_C3_vs_C3_B[0].modifier_key + " " + ambiguous_C3_vs_C3_B[0].key + "] > dk(" + ambiguous_C3_vs_C3_B[0].dk_C2 + ") here: ") } - - + if (duplicate_C3_vs_C3_B.length > 0) { + returnarray[1] = returnarray[1] + ("THIRDTEXT " + "duplicate y 5-5 rule: earlier: dk(C" + duplicate_C3_vs_C3_B[0].dk_C2 + ") + [" + duplicate_C3_vs_C3_B[0].modifier_key + " " + duplicate_C3_vs_C3_B[0].key + "] > dk(" + duplicate_C3_vs_C3_B[0].dk_C2 + ") here: ") + } } - // A 5-5 amb dup ........................................................... - - - - // filter 3 text .............................................................. - // OK C 1-4 amb............................................................................................................................................ - /* const ambiguous_C0C1_vs_C3 = rule.filter((curr, idx) => - (curr.rule_type === "C0" || curr.rule_type === "C1") - && (rule[index].rule_type === "C3") - - && curr.modifier_key === rule[index].modifier_prev_deadkey - && curr.key === rule[index].prev_deadkey - //&& rule[index].uniqueA !== 0 - && rule[index].uniqueB !== 0 - ); - - if (ambiguous_C0C1_vs_C3.length > 0) { - //Firstsentence - returnarray.push("ambiguous 1-4 rule: earlier: [" - + ambiguous_C0C1_vs_C3[0].modifier_key + " " - + ambiguous_C0C1_vs_C3[0].key + "] > \'" - + new TextDecoder().decode(ambiguous_C0C1_vs_C3[0].output) - + "\' here: [") - - return returnarray - }*/ - - - // E 2-4 amb................................................................................................................................................ - /* const ambiguous_C2_vs_C3 = rule.filter((curr, idx) => - (curr.rule_type === "C2") - && (rule[index].rule_type === "C3") - - && curr.modifier_deadkey === rule[index].modifier_prev_deadkey - && curr.deadkey === rule[index].prev_deadkey - //&& rule[index].uniqueA !== 0 - //&& rule[index].uniqueB !== 0 - ); - - if (ambiguous_C2_vs_C3.length > 0) - return ("ambiguous 2-4 rule: earlier: [" - + ambiguous_C2_vs_C3[0].modifier_deadkey + " " - + ambiguous_C2_vs_C3[0].deadkey + "] > dk(C" - + ambiguous_C2_vs_C3[0].dk_C2 - + "\' here: [")*/ - - - - /* const duplicate_C2_vs_C3 = rule.filter((curr, idx) => - (curr.rule_type === "C2") - && (rule[index].rule_type === "C3") - - - && curr.modifier_deadkey === rule[index].modifier_prev_deadkey - && curr.deadkey === rule[index].prev_deadkey - //&& rule[index].uniqueB !== 0 - && (idx < index) - // only amb here since no dup possible Mod K_A> A <-> Mod K_A> dk(dk1) - ); - console.log("duplicate_C2_vs_C3 ",) - this.writeDalaset(duplicate_C2_vs_C3) - - - if (duplicate_C2_vs_C3.length > 0) - return ("duplicate 2-4 rule: earlier: [" - + duplicate_C2_vs_C3[0].modifier_deadkey + " " - + duplicate_C2_vs_C3[0].modifier_deadkey + "] > \'" - + duplicate_C2_vs_C3[0].dk_prev - + "\' here: [")*/ - - - - /* - - const ambiguous_C0C1_vs_C2 = rule.filter((curr, idx) => - (curr.rule_type === "C0" || curr.rule_type === "C1") - && (rule[index].rule_type === "C2") - - - && curr.modifier_key === rule[index].modifier_deadkey - && curr.key === rule[index].deadkey - //&& rule[index].uniqueB !== 0 - && (idx < index) - // only amb here since no dup possible Mod K_A> A <-> Mod K_A> dk(dk1) - ); - console.log("ambiguous_C0C1_vs_C2 ", ) - this.writeDalaset(ambiguous_C0C1_vs_C2) - - - if (ambiguous_C0C1_vs_C2.length > 0) - return ("ambiguous 1-2 rule: earlier: [" - - + ambiguous_C0C1_vs_C2[0].modifier_key + " " - + ambiguous_C0C1_vs_C2[0].key + "] > \'" - + new TextDecoder().decode(ambiguous_C0C1_vs_C2[0].output) - + "\' here: [") - - */ - - - - - - - - // F 3-3 ................................................................................................................................................ - - /*const ambiguous_C2_vs_C2_B = rule.filter((curr, idx) => - (curr.rule_type === "C2") - - && curr.modifier_deadkey === rule[index].modifier_deadkey - && curr.deadkey === rule[index].deadkey - - && curr.modifier_key === rule[index].modifier_key - && curr.key === rule[index].key - && new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output) // amb - - && rule[index].uniqueB === 0 - && idx < index - ); - - if (ambiguous_C2_vs_C2_B.length > 0) { - //Firstsentence - returnarray.push("FIRSTTEXT 3-3 " + "ambiguous xy 3-3 rule: earlier: [" - + ambiguous_C2_vs_C2_B[0].modifier_deadkey + " " - + ambiguous_C2_vs_C2_B[0].deadkey + "] > dk(C" - + ambiguous_C2_vs_C2_B[0].dk_C2 - + ")\'" - + "here: ") - //Secondsentence - returnarray.push("SECONDTEXT 3-3 " + "ambiguous yx 3-3 rule: earlier: dk(C" - + ambiguous_C2_vs_C2_B[0].dk_C2 + ") + [" - + ambiguous_C2_vs_C2_B[0].modifier_key + " " - + ambiguous_C2_vs_C2_B[0].key + "] \'" - + new TextDecoder().decode(ambiguous_C2_vs_C2_B[0].output) - + "here: ") - - return returnarray - }*/ - - - - /*const duplicate_C2_vs_C2_B = rule.filter((curr, idx) => - (curr.rule_type === "C2") - - && curr.modifier_deadkey === rule[index].modifier_deadkey - && curr.deadkey === rule[index].deadkey - - && curr.modifier_key === rule[index].modifier_key - && curr.key === rule[index].key - && new TextDecoder().decode(curr.output) === new TextDecoder().decode(rule[index].output) // amb - - && rule[index].uniqueB === 0 - && idx < index - ); - if (duplicate_C2_vs_C2_B.length > 0) - console.log("duplicate_C2_vs_C2_B.length ", duplicate_C2_vs_C2_B.length, index) - if ((duplicate_C2_vs_C2_B.length > 0) && (duplicate_C2_vs_C2_B.length < 33)) - this.writeDalaset(duplicate_C2_vs_C2_B) -*/ - /* - console.log("curr.rule_type ", rule[368].rule_type, rule[397].rule_type, rule[368].rule_type === rule[397].rule_type) - console.log("curr.modifier_prev_deadkey ", rule[368].modifier_prev_deadkey, rule[397].modifier_prev_deadkey, rule[368].modifier_prev_deadkey === rule[397].modifier_prev_deadkey) - console.log("curr.prev_deadkey ", rule[368].prev_deadkey, rule[397].prev_deadkey, rule[368].prev_deadkey === rule[397].prev_deadkey) - console.log("curr.dk_prev ", rule[368].dk_prev, rule[397].dk_prev, rule[368].dk_prev === rule[397].dk_prev) - console.log("curr.uniqueA ", rule[368].uniqueA, rule[397].uniqueA, rule[368].uniqueA === rule[397].uniqueA) - - console.log("curr.modifier_deadkey ", rule[368].modifier_deadkey, rule[397].modifier_deadkey, rule[368].modifier_deadkey === rule[397].modifier_deadkey) - console.log("curr.deadkey ", rule[368].deadkey, rule[397].deadkey, rule[368].deadkey === rule[397].deadkey) - console.log("curr.dk ", rule[368].dk, rule[397].dk, rule[368].dk === rule[397].dk) - console.log("curr.dk_C2 ", rule[368].dk_C2, rule[397].dk_C2, rule[368].dk_C2 === rule[397].dk_C2) - console.log("curr.uniqueB ", rule[368].uniqueB, rule[397].uniqueB, rule[368].uniqueB === rule[397].uniqueB) - - console.log("curr.modifier_key ", rule[368].modifier_key, rule[397].modifier_key, rule[368].modifier_key === rule[397].modifier_key) - console.log("curr.key ", rule[368].key, rule[397].key, rule[368].key === rule[397].key) - console.log("curr.output ", new TextDecoder().decode(rule[368].output), new TextDecoder().decode(rule[397].output), - (new TextDecoder().decode(rule[368].output) === new TextDecoder().decode(rule[397].output))) - //------------------------------------------- - console.log("curr.rule_type ", rule[397].rule_type, rule[426].rule_type, rule[397].rule_type === rule[426].rule_type) - console.log("curr.modifier_prev_deadkey ", rule[397].modifier_prev_deadkey, rule[426].modifier_prev_deadkey, rule[397].modifier_prev_deadkey === rule[426].modifier_prev_deadkey) - console.log("curr.prev_deadkey ", rule[397].prev_deadkey, rule[426].prev_deadkey, rule[397].prev_deadkey === rule[426].prev_deadkey) - console.log("curr.dk_prev ", rule[397].dk_prev, rule[426].dk_prev, rule[397].dk_prev === rule[426].dk_prev) - console.log("curr.uniqueA ", rule[397].uniqueA, rule[426].uniqueA, rule[397].uniqueA === rule[426].uniqueA) - - console.log("curr.modifier_deadkey ", rule[397].modifier_deadkey, rule[426].modifier_deadkey, rule[397].modifier_deadkey === rule[426].modifier_deadkey) - console.log("curr.deadkey ", rule[397].deadkey, rule[426].deadkey, rule[397].deadkey === rule[426].deadkey) - console.log("curr.dk ", rule[397].dk, rule[426].dk, rule[397].dk === rule[426].dk) - console.log("curr.dk_C2 ", rule[397].dk_C2, rule[426].dk_C2, rule[397].dk_C2 === rule[426].dk_C2) - console.log("curr.uniqueB ", rule[397].uniqueB, rule[426].uniqueB, rule[397].uniqueB === rule[426].uniqueB) - - console.log("curr.modifier_key ", rule[397].modifier_key, rule[426].modifier_key, rule[397].modifier_key === rule[426].modifier_key) - console.log("curr.key ", rule[397].key, rule[426].key, rule[397].key === rule[426].key) - console.log("curr.output ", new TextDecoder().decode(rule[397].output), new TextDecoder().decode(rule[426].output), - (new TextDecoder().decode(rule[397].output) === new TextDecoder().decode(rule[426].output))) - - - */ - - /*console.log(" rule[539]", rule[539]) - console.log(" rule[540]", rule[540]) - console.log(" rule[541]", rule[541])*/ - - - /* if (duplicate_C2_vs_C2_B.length > 0) { - //Firstsentence - returnarray.push("FIRSTTEXT 3-3 " + "duplicate 3-3 rule: earlier: [" - + duplicate_C2_vs_C2_B[0].modifier_deadkey + " " - + duplicate_C2_vs_C2_B[0].deadkey + "] > dk(C" - + duplicate_C2_vs_C2_B[0].dk_C2 - + ")\'" - + "here: ") - //Secondsentence - returnarray.push("SECONDTEXT 3-3 " + "duplicate 3-3 rule: earlier: dk(C" - + duplicate_C2_vs_C2_B[0].dk_C2 + ") + [" - + duplicate_C2_vs_C2_B[0].modifier_key + " " - + duplicate_C2_vs_C2_B[0].key + "] \'" - + new TextDecoder().decode(duplicate_C2_vs_C2_B[0].output) - + "here: ") - - return returnarray - }*/ - - - - - /*const duplicate_C3_vs_C3 = rule.filter((curr, idx) => - (rule[index].rule_type === "C2") - && (curr.rule_type === "C2") - - && curr.modifier_deadkey === rule[index].modifier_deadkey - && curr.deadkey === rule[index].deadkey - - && curr.modifier_key === rule[index].modifier_key - && curr.key === rule[index].key - // && new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output) // amb - && new TextDecoder().decode(curr.output) === new TextDecoder().decode(rule[index].output) // dup - - && rule[index].uniqueB === 0 - && idx < index - - - ); - if (duplicate_C3_vs_C3.length > 0) { - const text1: string = "FIRSTTEXT 3-3 " + "duplicate 3-3 rule: earlier: [" - + duplicate_C3_vs_C3[0].modifier_deadkey + " " - + duplicate_C3_vs_C3[0].deadkey + "] > dk(C" - + duplicate_C3_vs_C3[0].dk_C2 - + ")\'" - const text2: string = "SECONDTEXT 3-3 " + "duplicate 3-3 rule: earlier: dk(C" - + duplicate_C3_vs_C3[0].dk_C2 + ") + [" - + duplicate_C3_vs_C3[0].modifier_key + " " - + duplicate_C3_vs_C3[0].key + "] \'" - + new TextDecoder().decode(duplicate_C3_vs_C3[0].output) - - return (text1 + text2 + "\' here: [") - }*/ - // G 3-6 ................................................................................................................................................ - // H 4-4 ................................................................................................................................................ - // I 5-5 ................................................................................................................................................ - // J 6-6 ................................................................................................................................................ - - /* const ambiguous_C3_vs_C3_C = rule.filter((curr, idx) => - (rule[index].rule_type === "C2") - && (curr.rule_type === "C2") - - && curr.modifier_deadkey === rule[index].modifier_deadkey - && curr.deadkey === rule[index].deadkey - - && curr.modifier_key === rule[index].modifier_key - && curr.key === rule[index].key - && new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output) // amb - - && rule[index].uniqueB === 0 - && idx < index - ); - - if (ambiguous_C3_vs_C3_C.length > 0) { - const text1: string = "FIRSTTEXT 3-3 " + "duplicate 3-3 rule: earlier: [" - + ambiguous_C3_vs_C3_C[0].modifier_deadkey + " " - + ambiguous_C3_vs_C3_C[0].deadkey + "] > dk(C" - + ambiguous_C3_vs_C3_C[0].dk_C2 - + ")\'" - const text2: string = "SECONDTEXT 3-3 " + "duplicate 3-3 rule: earlier: dk(C" - + ambiguous_C3_vs_C3_C[0].dk_C2 + ") + [" - + ambiguous_C3_vs_C3_C[0].modifier_key + " " - + ambiguous_C3_vs_C3_C[0].key + "] \'" - + new TextDecoder().decode(ambiguous_C3_vs_C3_C[0].output) - - return (text1 + text2 + "\' here: [") - } - - - const duplicate_C3_vs_C3_C = rule.filter((curr, idx) => - (rule[index].rule_type === "C2") - && (curr.rule_type === "C2") - - && curr.modifier_deadkey === rule[index].modifier_deadkey - && curr.deadkey === rule[index].deadkey - - && curr.modifier_key === rule[index].modifier_key - && curr.key === rule[index].key - // && new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output) // amb - && new TextDecoder().decode(curr.output) === new TextDecoder().decode(rule[index].output) // dup - - && rule[index].uniqueB === 0 - && idx < index); - - if (duplicate_C3_vs_C3_C.length > 0) { - const text1: string = "FIRSTTEXT 6-6 " + "duplicate 3-3 rule: earlier: [" - + duplicate_C3_vs_C3_C[0].modifier_deadkey + " " - + duplicate_C3_vs_C3_C[0].deadkey + "] > dk(C" - + duplicate_C3_vs_C3_C[0].dk_C2 - + ")\'" - const text2: string = "SECONDTEXT 6-6 " + "duplicate 3-3 rule: earlier: dk(C" - + duplicate_C3_vs_C3_C[0].dk_C2 + ") + [" - + duplicate_C3_vs_C3_C[0].modifier_key + " " - + duplicate_C3_vs_C3_C[0].key + "] \'" - + new TextDecoder().decode(duplicate_C3_vs_C3_C[0].output) - - return (text1 + text2 + "\' here: [") - }*/ - - - - //} - - return returnarray } public findUnAvailableRule(unique_Rules: rule_object[], index: number): string { + console.log("isAcceptableKeymanModifier ",unique_Rules[index].modifier_key,this.isAcceptableKeymanModifier(unique_Rules[index].modifier_key) ) + if(unique_Rules[index].modifier_key ==="CAPS" ) + console.log("isAcceptableKeymanModifier A",this.isAcceptableKeymanModifier(unique_Rules[index].modifier_key) ) + if ( (((unique_Rules[index].rule_type === "C0") || (unique_Rules[index].rule_type === "C1") || (unique_Rules[index].rule_type === "C4")) && (this.isAcceptableKeymanModifier(unique_Rules[index].modifier_key))) @@ -2295,39 +1934,39 @@ export class KeylayoutToKmnConverter { const maxkey: number = 50 let data: string = "" let keymarker: string = "" - /* - const data_CAll: rule_object[] = data_ukelele.ArrayOf_Rules.filter((curr) => { - if ((curr.output !== new TextEncoder().encode("") || curr.output !== undefined) - && (curr.rule_type === "C0") || (curr.rule_type === "C1") || (curr.rule_type === "C2") || (curr.rule_type === "C3")) { - return curr; - } - else return "" - }); - const unique_CAll_Rules: rule_object[] = data_CAll.reduce((unique, o) => { - if (!unique.some((obj: { output: Uint8Array; rule_type: string; modifier_key: string; modifier_deadkey: string; prev_deadkey: string; modifier_prev_deadkey: string; deadkey: string; key: string }) => - new TextDecoder().decode(obj.output) === new TextDecoder().decode(o.output) - - && obj.rule_type === o.rule_type - && obj.modifier_key === o.modifier_key - && obj.key === o.key - - && obj.modifier_deadkey === o.modifier_deadkey - && obj.deadkey === o.deadkey - - && obj.modifier_prev_deadkey === o.modifier_prev_deadkey - && obj.prev_deadkey === o.prev_deadkey) - ) { - unique.push(o); - } - return unique; - }, []);*/ - const unique_CAll_Rules: rule_object[] = data_ukelele.ArrayOf_Rules + + const data_CAll: rule_object[] = data_ukelele.ArrayOf_Rules.filter((curr) => { + if ((curr.output !== new TextEncoder().encode("") || curr.output !== undefined) + && (curr.rule_type === "C0") || (curr.rule_type === "C1") || (curr.rule_type === "C2") || (curr.rule_type === "C3")) { + return curr; + } + else return "" + }); + const unique_CAll_Rules: rule_object[] = data_CAll.reduce((unique, o) => { + if (!unique.some((obj: { output: Uint8Array; rule_type: string; modifier_key: string; modifier_deadkey: string; prev_deadkey: string; modifier_prev_deadkey: string; deadkey: string; key: string }) => + new TextDecoder().decode(obj.output) === new TextDecoder().decode(o.output) + + && obj.rule_type === o.rule_type + && obj.modifier_key === o.modifier_key + && obj.key === o.key + + && obj.modifier_deadkey === o.modifier_deadkey + && obj.deadkey === o.deadkey + + && obj.modifier_prev_deadkey === o.modifier_prev_deadkey + && obj.prev_deadkey === o.prev_deadkey) + ) { + unique.push(o); + } + return unique; + }, []); + //const unique_CAll_Rules: rule_object[] = data_ukelele.ArrayOf_Rules console.log("xx data_ukelele.ArrayOf_Rules", data_ukelele.ArrayOf_Rules.length) - //console.log("xx data_ukelele.ArrayOf_Rules", this.writeDalaset(data_ukelele.ArrayOf_Rules)) + console.log("xx data_ukelele.ArrayOf_Rules", this.writeDataset(data_ukelele.ArrayOf_Rules)) console.log("xx unique_CAll_Rules", unique_CAll_Rules.length) - console.log("xx unique_CAll_Rules", this.writeDalaset(unique_CAll_Rules)) + // console.log("xx unique_CAll_Rules", this.writeDataset(unique_CAll_Rules)) //................................................ C0 C1 ................................................................ //................................................ C0 C1 ................................................................ @@ -2381,7 +2020,8 @@ export class KeylayoutToKmnConverter { // warningtext = warningtext + this.findAmbiguousRules(unique_CAll_Rules, k) // warningtext = warningtext + this.findUnAvailableRule(unique_CAll_Rules, k) - +// add something loke that + return string[] instead of string + //warningtextArray[0] = warningtextArray[0] + this.findUnAvailableRule(unique_CAll_Rules, k) warningtextArray = this.findAmbiguousRules(unique_CAll_Rules, k) // console.log("warningtextArray ", warningtextArray) @@ -2442,9 +2082,6 @@ export class KeylayoutToKmnConverter { // warningtext = warningtext + this.findAmbiguousRules(unique_CAll_Rules, k) // OK //warningtext = warningtext + this.findUnAvailableRule(unique_CAll_Rules, k) // OK - warningtextArray = this.findAmbiguousRules(unique_CAll_Rules, k) - console.log(" warningtextArray", warningtextArray) - // warningtext1 1 unique - warningtext1 2 unique - warningtext1 3 unique @@ -2602,10 +2239,10 @@ export class KeylayoutToKmnConverter { const unique_CAll_Rules: rule_object[] = data_ukelele.ArrayOf_Rules console.log("xx data_ukelele.ArrayOf_Rules", data_ukelele.ArrayOf_Rules.length) - //console.log("xx data_ukelele.ArrayOf_Rules", this.writeDalaset(data_ukelele.ArrayOf_Rules)) + //console.log("xx data_ukelele.ArrayOf_Rules", this.writeDataset(data_ukelele.ArrayOf_Rules)) console.log("xx unique_CAll_Rules", unique_CAll_Rules.length) - console.log("xx unique_CAll_Rules", this.writeDalaset(unique_CAll_Rules)) + // console.log("xx unique_CAll_Rules", this.writeDataset(unique_CAll_Rules)) //................................................ C0 C1 ................................................................ //................................................ C0 C1 ................................................................ @@ -2691,10 +2328,7 @@ export class KeylayoutToKmnConverter { warningtext = warningtext + this.findAmbiguousRules(unique_CAll_Rules, k) warningtext = warningtext + this.findUnAvailableRule(unique_CAll_Rules, k) const warningtextArray: string[] = this.findAmbiguousRules(unique_CAll_Rules, k) - console.log(" warningtextArray", warningtextArray[0], warningtextArray[1], warningtextArray) - - // console.log("warningtext C2", warningtext) // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~ draft print ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -2874,21 +2508,21 @@ export class KeylayoutToKmnConverter { } /// console log all entries C3 TODO remove - public writeDalaset(dataRules: rule_object[]) { + public writeDataset(dataRules: rule_object[]) { for (let i = 0; i < dataRules.length; i++) { console.log("dataRules ", dataRules[i].rule_type !== "" ? dataRules[i].rule_type : "--".padEnd(4, " ") - , dataRules.length, i, + , /*dataRules.length, i,*/ "| ", (dataRules[i].modifier_prev_deadkey !== "" ? dataRules[i].modifier_prev_deadkey.padEnd(33, " ") : "--".padEnd(33, " ")), (dataRules[i].prev_deadkey !== "" ? dataRules[i].prev_deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), - //(dataRules[i].dk_prev !== 0 ? ("dk(A" + String(dataRules[i].dk_prev) + ")").padEnd(11, " ") : "--".padEnd(11, " ")), - //(dataRules[i].uniqueA !== 0 ? ("unique(A" + String(dataRules[i].uniqueA) + ")").padEnd(11, " ") : "--".padEnd(11, " ")), + (dataRules[i].dk_prev !== 0 ? ("dk(A" + String(dataRules[i].dk_prev) + ")").padEnd(11, " ") : "--".padEnd(11, " ")), + (dataRules[i].uniqueA !== 0 ? ("unique(A" + String(dataRules[i].uniqueA) + ")").padEnd(11, " ") : "--".padEnd(11, " ")), - (("dk(A-B-C " + String(dataRules[i].dk_prev) + "-" + String(dataRules[i].dk)).padEnd(9, "-") + (String(dataRules[i].dk_C2) + ")").padEnd(9, " ")), - ("unique(AB " + String(dataRules[i].uniqueA) + "-" + String(dataRules[i].uniqueB) + ")"), + /* (("dk(A-B-C " + String(dataRules[i].dk_prev) + "-" + String(dataRules[i].dk)).padEnd(9, "-") + (String(dataRules[i].dk_C2) + ")").padEnd(9, " ")), + ("unique(AB " + String(dataRules[i].uniqueA) + "-" + String(dataRules[i].uniqueB) + ")"),*/ (dataRules[i].modifier_deadkey !== "" ? dataRules[i].modifier_deadkey.padEnd(30, " ") : "--".padEnd(30, " ")), @@ -2910,7 +2544,7 @@ export class KeylayoutToKmnConverter { } // TODO remove - public writeDalasetSingle(dataRules: rule_object) { + public writeDatasetSingle(dataRules: rule_object) { console.log("dataRules ", dataRules.rule_type !== "" ? dataRules.rule_type : "--".padEnd(4, " ") @@ -2948,7 +2582,7 @@ class Rules { public modifier_deadkey: string, /* second key used by C2,C3 rules*/ public deadkey: string, - public dk: number, //todo remove one + public dk: number, public dk_C2: number, public uniqueB: number, From fe0f4b294c028eb7363ca8a36ddeb48441a6a240 Mon Sep 17 00:00:00 2001 From: Sabine Date: Mon, 17 Feb 2025 18:28:56 +0100 Subject: [PATCH 050/251] feat(developer): kmc-convert new approach ambiguous/duplicate rules C3 OK --- .../keylayout-to-kmn-converter.ts | 801 +++++++++--------- 1 file changed, 377 insertions(+), 424 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 7746bd19137..945b48ae08b 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -73,7 +73,7 @@ import boxXmlArray = util.boxXmlArray;*/ // check uniqueA, uniqueV, dk_prv, dk, dk_C2 // check duplicate rule conditions which do I need; which can go // when I run german with uniqueCAll why will there be [ ] without key anf modifier - + // 77 replace uniqueA 0, >0 with true, false @@ -1504,7 +1504,6 @@ export class KeylayoutToKmnConverter { ) { iskKeymanModifier = iskKeymanModifier && true } else { iskKeymanModifier = iskKeymanModifier && false } } -console.log(" modifier_single",modifier_single, iskKeymanModifier ) return iskKeymanModifier } public findDuplicateRules(rules: rule_object[], index: number, rule_type: string): string { @@ -1550,6 +1549,8 @@ console.log(" modifier_single",modifier_single, iskKeymanModifier ) // filter 1 Text............................................................... if (rule[index].rule_type === "C0" || rule[index].rule_type === "C1") { + this.writeDatasetSingle(rule[index]) + // OK A 1-1 + [CAPS K_N] > 'N' <-> + [CAPS K_N] > 'A' const ambiguous_C0C1_vs_C0C1 = rule.filter((curr, idx) => (curr.rule_type === "C0" || curr.rule_type === "C1") @@ -1562,6 +1563,11 @@ console.log(" modifier_single",modifier_single, iskKeymanModifier ) && new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output) // amb && idx < index ); + if (ambiguous_C0C1_vs_C0C1.length > 0) { + console.log("ambiguous_C0C1_vs_C0C1 ",) + this.writeDataset(ambiguous_C0C1_vs_C0C1) + } + //+ [CAPS K_N] > 'N' <-> + [CAPS K_N] > 'N' const duplicate_C0C1_vs_C0C1 = rule.filter((curr, idx) => (curr.rule_type === "C0" || curr.rule_type === "C1") @@ -1598,7 +1604,7 @@ console.log(" modifier_single",modifier_single, iskKeymanModifier ) // filter 2 Text............................................................... if (rule[index].rule_type === "C2") { - + this.writeDatasetSingle(rule[index]) // 2-2 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(C1) const ambiguous_C2_vs_C2 = rule.filter((curr, idx) => curr.rule_type === "C2" @@ -1607,6 +1613,10 @@ console.log(" modifier_single",modifier_single, iskKeymanModifier ) && (String(curr.dk_C2) !== String(rule[index].dk_C2) || String(curr.dk) !== String(rule[index].dk)) && idx < index ); + /*if (ambiguous_C2_vs_C2.length > 0) { + console.log("2-2 ambiguous_C2_vs_C2 ",) + this.writeDataset(ambiguous_C2_vs_C2) + }*/ //2-2 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(C11) const duplicate_C2_vs_C2 = rule.filter((curr, idx) => @@ -1617,6 +1627,12 @@ console.log(" modifier_single",modifier_single, iskKeymanModifier ) && String(curr.dk) === String(rule[index].dk) // dup && idx < index ); + /*if (duplicate_C2_vs_C2.length > 0) { + console.log("2-2 duplicate_C2_vs_C2 ",) + this.writeDataset(duplicate_C2_vs_C2) + //this.writeDatasetSingle(duplicate_C2_vs_C2[0]) + ///this.writeDatasetSingle(duplicate_C2_vs_C2[1]) + }*/ //3-3 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'B' const ambiguous_C2_vs_C2_B2 = rule.filter((curr, idx) => @@ -1627,8 +1643,11 @@ console.log(" modifier_single",modifier_single, iskKeymanModifier ) && curr.key === rule[index].key && (new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output)) // amb && idx < index - ); - //da stimmt noch was nicht + ); /*if (ambiguous_C2_vs_C2_B2.length > 0) { + console.log("3-3 ambiguous_C2_vs_C2_B2 ",) + this.writeDataset(ambiguous_C2_vs_C2_B2) + }*/ + //da stimmt noch was nicht //3-3 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'Ã' const duplicate_C2_vs_C2_B2 = rule.filter((curr, idx) => (curr.rule_type === "C2") @@ -1638,7 +1657,10 @@ console.log(" modifier_single",modifier_single, iskKeymanModifier ) && curr.key === rule[index].key && new TextDecoder().decode(curr.output) === new TextDecoder().decode(rule[index].output) // dup && idx < index - ); + );/* if (duplicate_C2_vs_C2_B2.length > 0) { + console.log("3-3 duplicate_C2_vs_C2_B2 ",) + this.writeDataset(duplicate_C2_vs_C2_B2) + }*/ //1-2 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > 'Ñ' const ambibguous_C2_vs_C1 = rule.filter((curr, idx) => @@ -1647,7 +1669,10 @@ console.log(" modifier_single",modifier_single, iskKeymanModifier ) && curr.key === rule[index].deadkey //&& rule[index].uniqueB === 0 // without this there will be no warning for first //&& (idx < index) // without this there will be no warning for first - ); + ); /*if (ambibguous_C2_vs_C1.length > 0) { + console.log("1-2 ambibguous_C2_vs_C1 ",) + this.writeDataset(ambibguous_C2_vs_C1) + }*/ if (ambiguous_C2_vs_C2.length > 0) { returnarray[0] = returnarray[0] + ("FIRSTTEXT " + "ambiguous 2-2 rule: earlier: [" + ambiguous_C2_vs_C2[0].modifier_deadkey + " " + ambiguous_C2_vs_C2[0].deadkey + "] > dk(C" + ambiguous_C2_vs_C2[0].dk_C2 + "here: )\'") @@ -1729,8 +1754,8 @@ console.log(" modifier_single",modifier_single, iskKeymanModifier ) && curr.modifier_prev_deadkey === rule[index].modifier_prev_deadkey && curr.prev_deadkey === rule[index].prev_deadkey && (String(curr.dk_prev) === String(rule[index].dk_prev)) - && rule[index].uniqueA !== 0 - && idx < index + /* && rule[index].uniqueA !== 0 + && idx < index*/ ); // 6-6 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'B' @@ -1774,11 +1799,13 @@ console.log(" modifier_single",modifier_single, iskKeymanModifier ) && curr.modifier_key === rule[index].modifier_key && curr.key === rule[index].key && String(curr.dk_C2) === String(rule[index].dk_C2) // no need to convert to string - && String(curr.dk) === String(rule[index].dk) + //&& String(curr.dk) === String(rule[index].dk) && (new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output)) // amb && rule[index].uniqueA !== 0 && idx < index ); + if (ambiguous_C3_vs_C3_B.length > 0) + console.log("ambiguous_C3_vs_C3_B ****************", ambiguous_C3_vs_C3_B) // 5-5 const duplicate_C3_vs_C3_B = rule.filter((curr, idx) => @@ -1792,6 +1819,11 @@ console.log(" modifier_single",modifier_single, iskKeymanModifier ) && idx < index ); + if (duplicate_C3_vs_C3_B.length > 0) { + console.log("duplicate_C3_vs_C3_B ***----*********",) + this.writeDatasetSingle(duplicate_C3_vs_C3_B[0]) + } + if (ambibguous_C3_vs_C1.length > 0) { returnarray[0] = returnarray[0] + ("FIRSTTEXT " + "ambiguous 1-4 rule: earlier: [" + ambibguous_C3_vs_C1[0].modifier_key + " " + ambibguous_C3_vs_C1[0].key + "] > \'" + new TextDecoder().decode(ambibguous_C3_vs_C1[0].output) + "\' here: ") } @@ -1824,39 +1856,287 @@ console.log(" modifier_single",modifier_single, iskKeymanModifier ) } if (ambiguous_C3_vs_C3_B.length > 0) { - returnarray[1] = returnarray[1] + ("THIRDTEXT " + "ambiguous y 5-5 rule: earlier: dk(C" + ambiguous_C3_vs_C3_B[0].dk_C2 + ") + [" + ambiguous_C3_vs_C3_B[0].modifier_key + " " + ambiguous_C3_vs_C3_B[0].key + "] > dk(" + ambiguous_C3_vs_C3_B[0].dk_C2 + ") here: ") + returnarray[1] = returnarray[1] + ("SECONDTEXT " + "ambiguous y 5-5 rule: earlier: dk(C" + ambiguous_C3_vs_C3_B[0].dk_C2 + ") + [" + ambiguous_C3_vs_C3_B[0].modifier_key + " " + ambiguous_C3_vs_C3_B[0].key + "] > dk(" + ambiguous_C3_vs_C3_B[0].dk_C2 + ") here: ") } if (duplicate_C3_vs_C3_B.length > 0) { - returnarray[1] = returnarray[1] + ("THIRDTEXT " + "duplicate y 5-5 rule: earlier: dk(C" + duplicate_C3_vs_C3_B[0].dk_C2 + ") + [" + duplicate_C3_vs_C3_B[0].modifier_key + " " + duplicate_C3_vs_C3_B[0].key + "] > dk(" + duplicate_C3_vs_C3_B[0].dk_C2 + ") here: ") + returnarray[1] = returnarray[1] + ("SECONDTEXT " + "duplicate y 5-5 rule: earlier: dk(C" + duplicate_C3_vs_C3_B[0].dk_C2 + ") + [" + duplicate_C3_vs_C3_B[0].modifier_key + " " + duplicate_C3_vs_C3_B[0].key + "] > dk(" + duplicate_C3_vs_C3_B[0].dk_C2 + ") here: ") } } return returnarray } - public findUnAvailableRule(unique_Rules: rule_object[], index: number): string { - console.log("isAcceptableKeymanModifier ",unique_Rules[index].modifier_key,this.isAcceptableKeymanModifier(unique_Rules[index].modifier_key) ) - if(unique_Rules[index].modifier_key ==="CAPS" ) - console.log("isAcceptableKeymanModifier A",this.isAcceptableKeymanModifier(unique_Rules[index].modifier_key) ) + public findUnAvailableRule(rule: rule_object[], index: number): string[] { + const returnarray: string[] = Array(3).fill(""); + const returnarray_sorted: string[] = Array(3).fill(""); - if ( - (((unique_Rules[index].rule_type === "C0") || (unique_Rules[index].rule_type === "C1") || (unique_Rules[index].rule_type === "C4")) - && (this.isAcceptableKeymanModifier(unique_Rules[index].modifier_key))) + // [0] rules with output 1,3,6 (key) + // [1] middle part 2,5 (dk) + // [2] lwft part 4 (prev_dk) - || (unique_Rules[index].rule_type === "C2" - && ((this.isAcceptableKeymanModifier(unique_Rules[index].modifier_deadkey)) - && (this.isAcceptableKeymanModifier(unique_Rules[index].modifier_key))) - ) + // console.log("isAcceptableKeymanModifier check 0", this.isAcceptableKeymanModifier(rule[index].modifier_key), rule[index].modifier_key) + // console.log("isAcceptableKeymanModifier check 1", this.isAcceptableKeymanModifier(rule[index].modifier_deadkey), rule[index].modifier_deadkey) + // console.log("isAcceptableKeymanModifier check 2", this.isAcceptableKeymanModifier(rule[index].modifier_prev_deadkey), rule[index].modifier_prev_deadkey) - || (unique_Rules[index].rule_type === "C3" - && ((this.isAcceptableKeymanModifier((unique_Rules[index].modifier_prev_deadkey))) - && (this.isAcceptableKeymanModifier((unique_Rules[index].modifier_deadkey))) - && (this.isAcceptableKeymanModifier((unique_Rules[index].modifier_key)))) - ) - ) - return "" - return ("unavailable modifier in: ") + + if (((rule[index].rule_type === "C0") || (rule[index].rule_type === "C1") || (rule[index].rule_type === "C4")) + && (!(this.isAcceptableKeymanModifier(rule[index].modifier_key)))) { + returnarray[1] = "unavailable modifier in: " + returnarray_sorted[0] = "unavailable modifier in: " + } + + else if + ((rule[index].rule_type === "C2" + && (!(this.isAcceptableKeymanModifier(rule[index].modifier_deadkey))))) { + returnarray[1] = "unavailable A modifier in: " + returnarray_sorted[1] = "unavailable modifier in: " + } + else if ((rule[index].rule_type === "C2") + && (!(this.isAcceptableKeymanModifier(rule[index].modifier_key)))) { + returnarray[0] = "unavailable B modifier in: " + returnarray_sorted[0] = "unavailable modifier in: " + } + + + else if ((rule[index].rule_type === "C3") + && (!(this.isAcceptableKeymanModifier(rule[index].modifier_prev_deadkey)))) { + returnarray[0] = "" + returnarray_sorted[2] = "" + } + else if ((rule[index].rule_type === "C3") + && (!(this.isAcceptableKeymanModifier((rule[index].modifier_deadkey))))) { + returnarray[1] = "" + returnarray_sorted[1] = "" + } + else if ((rule[index].rule_type === "C3") + && (!(this.isAcceptableKeymanModifier(rule[index].modifier_key)))) { + returnarray[2] = "" + returnarray_sorted[0] = "" + } + + + /* console.log("resultttt ", + (returnarray_sorted[0] === "" && returnarray_sorted[1] === "" && returnarray_sorted[2] === ""), + rule[index].rule_type, + rule[index].modifier_key, + rule[index].modifier_deadkey, + rule[index].modifier_prev_deadkey, + "--", + returnarray, + "--", + returnarray_sorted)*/ + + return returnarray_sorted + return returnarray } + public reviewRules(rule: rule_object[], index: number): string[] { + const returnarray_sorted: string[] = Array(3).fill(""); + + // [0] rules with output 1,3,6 (key) + // [1] middle part 2,5 (dk) + // [2] lwft part 4 (prev_dk) + + // +++++++++++++++++++++++++ first unavailable rules ++++++++++++++++++++++++++++++++++++++ + console.log("reviewRules isAcceptableKeymanModifier check 0 ", this.isAcceptableKeymanModifier(rule[index].modifier_key), rule[index].modifier_key) + console.log("reviewRules isAcceptableKeymanModifier check 1", this.isAcceptableKeymanModifier(rule[index].modifier_deadkey), rule[index].modifier_deadkey) + console.log("reviewRules isAcceptableKeymanModifier check 2", this.isAcceptableKeymanModifier(rule[index].modifier_prev_deadkey), rule[index].modifier_prev_deadkey) + + /* + if (((rule[index].rule_type === "C0") || (rule[index].rule_type === "C1") || (rule[index].rule_type === "C4")) + && (!(this.isAcceptableKeymanModifier(rule[index].modifier_key)))) { + returnarray[1] = "unavailable modifier in: " + returnarray_sorted[0] = "unavailable modifier in: " + } + + else if + ((rule[index].rule_type === "C2" + && (!(this.isAcceptableKeymanModifier(rule[index].modifier_deadkey))))) { + returnarray[1] = "unavailable A modifier in: " + returnarray_sorted[1] = "unavailable modifier in: " + + } + else if ((rule[index].rule_type === "C2") + && (!(this.isAcceptableKeymanModifier(rule[index].modifier_key)))) { + returnarray[0] = "unavailable B modifier in: " + returnarray_sorted[0] = "unavailable modifier in: " + } + */ + + if (rule[index].rule_type === "C3") { + + if (!(this.isAcceptableKeymanModifier(rule[index].modifier_prev_deadkey))) { + returnarray_sorted[2] = "unavailable modifier in: " + } + + if (!(this.isAcceptableKeymanModifier(rule[index].modifier_deadkey))) { + returnarray_sorted[1] = "unavailable modifier in: " + } + + if (!(this.isAcceptableKeymanModifier(rule[index].modifier_key))) { + returnarray_sorted[0] = "unavailable modifier in: " + } + } + // +++++++++++++++++++++++++ then ambiguous/duplicate rules ++++++++++++++++++++++++++++++++++++++ + + if (rule[index].rule_type === "C3") { + + // 1-4 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > 'Ñ' + const ambibguous_C3_vs_C1 = rule.filter((curr, idx) => + ((curr.rule_type === "C0") || (curr.rule_type === "C1")) + && curr.modifier_key === rule[index].modifier_prev_deadkey + && curr.key === rule[index].prev_deadkey + //&& rule[index].uniqueA === 0 // without this there will be no warning + //&& (idx < index) + ); + + // 2-4 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(C1) + const ambibguous_C3_vs_C2_B = rule.filter((curr, idx) => + ((curr.rule_type === "C2")) + && curr.modifier_deadkey === rule[index].modifier_prev_deadkey + && curr.deadkey === rule[index].prev_deadkey + && String(curr.dk_C2) === String(rule[index].dk_prev) // dup + // && rule[index].uniqueA === 0 // without this there will be no warning + //&& (idx < index) + ); + + // 6-3 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'B' + const ambiguous_C3_vs_C2_B2 = rule.filter((curr, idx) => + (curr.rule_type === "C2") + && String(curr.dk_prev) === String(rule[index].dk_prev) // amb + && curr.modifier_key === rule[index].modifier_key + && curr.key === rule[index].key + && (new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output)) // amb + // && rule[index].uniqueB !== 0 + // && idx < index + ); + + // 6-3 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'Ã' + const duplicate_C3_vs_C2_B2 = rule.filter((curr, idx) => + (curr.rule_type === "C2") + && String(curr.dk_prev) === String(rule[index].dk_prev) // dup + && curr.modifier_key === rule[index].modifier_key + && curr.key === rule[index].key + && new TextDecoder().decode(curr.output) === new TextDecoder().decode(rule[index].output) // dup + // && rule[index].uniqueB === 0 + // && idx < index + ); + + // 4-4 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > 'dk(C1)' + const ambiguous_C3_vs_C3 = rule.filter((curr, idx) => + curr.rule_type === "C3" + && curr.modifier_prev_deadkey === rule[index].modifier_prev_deadkey + && (String(curr.dk_prev) !== String(rule[index].dk_prev)) + && curr.prev_deadkey === rule[index].prev_deadkey + && rule[index].uniqueA !== 0 + && idx < index + ); + + // 4-4 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(C11) + const duplicate_C3_vs_C3 = rule.filter((curr, idx) => + curr.rule_type === "C3" + && curr.modifier_prev_deadkey === rule[index].modifier_prev_deadkey + && curr.prev_deadkey === rule[index].prev_deadkey + && (String(curr.dk_prev) === String(rule[index].dk_prev)) + // && rule[index].uniqueA !== 0 + && idx < index + ); + + // 6-6 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'B' + const ambiguous_C3_vs_C3_C = rule.filter((curr, idx) => + (curr.rule_type === "C3") + && String(curr.dk_C2) === String(rule[index].dk_C2) // no need to convert to string + && rule[index].uniqueA !== 0 + && String(curr.dk) === String(rule[index].dk) + && curr.modifier_key === rule[index].modifier_key + && curr.key === rule[index].key + && (new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output)) // amb + + && idx < index + ); + + // 6-6 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'Ã' + const duplicate_C3_vs_C3_C = rule.filter((curr, idx) => + (curr.rule_type === "C3") + && String(curr.dk_C2) === String(rule[index].dk_C2) + && curr.modifier_key === rule[index].modifier_key + && curr.key === rule[index].key + && (new TextDecoder().decode(curr.output) === new TextDecoder().decode(rule[index].output)) // dup + && idx < index + ); + + // 5-5 + const ambiguous_C3_vs_C3_B = rule.filter((curr, idx) => + (curr.rule_type === "C3") + && curr.modifier_key === rule[index].modifier_key + && curr.key === rule[index].key + && String(curr.dk_C2) === String(rule[index].dk_C2) // no need to convert to string + //&& String(curr.dk) === String(rule[index].dk) + && (new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output)) // amb + //&& rule[index].uniqueA !== 0 + && idx < index + ); + // 5-5 + const duplicate_C3_vs_C3_B = rule.filter((curr, idx) => + (curr.rule_type === "C3") + && curr.modifier_deadkey === rule[index].modifier_deadkey + && curr.deadkey === rule[index].deadkey + && String(curr.dk_prev) === String(rule[index].dk_prev) // no need to convert to string + && String(curr.dk_C2) === String(rule[index].dk_C2) // no need to convert to string + && String(curr.dk) === String(rule[index].dk) + && rule[index].uniqueB === 0 + //&& idx < index + ); + + if (ambiguous_C3_vs_C3_C.length > 0) { + returnarray_sorted[2] = returnarray_sorted[2] + ("THIRDTEXT " + "ambiguous y 6-6 rule: earlier: dk(B" + ambiguous_C3_vs_C3_C[0].dk_C2 + ") + [" + ambiguous_C3_vs_C3_C[0].modifier_key + " " + ambiguous_C3_vs_C3_C[0].key + "] > \'" + new TextDecoder().decode(ambiguous_C3_vs_C3_C[0].output) + "\' here: ") + } + + if (duplicate_C3_vs_C3_C.length > 0) { + returnarray_sorted[2] = returnarray_sorted[2] + ("THIRDTEXT " + "duplicate y 6-6x rule: earlier: dk(B" + duplicate_C3_vs_C3_C[0].dk_C2 + ") + [" + duplicate_C3_vs_C3_C[0].modifier_key + " " + duplicate_C3_vs_C3_C[0].key + "] > \'" + new TextDecoder().decode(duplicate_C3_vs_C3_C[0].output) + "\' here: ") + + } + if (ambibguous_C3_vs_C1.length > 0) { + returnarray_sorted[0] = returnarray_sorted[0] + ("FIRSTTEXT " + "ambiguous 1-4 rule: earlier(Todo check if print out or not): [" + ambibguous_C3_vs_C1[0].modifier_key + " " + ambibguous_C3_vs_C1[0].key + "] > \'" + new TextDecoder().decode(ambibguous_C3_vs_C1[0].output) + "\' here: ") + } + + if (ambibguous_C3_vs_C2_B.length > 0) { + returnarray_sorted[0] = returnarray_sorted[0] + ("FIRSTTEXT " + "ambiguous 2-4 rule: earlier(Todo check if print out or not): [" + ambibguous_C3_vs_C2_B[0].modifier_deadkey + " " + ambibguous_C3_vs_C2_B[0].deadkey + "] > dk(C" + ambibguous_C3_vs_C2_B[0].dk_C2 + ") here: )\'") + } + + if (ambiguous_C3_vs_C2_B2.length > 0) { + returnarray_sorted[1] = returnarray_sorted[1] + ("SECONDTEXT " + "ambiguous y 6-3 rule: earlier: dk(C" + ambiguous_C3_vs_C2_B2[0].dk_C2 + ") + [" + ambiguous_C3_vs_C2_B2[0].modifier_key + " " + ambiguous_C3_vs_C2_B2[0].key + "] > \'" + new TextDecoder().decode(ambiguous_C3_vs_C2_B2[0].output) + "\' here: ") + } + + if (duplicate_C3_vs_C2_B2.length > 0) { + returnarray_sorted[1] = returnarray_sorted[1] + ("SECONDTEXT " + "duplicate y 6-3 rule: earlier: dk(C" + duplicate_C3_vs_C2_B2[0].dk_C2 + ") + [" + duplicate_C3_vs_C2_B2[0].modifier_key + " " + duplicate_C3_vs_C2_B2[0].key + "] > \'" + new TextDecoder().decode(duplicate_C3_vs_C2_B2[0].output) + "\' here: ") + } + + if (ambiguous_C3_vs_C3.length > 0) { + returnarray_sorted[0] = returnarray_sorted[0] + ("FIRSTTEXT " + "ambiguous 4-4 rule: earlier: [" + ambiguous_C3_vs_C3[0].modifier_deadkey + " " + ambiguous_C3_vs_C3[0].deadkey + "] > dk(C" + ambiguous_C3_vs_C3[0].dk_C2 + "here: )\'") + } + + if (duplicate_C3_vs_C3.length > 0) { + returnarray_sorted[0] = returnarray_sorted[0] + ("FIRSTTEXT " + "duplicate 4-4 rule: earlier: [" + duplicate_C3_vs_C3[0].modifier_deadkey + " " + duplicate_C3_vs_C3[0].deadkey + "] > dk(C" + duplicate_C3_vs_C3[0].dk_C2 + "here: )\'") + } + + if (ambiguous_C3_vs_C3_B.length > 0) { + returnarray_sorted[1] = returnarray_sorted[1] + ("SECONDTEXT " + "ambiguous y 5-5 rule: earlier: dk(C" + ambiguous_C3_vs_C3_B[0].dk_C2 + ") + [" + ambiguous_C3_vs_C3_B[0].modifier_key + " " + ambiguous_C3_vs_C3_B[0].key + "] > dk(" + ambiguous_C3_vs_C3_B[0].dk_C2 + ") here: ") + } + + if (duplicate_C3_vs_C3_B.length > 0) { + returnarray_sorted[1] = returnarray_sorted[1] + ("SECONDTEXT " + "duplicate y 5-5 rule: earlier: dk(C" + duplicate_C3_vs_C3_B[0].dk_C2 + ") + [" + duplicate_C3_vs_C3_B[0].modifier_key + " " + duplicate_C3_vs_C3_B[0].key + "] > dk(" + duplicate_C3_vs_C3_B[0].dk_C2 + ") here: ") + } + } + + if (returnarray_sorted[0] !== "") returnarray_sorted[0] = "c WARNING C3 " + returnarray_sorted[0] + if (returnarray_sorted[1] !== "") returnarray_sorted[1] = "c WARNING C3 " + returnarray_sorted[1] + if (returnarray_sorted[2] !== "") returnarray_sorted[2] = "c WARNING C3 " + returnarray_sorted[2] + + return returnarray_sorted + } + + + /** * @brief member function to map Ukelele keycodes to a Windows Keycodes * @param pos Ukelele (=mac) keycodes @@ -1929,7 +2209,6 @@ console.log(" modifier_single",modifier_single, iskKeymanModifier ) public createData_Rules(data_ukelele: convert_object): string { let warningtextArray: string[] = Array(3).fill(""); - //console.log("warningtextArray ", warningtextArray) const maxkey: number = 50 let data: string = "" @@ -1990,18 +2269,22 @@ console.log(" modifier_single",modifier_single, iskKeymanModifier ) if (unique_CAll_Rules[i].key !== keymarker) data += '\n' //--------------------------------------------------------------------------------------------- + const ambiq_Array: string[] = this.findAmbiguousRules(unique_CAll_Rules, i) + const unav_Array: string[] = this.findUnAvailableRule(unique_CAll_Rules, i) + const new_WarningTextArray: string[] = Array(3).fill(""); - warningtextArray = this.findAmbiguousRules(unique_CAll_Rules, i) - // todo return string[] of findUnAvailableRule - warningtextArray[0] = warningtextArray[0] + this.findUnAvailableRule(unique_CAll_Rules, i) + + new_WarningTextArray[0] = ambiq_Array[0] + unav_Array[0] + new_WarningTextArray[1] = ambiq_Array[1] + unav_Array[1] + new_WarningTextArray[2] = ambiq_Array[2] + unav_Array[2] if (new TextDecoder().decode(unique_CAll_Rules[i].output) !== "") { // if no warning - if (warningtextArray[0] === "") + if (new_WarningTextArray[0] === "") data += "+ [" + (unique_CAll_Rules[i].modifier_key + ' ' + unique_CAll_Rules[i].key).trim() + `] > \'` + new TextDecoder().decode(unique_CAll_Rules[i].output) + '\'\n' else // if warning available - data += "c C0 WARNING: " + warningtextArray[0] + (unique_CAll_Rules[i].modifier_key + ' ' + unique_CAll_Rules[i].key).trim() + `] > \'` + new TextDecoder().decode(unique_CAll_Rules[i].output) + '\'\n' + data += "c C0 WARNING: " + new_WarningTextArray[0] + (unique_CAll_Rules[i].modifier_key + ' ' + unique_CAll_Rules[i].key).trim() + `] > \'` + new TextDecoder().decode(unique_CAll_Rules[i].output) + '\'\n' } keymarker = unique_CAll_Rules[i].key } @@ -2015,15 +2298,21 @@ console.log(" modifier_single",modifier_single, iskKeymanModifier ) if (unique_CAll_Rules[k].rule_type === "C2") { - // todo - //warningtext = warningtext + this.findDuplicateRules(unique_CAll_Rules, k, "C2") - // warningtext = warningtext + this.findAmbiguousRules(unique_CAll_Rules, k) - // warningtext = warningtext + this.findUnAvailableRule(unique_CAll_Rules, k) - -// add something loke that + return string[] instead of string - //warningtextArray[0] = warningtextArray[0] + this.findUnAvailableRule(unique_CAll_Rules, k) warningtextArray = this.findAmbiguousRules(unique_CAll_Rules, k) - // console.log("warningtextArray ", warningtextArray) + + const ambiq_Array: string[] = this.findAmbiguousRules(unique_CAll_Rules, k) + const unav_Array: string[] = this.findUnAvailableRule(unique_CAll_Rules, k) + const new_WarningTextArray: string[] = Array(3).fill(""); + + new_WarningTextArray[0] = ambiq_Array[0] + unav_Array[0] + new_WarningTextArray[1] = ambiq_Array[1] + unav_Array[1] + new_WarningTextArray[2] = ambiq_Array[2] + unav_Array[2] + // console.log("new_WarningTextArray after", new_WarningTextArray) + + // swap todo remove + warningtextArray[0] = ambiq_Array[1] + unav_Array[1] + warningtextArray[1] = ambiq_Array[0] + unav_Array[0] + warningtextArray[2] = ambiq_Array[2] + unav_Array[2] // unique First unique second if ((warningtextArray[0] === "") && (warningtextArray[1] === "")) { @@ -2033,33 +2322,38 @@ console.log(" modifier_single",modifier_single, iskKeymanModifier ) data += "dk(C" + String(unique_CAll_Rules[k].dk_C2) + ") + [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'\n" } + if ((new_WarningTextArray[0] !== "") && (new_WarningTextArray[1] === "")) { + console.log("cond MET ",) - // dup First unique second - if ((warningtextArray[0] !== "") && (warningtextArray[1] === "")) { if (unique_CAll_Rules[k].uniqueB !== 0) { - data += "C WARNING C2 xx" + warningtextArray[0] + "+ [" + unique_CAll_Rules[k].modifier_deadkey + " " + unique_CAll_Rules[k].deadkey + "] > dk(C" + String(unique_CAll_Rules[k].dk_C2) + ")\n" + data += "C WARNING C2 xx" + new_WarningTextArray[0] + "+ [" + unique_CAll_Rules[k].modifier_deadkey + " " + unique_CAll_Rules[k].deadkey + "] > dk(C" + String(unique_CAll_Rules[k].dk_C2) + ")\n" } + // if (unique_CAll_Rules[k].uniqueB !== 0) { data += "dk(C" + String(unique_CAll_Rules[k].dk_C2) + ") + [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'\n" + // } + data += "\n" + continue } - // unique First dup second - if ((warningtextArray[0] === "") && (warningtextArray[1] !== "")) { - if (unique_CAll_Rules[k].uniqueB !== 0) { - data += "+ [" + unique_CAll_Rules[k].modifier_deadkey + " " + unique_CAll_Rules[k].deadkey + "] > dk(C" + String(unique_CAll_Rules[k].dk_C2) + ")\n" - } + if ((new_WarningTextArray[0] === "") && (new_WarningTextArray[1] !== "")) { + console.log("I am here with: ") + + // if (unique_CAll_Rules[k].uniqueB !== 0) { + data += "C WARNING C2 yy 0" + new_WarningTextArray[1] + "+ [" + unique_CAll_Rules[k].modifier_deadkey + " " + unique_CAll_Rules[k].deadkey + "] > dk(C" + String(unique_CAll_Rules[k].dk_C2) + ")\n" + // } if (unique_CAll_Rules[k].uniqueB !== 0) { - data += "C WARNING C2 yy" + warningtextArray[1] + "dk(C" + String(unique_CAll_Rules[k].dk_C2) + ") + [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'\n" + data += "dk(C" + String(unique_CAll_Rules[k].dk_C2) + ") + [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'\n" } + continue } + if ((new_WarningTextArray[1] !== "") && (new_WarningTextArray[0] !== "")) { - // dup First dup second - if ((warningtextArray[0] !== "") && (warningtextArray[1] !== "")) { if (unique_CAll_Rules[k].uniqueB !== 0) { - data += "C WARNING C2 xx" + warningtextArray[0] + "+ [" + unique_CAll_Rules[k].modifier_deadkey + " " + unique_CAll_Rules[k].deadkey + "] > dk(C" + String(unique_CAll_Rules[k].dk_C2) + ")\n" + data += "C WARNING C2 xx 1" + new_WarningTextArray[1] + "+ [" + unique_CAll_Rules[k].modifier_deadkey + " " + unique_CAll_Rules[k].deadkey + "] > dk(C" + String(unique_CAll_Rules[k].dk_C2) + ")\n" } if (unique_CAll_Rules[k].uniqueB !== 0) { - data += "C WARNING C2 yy" + warningtextArray[1] + "dk(C" + String(unique_CAll_Rules[k].dk_C2) + ") + [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'\n" + data += "C WARNING C2 yy 1" + new_WarningTextArray[0] + "dk(C" + String(unique_CAll_Rules[k].dk_C2) + ") + [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'\n" } } data += "\n" @@ -2072,388 +2366,43 @@ console.log(" modifier_single",modifier_single, iskKeymanModifier ) data += "\nc ########## C3 #################################################################\n" - for (let k = 0; k < unique_CAll_Rules.length; k++) { - if (unique_CAll_Rules[k].rule_type === "C3") { - // const warningtext: string = "c C3 WARNING: " - // warningtext = warningtext + this.findDuplicateRules(unique_CAll_Rules, k, "C3") // OK - // warningtext = warningtext + this.findAmbiguousRules(unique_CAll_Rules, k) // OK - //warningtext = warningtext + this.findUnAvailableRule(unique_CAll_Rules, k) // OK - - - - // warningtext1 1 unique - warningtext1 2 unique - warningtext1 3 unique - if ((warningtextArray[0] === "") && (warningtextArray[1] === "") && (warningtextArray[2] === "")) { - if (unique_CAll_Rules[k].uniqueA !== 0) { - data += "+ [" + unique_CAll_Rules[k].modifier_prev_deadkey + " " + unique_CAll_Rules[k].prev_deadkey + "] > dk(A" + String(unique_CAll_Rules[k].dk_prev) + ")\n" - } - if ((unique_CAll_Rules[k].uniqueB !== 0) && (unique_CAll_Rules[k].uniqueA !== 0)) { - data += "dk(A" + String(unique_CAll_Rules[k].dk_prev) + ") + [" + unique_CAll_Rules[k].modifier_deadkey + " " + unique_CAll_Rules[k].deadkey + "] > dk(B" + String(unique_CAll_Rules[k].dk_C2) + ")\n" - } - data += "dk(B" + String(unique_CAll_Rules[k].dk_C2) + ") + [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'\n" - data += "\n" - } - //-----------------------------------OK - - - // warningtext1 1 dup - warningtext1 2 unique - warningtext1 3 unique - if ((warningtextArray[0] !== "") && (warningtextArray[1] === "") && (warningtextArray[2] === "")) { - if (unique_CAll_Rules[k].uniqueA !== 0) { - data += "C WARNING C3 xx A" + warningtextArray[0] + "+ [" + unique_CAll_Rules[k].modifier_prev_deadkey + " " + unique_CAll_Rules[k].prev_deadkey + "] > dk(A" + String(unique_CAll_Rules[k].dk_prev) + ")\n" - } - if ((unique_CAll_Rules[k].uniqueB !== 0) && (unique_CAll_Rules[k].uniqueA !== 0)) { - data += "dk(A" + String(unique_CAll_Rules[k].dk_prev) + ") + [" + unique_CAll_Rules[k].modifier_deadkey + " " + unique_CAll_Rules[k].deadkey + "] > dk(B" + String(unique_CAll_Rules[k].dk_C2) + ")\n" - } - data += "dk(B" + String(unique_CAll_Rules[k].dk_C2) + ") + [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'\n" - data += "\n" - } - // warningtext1 1 unique - warningtext1 2 dup - warningtext1 3 unique - if ((warningtextArray[0] === "") && (warningtextArray[1] !== "") && (warningtextArray[2] === "")) { - if (unique_CAll_Rules[k].uniqueA !== 0) { - data += "C WARNING C3 xx B" + warningtextArray[0] + "+ [" + unique_CAll_Rules[k].modifier_prev_deadkey + " " + unique_CAll_Rules[k].prev_deadkey + "] > dk(A" + String(unique_CAll_Rules[k].dk_prev) + ")\n" - } - if ((unique_CAll_Rules[k].uniqueB !== 0) && (unique_CAll_Rules[k].uniqueA !== 0)) { - data += "C WARNING C3 yy" + warningtextArray[1] + "dk(A" + String(unique_CAll_Rules[k].dk_prev) + ") + [" + unique_CAll_Rules[k].modifier_deadkey + " " + unique_CAll_Rules[k].deadkey + "] > dk(B" + String(unique_CAll_Rules[k].dk_C2) + ")\n" - } - data += "dk(B" + String(unique_CAll_Rules[k].dk_C2) + ") + [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'\n" - data += "\n" - } - // warningtext1 1 dup - warningtext1 2 dup - warningtext1 3 unique - if ((warningtextArray[0] !== "") && (warningtextArray[1] !== "") && (warningtextArray[2] === "")) { - if (unique_CAll_Rules[k].uniqueA !== 0) { - data += "C WARNING C3 xx C" + warningtextArray[0] + "+ [" + unique_CAll_Rules[k].modifier_prev_deadkey + " " + unique_CAll_Rules[k].prev_deadkey + "] > dk(A" + String(unique_CAll_Rules[k].dk_prev) + ")\n" - } - if ((unique_CAll_Rules[k].uniqueB !== 0) && (unique_CAll_Rules[k].uniqueA !== 0)) { - data += "C WARNING C3 yy" + warningtextArray[1] + "dk(A" + String(unique_CAll_Rules[k].dk_prev) + ") + [" + unique_CAll_Rules[k].modifier_deadkey + " " + unique_CAll_Rules[k].deadkey + "] > dk(B" + String(unique_CAll_Rules[k].dk_C2) + ")\n" - } - data += "dk(B" + String(unique_CAll_Rules[k].dk_C2) + ") + [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'\n" - data += "\n" - } - // warningtext1 1 unique - warningtext1 2 unique - warningtext1 3 dup - if ((warningtextArray[0] === "") && (warningtextArray[1] === "") && (warningtextArray[2] !== "")) { - if (unique_CAll_Rules[k].uniqueA !== 0) { - data += "+ [" + unique_CAll_Rules[k].modifier_prev_deadkey + " " + unique_CAll_Rules[k].prev_deadkey + "] > dk(A" + String(unique_CAll_Rules[k].dk_prev) + ")\n" - } - if ((unique_CAll_Rules[k].uniqueB !== 0) && (unique_CAll_Rules[k].uniqueA !== 0)) { - data += "dk(A" + String(unique_CAll_Rules[k].dk_prev) + ") + [" + unique_CAll_Rules[k].modifier_deadkey + " " + unique_CAll_Rules[k].deadkey + "] > dk(B" + String(unique_CAll_Rules[k].dk_C2) + ")\n" - } - data += "C WARNING C3 yy" + warningtextArray[2] + "dk(B" + String(unique_CAll_Rules[k].dk_C2) + ") + [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'\n" - data += "\n" - } - // warningtext1 1 dup - warningtext1 2 unique - warningtext1 3 dup - if ((warningtextArray[0] !== "") && (warningtextArray[1] === "") && (warningtextArray[2] !== "")) { - if (unique_CAll_Rules[k].uniqueA !== 0) { - data += "C WARNING C3 xx" + warningtextArray[0] + "+ [" + unique_CAll_Rules[k].modifier_prev_deadkey + " " + unique_CAll_Rules[k].prev_deadkey + "] > dk(A" + String(unique_CAll_Rules[k].dk_prev) + ")\n" - } - if ((unique_CAll_Rules[k].uniqueB !== 0) && (unique_CAll_Rules[k].uniqueA !== 0)) { - data += "dk(A" + String(unique_CAll_Rules[k].dk_prev) + ") + [" + unique_CAll_Rules[k].modifier_deadkey + " " + unique_CAll_Rules[k].deadkey + "] > dk(B" + String(unique_CAll_Rules[k].dk_C2) + ")\n" - } - data += "C WARNING C3 yy" + warningtextArray[2] + "dk(B" + String(unique_CAll_Rules[k].dk_C2) + ") + [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'\n" - data += "\n" - } - // warningtext1 1 unique - warningtext1 2 dup - warningtext1 3 dup - if ((warningtextArray[0] === "") && (warningtextArray[1] !== "") && (warningtextArray[2] !== "")) { - if (unique_CAll_Rules[k].uniqueA !== 0) { - data += "+ [" + unique_CAll_Rules[k].modifier_prev_deadkey + " " + unique_CAll_Rules[k].prev_deadkey + "] > dk(A" + String(unique_CAll_Rules[k].dk_prev) + ")\n" - } - if ((unique_CAll_Rules[k].uniqueB !== 0) && (unique_CAll_Rules[k].uniqueA !== 0)) { - data += "C WARNING C3 yy" + warningtextArray[1] + "dk(A" + String(unique_CAll_Rules[k].dk_prev) + ") + [" + unique_CAll_Rules[k].modifier_deadkey + " " + unique_CAll_Rules[k].deadkey + "] > dk(B" + String(unique_CAll_Rules[k].dk_C2) + ")\n" - } - data += "C WARNING C3 yy" + warningtextArray[2] + "dk(B" + String(unique_CAll_Rules[k].dk_C2) + ") + [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'\n" - data += "\n" - } - // warningtext1 1 dup - warningtext1 2 dup - warningtext1 3 dup - if ((warningtextArray[0] !== "") && (warningtextArray[1] !== "") && (warningtextArray[2] !== "")) { - if (unique_CAll_Rules[k].uniqueA !== 0) { - data += "C WARNING C3 yy" + warningtextArray[1] + "C WARNING C2 xx" + warningtextArray[0] + "+ [" + unique_CAll_Rules[k].modifier_prev_deadkey + " " + unique_CAll_Rules[k].prev_deadkey + "] > dk(A" + String(unique_CAll_Rules[k].dk_prev) + ")\n" - } - if ((unique_CAll_Rules[k].uniqueB !== 0) && (unique_CAll_Rules[k].uniqueA !== 0)) { - data += "dk(A" + String(unique_CAll_Rules[k].dk_prev) + ") + [" + unique_CAll_Rules[k].modifier_deadkey + " " + unique_CAll_Rules[k].deadkey + "] > dk(B" + String(unique_CAll_Rules[k].dk_C2) + ")\n" - } - data += "C WARNING C3 yy" + warningtextArray[2] + "dk(B" + String(unique_CAll_Rules[k].dk_C2) + ") + [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'\n" - data += "\n" - } - - /* if (warningtext === "c C3 WARNING: ") { - - if (unique_CAll_Rules[k].uniqueA !== 0) { - data += "+ [" + unique_CAll_Rules[k].modifier_prev_deadkey + " " + unique_CAll_Rules[k].prev_deadkey + "] > dk(A" + String(unique_CAll_Rules[k].dk_prev) + ")\n" - } - - if ((unique_CAll_Rules[k].uniqueB !== 0) && (unique_CAll_Rules[k].uniqueA !== 0)) { - data += "dk(A" + String(unique_CAll_Rules[k].dk_prev) + ") + [" + unique_CAll_Rules[k].modifier_deadkey + " " + unique_CAll_Rules[k].deadkey + "] > dk(B" + String(unique_CAll_Rules[k].dk) + ")\n" - } - - data += "dk(B" + String(unique_CAll_Rules[k].dk) + ") + [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'\n" - data += "\n" - } - - else { - data += warningtext + unique_CAll_Rules[k].modifier_prev_deadkey + " " + unique_CAll_Rules[k].prev_deadkey + "] > dk(A" + String(unique_CAll_Rules[k].dk_prev) + ")\n" - data += "dk(A" + String(unique_CAll_Rules[k].dk_prev) + ") + [" + unique_CAll_Rules[k].modifier_deadkey + " " + unique_CAll_Rules[k].deadkey + "] > dk(B" + String(unique_CAll_Rules[k].dk) + ")\n" - data += "dk(B" + String(unique_CAll_Rules[k].dk) + ") + [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'\n" - }*/ - - data += "\n" - } - } - - data += '\n' - return data - } - - public createData_Rules_old(data_ukelele: convert_object): string { - - const maxkey: number = 50 - let data: string = "" - let keymarker: string = "" - /* - const data_CAll: rule_object[] = data_ukelele.ArrayOf_Rules.filter((curr) => { - if ((curr.output !== new TextEncoder().encode("") || curr.output !== undefined) - && (curr.rule_type === "C0") || (curr.rule_type === "C1") || (curr.rule_type === "C2") || (curr.rule_type === "C3")) { - return curr; - } - else return "" - }); - const unique_CAll_Rules: rule_object[] = data_CAll.reduce((unique, o) => { - if (!unique.some((obj: { output: Uint8Array; rule_type: string; modifier_key: string; modifier_deadkey: string; prev_deadkey: string; modifier_prev_deadkey: string; deadkey: string; key: string }) => - new TextDecoder().decode(obj.output) === new TextDecoder().decode(o.output) - - && obj.rule_type === o.rule_type - && obj.modifier_key === o.modifier_key - && obj.key === o.key - - && obj.modifier_deadkey === o.modifier_deadkey - && obj.deadkey === o.deadkey - - && obj.modifier_prev_deadkey === o.modifier_prev_deadkey - && obj.prev_deadkey === o.prev_deadkey) - ) { - unique.push(o); - } - return unique; - }, []);*/ - const unique_CAll_Rules: rule_object[] = data_ukelele.ArrayOf_Rules - - console.log("xx data_ukelele.ArrayOf_Rules", data_ukelele.ArrayOf_Rules.length) - //console.log("xx data_ukelele.ArrayOf_Rules", this.writeDataset(data_ukelele.ArrayOf_Rules)) - - console.log("xx unique_CAll_Rules", unique_CAll_Rules.length) - // console.log("xx unique_CAll_Rules", this.writeDataset(unique_CAll_Rules)) - - //................................................ C0 C1 ................................................................ - //................................................ C0 C1 ................................................................ - //................................................ C0 C1 ................................................................ + const warn_text = this.reviewRules(unique_CAll_Rules, k) - for (let i = 0; i < unique_CAll_Rules.length; i++) { + /*console.log("warn_text[0] ", warn_text[0], warn_text[0].indexOf("duplicate")) + console.log("warn_text[1] ", warn_text[1], warn_text[1].indexOf("duplicate")) + console.log("warn_text[2] ", warn_text[2], warn_text[2].indexOf("duplicate"))*/ - if ((unique_CAll_Rules[i].rule_type === "C0") || (unique_CAll_Rules[i].rule_type === "C1")) { - // lookup key nr of the key that is being processed - let keyNr: number = 0; - for (let j = 0; j < maxkey; j++) { - if (this.map_UkeleleKC_To_VK(j) === unique_CAll_Rules[i].key) - keyNr = j + // just print out what's in the array + // FIRSTTEXT print + if ((warn_text[0].indexOf("duplicate") < 0)) { + data += warn_text[0] + " [" + unique_CAll_Rules[k].modifier_prev_deadkey + " " + unique_CAll_Rules[k].prev_deadkey + "] > dk(A" + String(unique_CAll_Rules[k].dk_prev) + ")\n" } - // skip keyNr 48 ( TAB ) - if (keyNr === 48) - continue - - // add a line after rules of each key - if (unique_CAll_Rules[i].key !== keymarker) - data += '\n' - - - let warningtext: string = "c C0 WARNING: " - // warningtext = warningtext + this.findDuplicateRules(unique_CAll_Rules, i, "C01") - //warningtext = warningtext + this.findDuplicateRules(unique_CAll_Rules, i) - warningtext = warningtext + this.findAmbiguousRules(unique_CAll_Rules, i)[0] - //const warningtextArray: string[] = this.findAmbiguousRules(unique_CAll_Rules, i) - // console.log("warningtextArrayOUT ", warningtextArray) - - warningtext = warningtext + this.findUnAvailableRule(unique_CAll_Rules, i)[0] - // todo what about empty returns -> undefined??? - - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // ~~~~ draft print ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // ((unique_CAll_Rules[i].rule_type === "C0") || (unique_CAll_Rules[i].rule_type === "C1") - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - if ((KeylayoutToKmnConverter.print_draft) && (new TextDecoder().decode(unique_CAll_Rules[i].output) !== "")) { - if (warningtext === "c C0 WARNING: ") - data += unique_CAll_Rules[i].rule_type + keyNr + keyNr + "-(modif:" + unique_CAll_Rules[i].rule_type + "-" + unique_CAll_Rules[i].dk_prev + `) + [` + (unique_CAll_Rules[i].modifier_key + ' ' + unique_CAll_Rules[i].key).trim() + `] °°-> \'` + new TextDecoder().decode(unique_CAll_Rules[i].output) + '\'\n' - else - data += warningtext + keyNr + "-(modif:" + unique_CAll_Rules[i].rule_type + "-" + unique_CAll_Rules[i].dk_prev + `) + [` + (unique_CAll_Rules[i].modifier_key + ' ' + unique_CAll_Rules[i].key).trim() + `] **°°-> \'` + new TextDecoder().decode(unique_CAll_Rules[i].output) + '\'\n' + //SECONDTEXT print + if ((warn_text[1].indexOf("duplicate") < 0)) { + data += warn_text[1] + "dk(A" + String(unique_CAll_Rules[k].dk_prev) + ") + [" + unique_CAll_Rules[k].modifier_deadkey + " " + unique_CAll_Rules[k].deadkey + "] > dk(B" + String(unique_CAll_Rules[k].dk_C2) + ")\n" } - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // ~~~~ draft print end ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - else { - if (warningtext === "c C0 WARNING: ") - data += "+ [" + (unique_CAll_Rules[i].modifier_key + ' ' + unique_CAll_Rules[i].key).trim() + `] > \'` + new TextDecoder().decode(unique_CAll_Rules[i].output) + '\'\n' - else - data += warningtext + (unique_CAll_Rules[i].modifier_key + ' ' + unique_CAll_Rules[i].key).trim() + `] > \'` + new TextDecoder().decode(unique_CAll_Rules[i].output) + '\'\n' - } - keymarker = unique_CAll_Rules[i].key - } - } - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // ~~~~ draft print ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - - if (KeylayoutToKmnConverter.print_draft) { - data += "\n########## C2 #################################################################\n" - } - else - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // ~~~~ draft print end ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - data += "\n" - - //................................................ C2 ................................................................... - //................................................ C2 ................................................................... - //................................................ C2 ................................................................... - data += "\nc ########## C2 #################################################################\n" - for (let k = 0; k < unique_CAll_Rules.length; k++) { - - if (unique_CAll_Rules[k].rule_type === "C2") { - - let warningtext: string = "c C2 WARNING: " - //warningtext = warningtext + this.findDuplicateRules(unique_CAll_Rules, k, "C2") - warningtext = warningtext + this.findAmbiguousRules(unique_CAll_Rules, k) - warningtext = warningtext + this.findUnAvailableRule(unique_CAll_Rules, k) - const warningtextArray: string[] = this.findAmbiguousRules(unique_CAll_Rules, k) - - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // ~~~~ draft print ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - if (KeylayoutToKmnConverter.print_draft) { - if (warningtext === "c C2 WARNING: ") { - data += "new: [" + unique_CAll_Rules[k].modifier_deadkey + " " + unique_CAll_Rules[k].deadkey + "] > XXX" + - " [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] °°-> \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'" - } - else { - data += warningtext + " [" + unique_CAll_Rules[k].modifier_deadkey + " " + unique_CAll_Rules[k].deadkey + "] > XXX" + - "[" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'" - } + // THIRDTEXT print OK + if ((warn_text[2].indexOf("duplicate") < 0)) { + data += warn_text[2] + "dk(B" + String(unique_CAll_Rules[k].dk_C2) + ") + [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'\n" } - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // ~~~~ draft print end ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - else { - // all OK - if (warningtext === "c C2 WARNING: ") { - - if (unique_CAll_Rules[k].uniqueB !== 0) { - data += "+ [" + unique_CAll_Rules[k].modifier_deadkey + " " + unique_CAll_Rules[k].deadkey + "] > dk(C" + String(unique_CAll_Rules[k].dk_C2) + ")\n" - } - //data += "---\n" - data += "dk(C" + String(unique_CAll_Rules[k].dk_C2) + ") + [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'\n" - } - // warning avail - if (warningtextArray[0] !== "") { - - console.log(" warningtext XXX ", typeof (warningtext), warningtext[0], warningtext[1]) - const secondline = warningtext[1] - const posSecond = warningtext.indexOf("SECONDTEXT") - const firsttext = warningtext[1] - const secondtext = warningtext[0] - console.log("secondline ", secondline, posSecond, firsttext, "---", secondtext) - - data += firsttext + "+ [" + unique_CAll_Rules[k].modifier_deadkey + " " + unique_CAll_Rules[k].deadkey + "] > dk(C" + String(unique_CAll_Rules[k].dk_C2) + ")\n" - if (secondline) - data += "c " + secondtext + "dk(C" + String(unique_CAll_Rules[k].dk_C2) + ") + [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'\n" - else - data += "dk(C" + String(unique_CAll_Rules[k].dk_C2) + ") + [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'\n" - - - - // data += warningtext + unique_CAll_Rules[k].modifier_deadkey + " " + unique_CAll_Rules[k].deadkey + "] > dk(C" + String(unique_CAll_Rules[k].dk_C2) + ")\n" - // data += " dk(C" + String(unique_CAll_Rules[k].dk_C2) + ") + [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'\n" - } - - } data += "\n" } } - //................................................ C3 ................................................................... - //................................................ C3 ................................................................... - //................................................ C3 ................................................................... - - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // ~~~~ draft print ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - if (KeylayoutToKmnConverter.print_draft) { - data += "\n########## C3 #################################################################\n" - } - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // ~~~~ draft print end ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - data += "\nc ########## C3 #################################################################\n" - for (let k = 0; k < unique_CAll_Rules.length; k++) { - - if (unique_CAll_Rules[k].rule_type === "C3") { - - let warningtext: string = "c C3 WARNING: " - warningtext = warningtext + this.findDuplicateRules(unique_CAll_Rules, k, "C3") // OK - warningtext = warningtext + this.findAmbiguousRules(unique_CAll_Rules, k) // OK - warningtext = warningtext + this.findUnAvailableRule(unique_CAll_Rules, k) // OK - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // ~~~~ draft print ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - if (KeylayoutToKmnConverter.print_draft) { - if (warningtext === "c C3 WARNING: ") { - data += " [" + unique_CAll_Rules[k].modifier_prev_deadkey + " " + unique_CAll_Rules[k].prev_deadkey + "] > XXX " + - "[" + unique_CAll_Rules[k].modifier_deadkey + " " + unique_CAll_Rules[k].deadkey + "] > YYY " + - " [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] °°-> \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'" - } - else { - data += warningtext + " [" + unique_CAll_Rules[k].modifier_prev_deadkey + " " + unique_CAll_Rules[k].prev_deadkey + "] > XXX " + - "[" + unique_CAll_Rules[k].modifier_deadkey + " " + unique_CAll_Rules[k].deadkey + "] > YYY " + - " [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] °°-> \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'" - } - } - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // ~~~~ draft print end ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - else { - if (warningtext === "c C3 WARNING: ") { - - if (unique_CAll_Rules[k].uniqueA !== 0) { - data += "+ [" + unique_CAll_Rules[k].modifier_prev_deadkey + " " + unique_CAll_Rules[k].prev_deadkey + "] > dk(A" + String(unique_CAll_Rules[k].dk_prev) + ")\n" - } - - if ((unique_CAll_Rules[k].uniqueB !== 0) && (unique_CAll_Rules[k].uniqueA !== 0)) { - data += "dk(A" + String(unique_CAll_Rules[k].dk_prev) + ") + [" + unique_CAll_Rules[k].modifier_deadkey + " " + unique_CAll_Rules[k].deadkey + "] > dk(B" + String(unique_CAll_Rules[k].dk) + ")\n" - } - - data += "dk(B" + String(unique_CAll_Rules[k].dk) + ") + [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'\n" - data += "\n" - } - - else { - data += warningtext + unique_CAll_Rules[k].modifier_prev_deadkey + " " + unique_CAll_Rules[k].prev_deadkey + "] > dk(A" + String(unique_CAll_Rules[k].dk_prev) + ")\n" - data += "dk(A" + String(unique_CAll_Rules[k].dk_prev) + ") + [" + unique_CAll_Rules[k].modifier_deadkey + " " + unique_CAll_Rules[k].deadkey + "] > dk(B" + String(unique_CAll_Rules[k].dk) + ")\n" - data += "dk(B" + String(unique_CAll_Rules[k].dk) + ") + [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'\n" - } - } - data += "\n" - } - } - data += '\n' return data } + public createData_Stores(data_ukelele: convert_object): string { let data: string = "" @@ -2511,7 +2460,7 @@ console.log(" modifier_single",modifier_single, iskKeymanModifier ) public writeDataset(dataRules: rule_object[]) { for (let i = 0; i < dataRules.length; i++) { - console.log("dataRules ", + console.log("dataRules ", i, dataRules[i].rule_type !== "" ? dataRules[i].rule_type : "--".padEnd(4, " ") , /*dataRules.length, i,*/ @@ -2521,15 +2470,17 @@ console.log(" modifier_single",modifier_single, iskKeymanModifier ) (dataRules[i].dk_prev !== 0 ? ("dk(A" + String(dataRules[i].dk_prev) + ")").padEnd(11, " ") : "--".padEnd(11, " ")), (dataRules[i].uniqueA !== 0 ? ("unique(A" + String(dataRules[i].uniqueA) + ")").padEnd(11, " ") : "--".padEnd(11, " ")), - /* (("dk(A-B-C " + String(dataRules[i].dk_prev) + "-" + String(dataRules[i].dk)).padEnd(9, "-") + (String(dataRules[i].dk_C2) + ")").padEnd(9, " ")), - ("unique(AB " + String(dataRules[i].uniqueA) + "-" + String(dataRules[i].uniqueB) + ")"),*/ + /* (("dk(A-B-C " + String(dataRules[i].dk_prev) + "-" + String(dataRules[i].dk)).padEnd(9, "-") + (String(dataRules[i].dk_C2) + ")").padEnd(9, " ")), + ("unique(AB " + String(dataRules[i].uniqueA) + "-" + String(dataRules[i].uniqueB) + ")"),*/ (dataRules[i].modifier_deadkey !== "" ? dataRules[i].modifier_deadkey.padEnd(30, " ") : "--".padEnd(30, " ")), (dataRules[i].deadkey !== "" ? dataRules[i].deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), dataRules[i].rule_type === "C2" ? (dataRules[i].dk !== 0 ? ("dk(C" + String(dataRules[i].dk) + ")").padEnd(9, " ") : "--".padEnd(9, " ")) : ((dataRules[i].dk !== 0 ? ("dk(B" + String(dataRules[i].dk) + ")").padEnd(9, " ") : "--".padEnd(9, " "))), dataRules[i].rule_type === "C2" ? (dataRules[i].uniqueB !== 0 ? ("unique(C" + String(dataRules[i].uniqueB) + ")").padEnd(9, " ") : "--".padEnd(9, " ")) : ((dataRules[i].uniqueA !== 0 ? ("unique(B" + String(dataRules[i].dk) + ")").padEnd(9, " ") : "--".padEnd(9, " "))), - + dataRules[i].dk, + dataRules[i].dk_C2, + dataRules[i].dk_prev, // dataRules[i].rule_type === "C2" ? (dataRules[i].dk !== 0 ? ("dk(C" + String(dataRules[i].dk) + ")").padEnd(9, " ") : "--".padEnd(9, " ")) : ((dataRules[i].dk !== 0 ? ("dk(B" + String(dataRules[i].dk) + ")").padEnd(9, " ") : "--".padEnd(9, " "))), // dataRules[i].rule_type === "C2" ? (dataRules[i].uniqueB !== 0 ? ("unique(C" + String(dataRules[i].uniqueB) + ")").padEnd(9, " ") : "--".padEnd(9, " ")) : ((dataRules[i].uniqueA !== 0 ? ("unique(B" + String(dataRules[i].dk) + ")").padEnd(9, " ") : "--".padEnd(9, " "))), @@ -2560,7 +2511,9 @@ console.log(" modifier_single",modifier_single, iskKeymanModifier ) (dataRules.deadkey !== "" ? dataRules.deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), dataRules.rule_type === "C2" ? (dataRules.dk !== 0 ? ("dk(C" + String(dataRules.dk) + ")").padEnd(9, " ") : "--".padEnd(9, " ")) : ((dataRules.dk !== 0 ? ("dk(B" + String(dataRules.dk) + ")").padEnd(9, " ") : "--".padEnd(9, " "))), dataRules.rule_type === "C2" ? (dataRules.uniqueB !== 0 ? ("unique(C" + String(dataRules.uniqueB) + ")").padEnd(9, " ") : "--".padEnd(9, " ")) : ((dataRules.uniqueA !== 0 ? ("unique(B" + String(dataRules.dk) + ")").padEnd(9, " ") : "--".padEnd(9, " "))), - + dataRules.dk, + dataRules.dk_C2, + dataRules.dk_prev, "| ", (dataRules.modifier_key !== "" ? dataRules.modifier_key.padEnd(40, " ") : "--".padEnd(40, " ")), (dataRules.key !== "" ? dataRules.key.padEnd(8, " ") : "--".padEnd(8, " ")), @@ -2582,7 +2535,7 @@ class Rules { public modifier_deadkey: string, /* second key used by C2,C3 rules*/ public deadkey: string, - public dk: number, + public dk: number, public dk_C2: number, public uniqueB: number, From 44bedec80896082c25cb9cd4b9bf1e1084b62005 Mon Sep 17 00:00:00 2001 From: Sabine Date: Tue, 18 Feb 2025 21:46:42 +0100 Subject: [PATCH 051/251] feat(developer): kmc-convert new approach ambiguous/duplicate rules C0/C1 and C2 OK --- .../keylayout-to-kmn-converter.ts | 1141 +++-------------- 1 file changed, 203 insertions(+), 938 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 945b48ae08b..c869b8393c4 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -10,58 +10,58 @@ import { ConverterToKmnArtifacts } from "../converter-artifacts.js"; import boxXmlArray = util.boxXmlArray;*/ { // TODO keylayout->kmn - // OK modifiers: The identifier of the element to use for this range of hardware keyboard types. - // OK defaultIndex: The table number to use for modifier key combinations which are not explicitly specified by any element within the . - // OK write read, convert, write + // modifiers: The identifier of the element to use for this range of hardware keyboard types. + // defaultIndex: The table number to use for modifier key combinations which are not explicitly specified by any element within the . + // write read, convert, write // tests for 3 functions read write convert - // OK add data to object - // OK Use filter functions - // OK action/output:use filter etc to shorten func - // OK deadkeyables:use filter etc to shorten func - // OK dk-> for all action:use filter etc to shorten func + // add data to object + // Use filter functions + // action/output:use filter etc to shorten func + // deadkeyables:use filter etc to shorten func + // dk-> for all action:use filter etc to shorten func // remove unneccessary data from dataObject // rename symbols - // OK remove part using kmn_key_Name1 - // OK remove unnecceaasry map_UkeleleKC_To_kmn_Key_Name_Array_Position_n etc - // OK loop throught ANSI, JIS- at moment only use [keyMapSet_count] (keyMapSet_count=0) - // OK remove funcs at teh end + // remove part using kmn_key_Name1 + // remove unnecceaasry map_UkeleleKC_To_kmn_Key_Name_Array_Position_n etc + // loop throught ANSI, JIS- at moment only use [keyMapSet_count] (keyMapSet_count=0) + // remove funcs at teh end // import { makePathToFixture } from '../../test/helpers/index.js'; - // OK Mapping 0->30 or 0->K_A-> missing entries in mapping - // OK Replace any-types - // OK Several steps action-> action-> action->character ( not only action->character) + // Mapping 0->30 or 0->K_A-> missing entries in mapping + // Replace any-types + // Several steps action-> action-> action->character ( not only action->character) // TODO waht about using actions twice in a row??? -> error msg if chain >4 - // OK Usable for all keylayout files + // Usable for all keylayout files // Return conditions - // OK Use callbacks as for writeFileSync + // Use callbacks as for writeFileSync // Tests throws // Conditions NCAPS,OPT;... // TODO move func outside of class // Functions as object methods? // objects contain only used stuff READ in: -- out: only read arrays / CONVERT in: only read arrays out: return only to write arrays - // OK Use catch blocks for file read - // OK read: answer : + [K_A] > 'a' is OK / TODO which format to use in output ? + [K_A] > 'a' (character code) or + [K_A] > U+0061 (virt Keycode) + // Use catch blocks for file read + // read: answer : + [K_A] > 'a' is OK / TODO which format to use in output ? + [K_A] > 'a' (character code) or + [K_A] > U+0061 (virt Keycode) // read TODO which stores? - // OK one entry vs several entry in tags + // one entry vs several entry in tags // false arrangement of tags ? - // OK no added NCAPS when first modifier in modifierMap does not contain "caps" or"caps?" + // no added NCAPS when first modifier in modifierMap does not contain "caps" or"caps?" // use length to clear array instead of defining evetry time new (modifierMap_ONE_InKeymapSelect.length=0 - // OK naming of for-loop var i,j,k?... + // naming of for-loop var i,j,k?... // warning if contrADICTING RULES E:G: [ 'modifier_C0', 'SHIFT NCAPS', 'K_C', 'c'], vs [ 'modifier_C0', 'SHIFT NCAPS', 'K_C', 'C' ], - // OK print NCAPS as the first of the modifiers in create_kmn_modifier - // OK use boxXmlArray from codebase instead of my own - // OK where are rules for action+none ( a, e, u, etc) - // OK order of object member var - // OK readfilesync with paths better way? - // OK rearrange code to use read, convert, write - // OK TODO rewrite explanantion for object instead of array - // OK remove all any types + // print NCAPS as the first of the modifiers in create_kmn_modifier + // use boxXmlArray from codebase instead of my own + // where are rules for action+none ( a, e, u, etc) + // order of object member var + // readfilesync with paths better way? + // rearrange code to use read, convert, write + // TODO rewrite explanantion for object instead of array + // remove all any types // check code for code styles keyman // public dk: number, //todo remove one - // OK todo use from elsewhere boxXmlArray_S - // OK prev_deadkeys_Ch: Uint8Array, /* Todo needed?*/ + // todo use from elsewhere boxXmlArray_S + // prev_deadkeys_Ch: Uint8Array, /* Todo needed?*/ // Todo remove print_draft // TODO throws - // OK Todo files/path !!! + // Todo files/path !!! // TODO need to use export const USVirtualKeyCodes here // start Tests v ToDo remove...................................... // TODO remove: test files: checkif kmn gets the same output as ukelele file(except for C3 t works well :)) @@ -74,6 +74,7 @@ import boxXmlArray = util.boxXmlArray;*/ // check duplicate rule conditions which do I need; which can go // when I run german with uniqueCAll why will there be [ ] without key anf modifier // 77 replace uniqueA 0, >0 with true, false + // what if keylayout file is not correct e.g missing > @@ -1057,359 +1058,11 @@ export class KeylayoutToKmnConverter { return mapIndexArray_max } - /* public get_KeyMap_Code__From__KeyMap_Action(data: any, search: string): number { - for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { - for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { - if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { - return data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'] - } - } - } - return -1 - }*/ - /*public get_KeyMap_Behaviour_array__From__KeyMap_Action(data: any, search: string[]): string[][] { - const returnarray2D: string[][] = [] - for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { - for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { - const returnarray: string[] = [] - if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { - returnarray.push(this.map_UkeleleKC_To_VK(Number(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']))) - returnarray.push(data.keyboard.keyMapSet[0].keyMap[i]['@_index']) - returnarray.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action']) - } - if (returnarray.length > 0) - returnarray2D.push(returnarray) - } - } - return returnarray2D - }*/ - /*public get_KeyMap_Code_array__From__KeyMap_Action_array(data: any, search: string[][]): string[] { - const returnarray: string[] = [] - for (let i = 0; i < search.length; i++) { - for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap.length; j++) { - for (let k = 0; k < data.keyboard.keyMapSet[0].keyMap[j].key.length; k++) { - if (data.keyboard.keyMapSet[0].keyMap[j].key[k]['@_action'] === search[i][0]) { - returnarray.push(data.keyboard.keyMapSet[0].keyMap[j].key[k]['@_code']) - } - } - } - } - return returnarray - }*/ - /*public get_ActionID_array__From__ActionID_NoneNext(data: any, search: string): string[] { - const returnarray: string[] = [] - if (search !== "none") { - for (let i = 0; i < data.keyboard.actions.action.length; i++) { - for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { - if (data.keyboard.actions.action[i].when[j]['@_next'] === search) { - if (data.keyboard.actions.action[i].when[j]['@_state'] === "none") - returnarray.push(data.keyboard.actions.action[i]['@_id']) - } - } - } - } - return returnarray - }*/ - /* public get_keyModifierArray__from__Action(data: any, search: string): string[][] { - // search is a9 - const returnarray2D: string[][] = [] - for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { - for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { - const returnarray: string[] = [] - if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { - returnarray.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action']) - returnarray.push(this.map_UkeleleKC_To_VK(Number(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']))) - returnarray.push(data.keyboard.keyMapSet[0].keyMap[i]['@_index']) - } - if (returnarray.length > 0) - returnarray2D.push(returnarray) - } - } - return returnarray2D - }*/ - - // ToDo needed?? - /*public get_ActionID_Output__From__ActionID_IdState(data: any, search_id: string, search_state: string): Uint8Array { - for (let i = 0; i < data.keyboard.actions.action.length; i++) { - for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { - if ((data.keyboard.actions.action[i]['@_id'] === search_id) && - (data.keyboard.actions.action[i].when[j]['@_state'] === search_state)) { - return new TextEncoder().encode(data.keyboard.actions.action[i].when[j]['@_output']) - } - } - } - return new TextEncoder().encode("") - }*/ - // ToDo needed?? - /*public get_ActionID_Key__From__ActionID_IdState(data: any, search_id: string, search_state: string): Uint8Array { - for (let i = 0; i < data.keyboard.actions.action.length; i++) { - for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { - if ((data.keyboard.actions.action[i]['@_id'] === search_id) && - (data.keyboard.actions.action[i].when[j]['@_state'] === search_state)) { - return new TextEncoder().encode(data.keyboard.actions.action[i].when[j]['@_output']) - } - } - } - return new TextEncoder().encode("") - }*/ - // ToDo needed?? - /*public get_KeyMap_Keymaparray__From__KeyMap_Code_array(data: any, search: string[]): string[][] { - const returnarray: string[][] = [] - for (let k = 0; k < search.length; k++) { - const returnarray1D: string[] = [] - for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { - for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { - if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'] === search[k]) { - returnarray1D.push(search[k]) - returnarray1D.push(data.keyboard.keyMapSet[0].keyMap[i]['@_index']) - } - } - } - returnarray.push(returnarray1D) - } - return returnarray - }*/ - /*public get_KeyMap_Keymaparray__From__KeyMap_Action_array(data: any, search: string): string[][] { - const returnarray: string[][] = [] - for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { - const returnarray1D: string[] = [] - for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { - if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { - returnarray1D.push(search) - returnarray1D.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']) - returnarray1D.push(data.keyboard.keyMapSet[0].keyMap[i]['@_index']) - } - if (returnarray1D.length > 0) - returnarray.push(returnarray1D) - } - } - //ToDo check if I can use this filer somewhere else - const [uniqueElements] = returnarray.reduce((acc, curr) => { - const [uniq, set] = acc; - if (!set.has(curr.join(','))) { - set.add(curr.join(',')); - uniq.push(curr); - } - return acc; - }, - [[], new Set()], - ); - return uniqueElements - }*/ - - // ToDo needed?? - /*public get_KeyMap_Keymaparray__From__KeyMap_Action(data: any, search: string): string[] { - const returnarray: string[] = [] - for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { - for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { - if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { - returnarray.push(data.keyboard.keyMapSet[0].keyMap[i]['@_index']) - } - } - } - return returnarray - }*/ - // ToDo needed?? - /*public get_ActionID_Id_array__From__ActionID_next(data: any, search: string): string[][] { - const returnarray2D: string[][] = [] - if (search !== "none") { - for (let i = 0; i < data.keyboard.actions.action.length; i++) { - const returnarray: string[] = [] - for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { - if (data.keyboard.actions.action[i].when[j]['@_next'] === search) { - returnarray.push(data.keyboard.actions.action[i]['@_id']) - } - } - if (returnarray.length > 0) - returnarray2D.push(returnarray) - } - } - return returnarray2D - }*/ - // ToDo needed?? get all entries for state= and a given action id - /*public get_Action2ID_State_arrayState_Array__From__ActionID_Id(data: any, search: string): string[] { - const returnarray: string[] = [] - for (let i = 0; i < data.keyboard.actions.action.length; i++) { - if (data.keyboard.actions.action[i]['@_id'] === search) { - for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { - if (data.keyboard.actions.action[i].when[j]['@_state'] !== "none") { - returnarray.push(data.keyboard.actions.action[i].when[j]['@_state']) - } - } - } - } - return returnarray - }*/ - // ToDo needed?? get all entries for state= and a given action id - /* public get_ActionID_Id_arrayNext_Array__From__ActionID_StateNext(data: any, search: string): string[] { - const returnarray: string[] = [] - for (let i = 0; i < data.keyboard.actions.action.length; i++) { - for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { - if ((data.keyboard.actions.action[i].when[j]['@_next'] === search) && (data.keyboard.actions.action[i].when[j]['@_state'] !== "none")) { - returnarray.push(data.keyboard.actions.action[i]['@_id']) - } - } - } - return returnarray - }*/ - /*public map_UkeleleKC_To_VK_array(search: string[]): string[] { - const returnarray: string[] = [] - for (let i = 0; i < search.length; i++) { - returnarray.push(this.map_UkeleleKC_To_VK(Number(search[i]))) - } - return returnarray - }*/ - /*public get_ActionID_Id__From__ActionID_Next(data: any, search: string) { - for (let i = 0; i < data.keyboard.actions.action.length; i++) { - for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { - if ((data.keyboard.actions.action[i].when[j]['@_next'] === search)) { - return data.keyboard.actions.action[i]['@_id'] - } - } - } - return "" - }*/ - /*public get_Modifier_Text__From__Modifier_Index(data: any, search: string): string[] { - const mapIndexArray_max: string[] = [] - const mapIndexArrayperKey: string[] = [] - for (let i = 0; i < data[search].length; i++) { - mapIndexArrayperKey.push((data[search][i])) - } - for (let i = 0; i < data[search].length; i++) { - mapIndexArray_max.push(data[search][i]) - } - return mapIndexArray_max - }*/ - /*public get_KeyMap_Code__From__ActionID_Action(data: any, search: string): number { - const mapIndexArray_max: number[][] = [] - for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { - for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { - const mapIndexArrayperKey: number[] = [] - - if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { - mapIndexArrayperKey.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']) - mapIndexArrayperKey.push(i) - } - if (mapIndexArrayperKey.length > 0) - mapIndexArray_max.push(mapIndexArrayperKey) - } - } - return mapIndexArray_max[0][1] - }*/ - /*public get_KeyMap_Code__From__ActionID_Action2(data: any, search: string): number { - const mapIndexArray_max: number[][] = [] - for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { - for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { - const mapIndexArrayperKey: number[] = [] - - if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { - mapIndexArrayperKey.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']) - mapIndexArrayperKey.push(i) - } - if (mapIndexArrayperKey.length > 0) - mapIndexArray_max.push(mapIndexArrayperKey) - } - } - return mapIndexArray_max[0][1] - }*/ - /*public get_ActionID_Next__From__ActionID_Id(data: any, search: string): string { - for (let i = 0; i < data.keyboard.actions.action.length; i++) { - if ((data.keyboard.actions.action[i]['@_id'] === search)) - return data.keyboard.actions.action[i].when[1]['@_next'] - } - return "" - }*/ - /*public get_KeyMap_Index__From__KeyMap_Action(data: any, search: string): number { - for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { - for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { - if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { - return data.keyboard.keyMapSet[0].keyMap[i]['@_index'] - } - } - } - return -1 - }*/ - /*public get_KeyMap_IndexCodeAction_array__From__KeyMap_Action(data: any, search: string): string[][] { - const returnarray2D: string[][] = [] - for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { - for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { - const returnarray: string[] = [] - if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { - returnarray.push(data.keyboard.keyMapSet[0].keyMap[i]['@_index']) - returnarray.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']) - returnarray.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action']) - } - if (returnarray.length > 0) { - returnarray2D.push(returnarray) - } - } - } - return returnarray2D - }*/ - /*public get_KeyMap_IndexCodeAction_array__From__KeyMap_Action_Array(data: any, search: string[][]): string[][] { - console.log("search uuuu ", search) - const modifierArray: number[] = [] - const modifierArray2D: number[][] = [] - - const returnarray2D: string[][] = [] - for (let i = 0; i < search.length; i++) { - modifierArray.push(Number(search[i][0])) - } - modifierArray2D.push(modifierArray) - - returnarray2D.push(this.get_KeyMap_Modifier_array__From__behaviour_arr(data, modifierArray2D)) - return returnarray2D - }*/ - /*public get_KeyMap_ModiIndex_array__From__KeyMap_Action(data: any, search_code: string, search_action: string): string[][] { - const returnarray2D: string[][] = [] - for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { - for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { - const returnarray: string[] = [] - if ((data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search_action) && - (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'] === search_code)) { - returnarray.push(data.keyboard.keyMapSet[0].keyMap[i]['@_index']) - returnarray.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']) - returnarray.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action']) - } - if (returnarray.length > 0) { - returnarray2D.push(returnarray) - } - } - } - return returnarray2D - }*/ - /*public get_ActionID_Output__From__ActionID_State(data: any, search: string, nextval: string): string { - for (let i = 0; i < data.keyboard.actions.action.length; i++) { - for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { - if ((data.keyboard.actions.action[i].when[j]['@_state'] === search) && (data.keyboard.actions.action[i]['@_id'] === nextval)) { - return data.keyboard.actions.action[i].when[j]['@_output'] - } - } - } - return "" - }*/ - /* public get_KeyMap_Modifier_aray__From__KeyMap_Index(data: any, search: number): string[] { - return data.ArrayOf_Modifiers[search] - }*/ - - - /*public get_data_From__KeyMap_Modifier_Index(data: any, search: number): string[] { - return data[search] - }*/ - - /*public get_dataArray2D__From__KeyMap_Modifier_Index(data: any, search: string[]): string[][] { - const returnarray: string[][] = [] - for (let i = 0; i < search.length; i++) { - returnarray.push(data[search[i]]) - } - return returnarray - }*/ /** * @brief member function to return the unicode value of a character * @param character the value that will converted * @return headecimal value of a character */ - /* public getHexFromChar(character: string): string { return character.charCodeAt(0).toString(16).slice(-4).toUpperCase().padStart(4, "0") }*/ @@ -1506,70 +1159,67 @@ export class KeylayoutToKmnConverter { } return iskKeymanModifier } - public findDuplicateRules(rules: rule_object[], index: number, rule_type: string): string { - for (let i = 0; i < index - 1; i++) { - if ( - ((rule_type === "C01") - && rules[i].modifier_key === rules[index].modifier_key - && rules[i].key === rules[index].key && - new TextDecoder().decode(rules[i].output) === new TextDecoder().decode(rules[index].output) - ) - || (rule_type === "C2" - && rules[i].modifier_deadkey === rules[index].modifier_deadkey - && rules[i].deadkey === rules[index].deadkey - && rules[i].modifier_key === rules[index].modifier_key - && rules[i].key === rules[index].key - && new TextDecoder().decode(rules[i].output) === new TextDecoder().decode(rules[index].output) - ) - || (rule_type === "C3" - && rules[i].modifier_prev_deadkey === rules[index].modifier_prev_deadkey - && rules[i].prev_deadkey === rules[index].prev_deadkey - && rules[i].modifier_deadkey === rules[index].modifier_deadkey - && rules[i].deadkey === rules[index].deadkey - && rules[i].modifier_key === rules[index].modifier_key - && rules[i].key === rules[index].key - && new TextDecoder().decode(rules[i].output) === new TextDecoder().decode(rules[index].output) - ) - ) - return ("duplicate Rule: old: modif[ modi; " + rules[i].dk_prev + "[" + - rules[i].modifier_prev_deadkey + " " + rules[i].prev_deadkey + "] > XXX [" + - rules[i].modifier_deadkey + " " + rules[i].deadkey + "] > YYY [" + - rules[i].modifier_key + " " + rules[i].key + - "] °°-> \'" + new TextDecoder().decode(rules[i].output) + "\' <--> ") + // definition of comparisons 1-1, 2-4, 6-6, ... see https://docs.google.com/document/d/12J3NGO6RxIthCpZDTR8FYSRjiMgXJDLwPY2z9xqKzJ0/edit?tab=t.0 + // todo remove comments n filters after check of several keylayout files + public reviewRules(rule: rule_object[], index: number): string[] { + const warningTextArray: string[] = Array(3).fill(""); + + // +++++++++++++++++++++++++ check unavailable modifiers ++++++++++++++++++++++++++++++++++++++ + + if (((rule[index].rule_type === "C0") || (rule[index].rule_type === "C1") || (rule[index].rule_type === "C4"))) { + + if (!(this.isAcceptableKeymanModifier(rule[index].modifier_key))) { + warningTextArray[2] = "C1 unavailable modifier in: " + } + } + + if (rule[index].rule_type === "C2") { + if + (!(this.isAcceptableKeymanModifier(rule[index].modifier_deadkey))) { + warningTextArray[1] = "C2 unavailable modifier in: " + } + + if (!(this.isAcceptableKeymanModifier(rule[index].modifier_key))) { + warningTextArray[2] = "C2 unavailable modifier in: " + } } - return "" - } + if (rule[index].rule_type === "C3") { - public findAmbiguousRules(rule: rule_object[], index: number): string[] { - const returnarray: string[] = Array(3).fill(""); + if (!(this.isAcceptableKeymanModifier(rule[index].modifier_prev_deadkey))) { + warningTextArray[2] = "C3 unavailable modifier in: " + } - // filter 1 Text............................................................... - if (rule[index].rule_type === "C0" || rule[index].rule_type === "C1") { + if (!(this.isAcceptableKeymanModifier(rule[index].modifier_deadkey))) { + warningTextArray[1] = "C3 unavailable modifier in: " + } - this.writeDatasetSingle(rule[index]) + if (!(this.isAcceptableKeymanModifier(rule[index].modifier_key))) { + warningTextArray[0] = "C3 unavailable modifier in: " + } - // OK A 1-1 + [CAPS K_N] > 'N' <-> + [CAPS K_N] > 'A' - const ambiguous_C0C1_vs_C0C1 = rule.filter((curr, idx) => - (curr.rule_type === "C0" || curr.rule_type === "C1") + } + // +++++++++++++++++++++++++ check ambiguous/duplicate rules ++++++++++++++++++++++++++++++++++++++ + + if (((rule[index].rule_type === "C0") || (rule[index].rule_type === "C1"))) { + + // 1-1 + [CAPS K_N] > 'N' <-> + [CAPS K_N] > 'A' + const amb_1_1_bot = rule.filter((curr, idx) => ( + curr.rule_type === "C0" || curr.rule_type === "C1") && curr.modifier_prev_deadkey === "" && curr.prev_deadkey === "" && curr.modifier_deadkey === "" && curr.deadkey === "" && curr.modifier_key === rule[index].modifier_key && curr.key === rule[index].key - && new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output) // amb + && new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output) && idx < index ); - if (ambiguous_C0C1_vs_C0C1.length > 0) { - console.log("ambiguous_C0C1_vs_C0C1 ",) - this.writeDataset(ambiguous_C0C1_vs_C0C1) - } - //+ [CAPS K_N] > 'N' <-> + [CAPS K_N] > 'N' - const duplicate_C0C1_vs_C0C1 = rule.filter((curr, idx) => + // 1-1 + [CAPS K_N] > 'N' <-> + [CAPS K_N] > 'N' + const dup_1_1_bot = rule.filter((curr, idx) => (curr.rule_type === "C0" || curr.rule_type === "C1") && curr.modifier_prev_deadkey === "" && curr.prev_deadkey === "" @@ -1577,566 +1227,245 @@ export class KeylayoutToKmnConverter { && curr.deadkey === "" && curr.modifier_key === rule[index].modifier_key && curr.key === rule[index].key - && new TextDecoder().decode(curr.output) === new TextDecoder().decode(rule[index].output) // dup + && new TextDecoder().decode(curr.output) === new TextDecoder().decode(rule[index].output) && idx < index ); - if (ambiguous_C0C1_vs_C0C1.length > 0) { - //Firstsentence - returnarray[0] = returnarray[0] + ( - "ambiguous 1-1 rule: earlier: [" - + ambiguous_C0C1_vs_C0C1[0].modifier_key + " " - + ambiguous_C0C1_vs_C0C1[0].key + "] > \'" - + new TextDecoder().decode(ambiguous_C0C1_vs_C0C1[0].output) - + "\' here: [") + if (amb_1_1_bot.length > 0) { + warningTextArray[2] = warningTextArray[2] + ("C1 ambiguous 1-1 rule: earlier: [" + amb_1_1_bot[0].modifier_key + " " + amb_1_1_bot[0].key + "] > \'" + new TextDecoder().decode(amb_1_1_bot[0].output) + "\' here: [") } - if (duplicate_C0C1_vs_C0C1.length > 0) { - //Firstsentence - returnarray[0] = returnarray[0] + ("duplicate 1-1 rule: earlier: [" - + duplicate_C0C1_vs_C0C1[0].modifier_key + " " - + duplicate_C0C1_vs_C0C1[0].key + "] > \'" - + new TextDecoder().decode(duplicate_C0C1_vs_C0C1[0].output) - + "\' here: [") + if (dup_1_1_bot.length > 0) { + warningTextArray[2] = warningTextArray[2] + ("C1 duplicate 1-1 rule: earlier: [" + dup_1_1_bot[0].modifier_key + " " + dup_1_1_bot[0].key + "] > \'" + new TextDecoder().decode(dup_1_1_bot[0].output) + "\' here: [") } - return returnarray } - // filter 2 Text............................................................... if (rule[index].rule_type === "C2") { - this.writeDatasetSingle(rule[index]) + // 2-2 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(C1) - const ambiguous_C2_vs_C2 = rule.filter((curr, idx) => + const amb_2_2_mid = rule.filter((curr, idx) => curr.rule_type === "C2" && curr.modifier_deadkey === rule[index].modifier_deadkey && curr.deadkey === rule[index].deadkey - && (String(curr.dk_C2) !== String(rule[index].dk_C2) || String(curr.dk) !== String(rule[index].dk)) + && curr.dk_C2 !== rule[index].dk_C2 || curr.dk !== rule[index].dk && idx < index ); - /*if (ambiguous_C2_vs_C2.length > 0) { - console.log("2-2 ambiguous_C2_vs_C2 ",) - this.writeDataset(ambiguous_C2_vs_C2) - }*/ //2-2 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(C11) - const duplicate_C2_vs_C2 = rule.filter((curr, idx) => + const dup_2_2 = rule.filter((curr, idx) => curr.rule_type === "C2" && curr.modifier_deadkey === rule[index].modifier_deadkey && curr.deadkey === rule[index].deadkey - && String(curr.dk_C2) === String(rule[index].dk_C2) // dup - && String(curr.dk) === String(rule[index].dk) // dup + && curr.dk_C2 === rule[index].dk_C2 + && curr.dk === rule[index].dk && idx < index ); - /*if (duplicate_C2_vs_C2.length > 0) { - console.log("2-2 duplicate_C2_vs_C2 ",) - this.writeDataset(duplicate_C2_vs_C2) - //this.writeDatasetSingle(duplicate_C2_vs_C2[0]) - ///this.writeDatasetSingle(duplicate_C2_vs_C2[1]) - }*/ //3-3 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'B' - const ambiguous_C2_vs_C2_B2 = rule.filter((curr, idx) => + const amb_3_3_bot = rule.filter((curr, idx) => (curr.rule_type === "C2") - && String(curr.dk_C2) === String(rule[index].dk_C2) + && curr.dk_C2 === rule[index].dk_C2 && rule[index].uniqueB !== 0 && curr.modifier_key === rule[index].modifier_key && curr.key === rule[index].key - && (new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output)) // amb + && (new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output)) && idx < index - ); /*if (ambiguous_C2_vs_C2_B2.length > 0) { - console.log("3-3 ambiguous_C2_vs_C2_B2 ",) - this.writeDataset(ambiguous_C2_vs_C2_B2) - }*/ - //da stimmt noch was nicht + ); + //3-3 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'Ã' - const duplicate_C2_vs_C2_B2 = rule.filter((curr, idx) => + const dup_3_3_bot = rule.filter((curr, idx) => (curr.rule_type === "C2") - && String(curr.dk_C2) === String(rule[index].dk_C2) // dup + && curr.dk_C2 === rule[index].dk_C2 && rule[index].uniqueB === 0 && curr.modifier_key === rule[index].modifier_key && curr.key === rule[index].key - && new TextDecoder().decode(curr.output) === new TextDecoder().decode(rule[index].output) // dup + && new TextDecoder().decode(curr.output) === new TextDecoder().decode(rule[index].output) && idx < index - );/* if (duplicate_C2_vs_C2_B2.length > 0) { - console.log("3-3 duplicate_C2_vs_C2_B2 ",) - this.writeDataset(duplicate_C2_vs_C2_B2) - }*/ + ); //1-2 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > 'Ñ' - const ambibguous_C2_vs_C1 = rule.filter((curr, idx) => + const amb_1_2_mid = rule.filter((curr, idx) => ((curr.rule_type === "C0") || (curr.rule_type === "C1")) && curr.modifier_key === rule[index].modifier_deadkey && curr.key === rule[index].deadkey - //&& rule[index].uniqueB === 0 // without this there will be no warning for first - //&& (idx < index) // without this there will be no warning for first - ); /*if (ambibguous_C2_vs_C1.length > 0) { - console.log("1-2 ambibguous_C2_vs_C1 ",) - this.writeDataset(ambibguous_C2_vs_C1) - }*/ - - if (ambiguous_C2_vs_C2.length > 0) { - returnarray[0] = returnarray[0] + ("FIRSTTEXT " + "ambiguous 2-2 rule: earlier: [" + ambiguous_C2_vs_C2[0].modifier_deadkey + " " + ambiguous_C2_vs_C2[0].deadkey + "] > dk(C" + ambiguous_C2_vs_C2[0].dk_C2 + "here: )\'") - } - if (duplicate_C2_vs_C2.length > 0) { - returnarray[0] = returnarray[0] + ("FIRSTTEXT " + "duplicate 2-2 rule: earlier: [" + duplicate_C2_vs_C2[0].modifier_deadkey + " " + duplicate_C2_vs_C2[0].deadkey + "] > dk(C" + duplicate_C2_vs_C2[0].dk_C2 + "here: )\'") - } - if (ambiguous_C2_vs_C2_B2.length > 0) { - returnarray[1] = returnarray[1] + ("SECONDTEXT " + "duplicate y 3-3 rule: earlier: dk(C" + ambiguous_C2_vs_C2_B2[0].dk_C2 + ") + [" + ambiguous_C2_vs_C2_B2[0].modifier_key + " " + ambiguous_C2_vs_C2_B2[0].key + "] > \'" + new TextDecoder().decode(ambiguous_C2_vs_C2_B2[0].output) + "\' here: ") - } - if (duplicate_C2_vs_C2_B2.length > 0) { - returnarray[1] = returnarray[1] + ("SECONDTEXT " + "duplicate y 3-3 rule: earlier: dk(C" + duplicate_C2_vs_C2_B2[0].dk_C2 + ") + [" + duplicate_C2_vs_C2_B2[0].modifier_key + " " + duplicate_C2_vs_C2_B2[0].key + "] > \'" + new TextDecoder().decode(duplicate_C2_vs_C2_B2[0].output) + "\' here: ") - } - if (ambibguous_C2_vs_C1.length > 0) { - returnarray[0] = returnarray[0] + ("FIRSTTEXT " + "ambiguous 1-2 rule: earlier: [" + ambibguous_C2_vs_C1[0].modifier_key + " " + ambibguous_C2_vs_C1[0].key + "] > \'" + new TextDecoder().decode(ambibguous_C2_vs_C1[0].output) + "\' here: ") - } - return returnarray - } - - if (rule[index].rule_type === "C3") { - returnarray[0] = "" - returnarray[1] = "" - returnarray[2] = "" - - // 1-4 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > 'Ñ' - const ambibguous_C3_vs_C1 = rule.filter((curr, idx) => - ((curr.rule_type === "C0") || (curr.rule_type === "C1")) - && curr.modifier_key === rule[index].modifier_prev_deadkey - && curr.key === rule[index].prev_deadkey - //&& rule[index].uniqueA === 0 // without this there will be no warning - //&& (idx < index) - ); - - // 2-4 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(C1) - const ambibguous_C3_vs_C2_B = rule.filter((curr, idx) => - ((curr.rule_type === "C2")) - && curr.modifier_deadkey === rule[index].modifier_prev_deadkey - && curr.deadkey === rule[index].prev_deadkey - && String(curr.dk_C2) === String(rule[index].dk_prev) // dup - // && rule[index].uniqueA === 0 // without this there will be no warning - //&& (idx < index) - ); - - // 6-3 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'B' - const ambiguous_C3_vs_C2_B2 = rule.filter((curr, idx) => - (curr.rule_type === "C2") - && String(curr.dk_prev) === String(rule[index].dk_prev) // amb - && curr.modifier_key === rule[index].modifier_key - && curr.key === rule[index].key - && (new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output)) // amb - // && rule[index].uniqueB !== 0 - // && idx < index - ); - - // 6-3 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'Ã' - const duplicate_C3_vs_C2_B2 = rule.filter((curr, idx) => - (curr.rule_type === "C2") - && String(curr.dk_prev) === String(rule[index].dk_prev) // dup - && curr.modifier_key === rule[index].modifier_key - && curr.key === rule[index].key - && new TextDecoder().decode(curr.output) === new TextDecoder().decode(rule[index].output) // dup - // && rule[index].uniqueB === 0 - // && idx < index - ); - - // 4-4 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > 'dk(C1)' - const ambiguous_C3_vs_C3 = rule.filter((curr, idx) => - curr.rule_type === "C3" - && curr.modifier_prev_deadkey === rule[index].modifier_prev_deadkey - && (String(curr.dk_prev) !== String(rule[index].dk_prev)) - && curr.prev_deadkey === rule[index].prev_deadkey - && rule[index].uniqueA !== 0 - && idx < index + //&& rule[index].uniqueB === 0 // include and the first occurance will be printed + //&& (idx < index) // include and the first occurance will be printed ); - // 4-4 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(C11) - const duplicate_C3_vs_C3 = rule.filter((curr, idx) => - curr.rule_type === "C3" - && curr.modifier_prev_deadkey === rule[index].modifier_prev_deadkey - && curr.prev_deadkey === rule[index].prev_deadkey - && (String(curr.dk_prev) === String(rule[index].dk_prev)) - /* && rule[index].uniqueA !== 0 - && idx < index*/ - ); - - // 6-6 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'B' - const ambiguous_C3_vs_C3_C = rule.filter((curr, idx) => - (curr.rule_type === "C3") - && String(curr.dk_C2) === String(rule[index].dk_C2) // no need to convert to string - && rule[index].uniqueA !== 0 - && String(curr.dk) === String(rule[index].dk) - && curr.modifier_key === rule[index].modifier_key - && curr.key === rule[index].key - && (new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output)) // amb - - && idx < index - ); - - // 6-6 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'Ã' - const duplicate_C3_vs_C3_C = rule.filter((curr, idx) => - ((curr.rule_type === "C3") - && curr.modifier_key === rule[index].modifier_key - && curr.key === rule[index].key - && curr.modifier_deadkey === rule[index].modifier_deadkey - && curr.deadkey === rule[index].deadkey - && curr.modifier_prev_deadkey !== "" - && curr.prev_deadkey !== "" - && curr.dk_prev !== 0 - && new TextDecoder().decode(curr.output) === new TextDecoder().decode(rule[index].output) // dup - && rule[index].uniqueB !== 0 - && idx < index) - || - ((curr.rule_type === "C3") - && curr.dk_C2 === rule[index].dk_C2 - && curr.modifier_key === rule[index].modifier_key - && curr.key === rule[index].key - && new TextDecoder().decode(curr.output) === new TextDecoder().decode(rule[index].output) // dup - && idx < index) - ); - - // 5-5 - const ambiguous_C3_vs_C3_B = rule.filter((curr, idx) => - (curr.rule_type === "C3") - && curr.modifier_key === rule[index].modifier_key - && curr.key === rule[index].key - && String(curr.dk_C2) === String(rule[index].dk_C2) // no need to convert to string - //&& String(curr.dk) === String(rule[index].dk) - && (new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output)) // amb - && rule[index].uniqueA !== 0 - && idx < index - ); - if (ambiguous_C3_vs_C3_B.length > 0) - console.log("ambiguous_C3_vs_C3_B ****************", ambiguous_C3_vs_C3_B) - - // 5-5 - const duplicate_C3_vs_C3_B = rule.filter((curr, idx) => - (curr.rule_type === "C3") - && curr.modifier_deadkey === rule[index].modifier_deadkey - && curr.deadkey === rule[index].deadkey - && String(curr.dk_prev) === String(rule[index].dk_prev) // no need to convert to string - && String(curr.dk_C2) === String(rule[index].dk_C2) // no need to convert to string - && String(curr.dk) === String(rule[index].dk) - && rule[index].uniqueA !== 0 - && idx < index - ); - - if (duplicate_C3_vs_C3_B.length > 0) { - console.log("duplicate_C3_vs_C3_B ***----*********",) - this.writeDatasetSingle(duplicate_C3_vs_C3_B[0]) - } - - if (ambibguous_C3_vs_C1.length > 0) { - returnarray[0] = returnarray[0] + ("FIRSTTEXT " + "ambiguous 1-4 rule: earlier: [" + ambibguous_C3_vs_C1[0].modifier_key + " " + ambibguous_C3_vs_C1[0].key + "] > \'" + new TextDecoder().decode(ambibguous_C3_vs_C1[0].output) + "\' here: ") - } - - if (ambibguous_C3_vs_C2_B.length > 0) { - returnarray[0] = returnarray[0] + ("FIRSTTEXT " + "ambiguous 2-4 rule: earlier: [" + ambibguous_C3_vs_C2_B[0].modifier_deadkey + " " + ambibguous_C3_vs_C2_B[0].deadkey + "] > dk(C" + ambibguous_C3_vs_C2_B[0].dk_C2 + ") here: )\'") - } - - if (ambiguous_C3_vs_C2_B2.length > 0) { - returnarray[2] = returnarray[2] + ("SECONDTEXT " + "ambiguous y 6-3 rule: earlier: dk(C" + ambiguous_C3_vs_C2_B2[0].dk_C2 + ") + [" + ambiguous_C3_vs_C2_B2[0].modifier_key + " " + ambiguous_C3_vs_C2_B2[0].key + "] > \'" + new TextDecoder().decode(ambiguous_C3_vs_C2_B2[0].output) + "\' here: ") - } - - if (duplicate_C3_vs_C2_B2.length > 0) { - returnarray[2] = returnarray[2] + ("SECONDTEXT " + "duplicate y 6-3 rule: earlier: dk(C" + duplicate_C3_vs_C2_B2[0].dk_C2 + ") + [" + duplicate_C3_vs_C2_B2[0].modifier_key + " " + duplicate_C3_vs_C2_B2[0].key + "] > \'" + new TextDecoder().decode(duplicate_C3_vs_C2_B2[0].output) + "\' here: ") - } - - if (ambiguous_C3_vs_C3.length > 0) { - returnarray[0] = returnarray[0] + ("FIRSTTEXT " + "ambiguous 4-4 rule: earlier: [" + ambiguous_C3_vs_C3[0].modifier_deadkey + " " + ambiguous_C3_vs_C3[0].deadkey + "] > dk(C" + ambiguous_C3_vs_C3[0].dk_C2 + "here: )\'") + if (amb_2_2_mid.length > 0) { + warningTextArray[1] = warningTextArray[1] + ("C2 SECONDTEXT " + "ambiguous 2-2 rule: earlier: [" + amb_2_2_mid[0].modifier_deadkey + " " + amb_2_2_mid[0].deadkey + "] > dk(C" + amb_2_2_mid[0].dk_C2 + ") here: ") } - if (duplicate_C3_vs_C3.length > 0) { - returnarray[0] = returnarray[0] + ("FIRSTTEXT " + "duplicate 4-4 rule: earlier: [" + duplicate_C3_vs_C3[0].modifier_deadkey + " " + duplicate_C3_vs_C3[0].deadkey + "] > dk(C" + duplicate_C3_vs_C3[0].dk_C2 + "here: )\'") + if (dup_2_2.length > 0) { + warningTextArray[1] = warningTextArray[1] + ("C2 SECONDTEXT " + "duplicate 2-2 rule: earlier: [" + dup_2_2[0].modifier_deadkey + " " + dup_2_2[0].deadkey + "] > dk(C" + dup_2_2[0].dk_C2 + ") here: ") } - - if (ambiguous_C3_vs_C3_C.length > 0) { - returnarray[2] = returnarray[2] + ("THIRDTEXT " + "ambiguous y 6-6 rule: earlier: dk(B" + ambiguous_C3_vs_C3_C[0].dk_C2 + ") + [" + ambiguous_C3_vs_C3_C[0].modifier_key + " " + ambiguous_C3_vs_C3_C[0].key + "] > \'" + new TextDecoder().decode(ambiguous_C3_vs_C3_C[0].output) + "\' here: ") + if (amb_3_3_bot.length > 0) { + warningTextArray[2] = warningTextArray[2] + ("C2 THIRDTEXT " + "ambiguous y 3-3 rule: earlier: dk(C" + amb_3_3_bot[0].dk_C2 + ") + [" + amb_3_3_bot[0].modifier_key + " " + amb_3_3_bot[0].key + "] > \'" + new TextDecoder().decode(amb_3_3_bot[0].output) + "\' here: ") } - - if (duplicate_C3_vs_C3_C.length > 0) { - returnarray[2] = returnarray[2] + ("THIRDTEXT " + "duplicate y 6-6 rule: earlier: dk(B" + duplicate_C3_vs_C3_C[0].dk_C2 + ") + [" + duplicate_C3_vs_C3_C[0].modifier_key + " " + duplicate_C3_vs_C3_C[0].key + "] > \'" + new TextDecoder().decode(duplicate_C3_vs_C3_C[0].output) + "\' here: ") + if (dup_3_3_bot.length > 0) { + warningTextArray[2] = warningTextArray[2] + ("C2 THIRDTEXT " + "duplicate y 3-3 rule: earlier: dk(C" + dup_3_3_bot[0].dk_C2 + ") + [" + dup_3_3_bot[0].modifier_key + " " + dup_3_3_bot[0].key + "] > \'" + new TextDecoder().decode(dup_3_3_bot[0].output) + "\' here: ") } - - if (ambiguous_C3_vs_C3_B.length > 0) { - returnarray[1] = returnarray[1] + ("SECONDTEXT " + "ambiguous y 5-5 rule: earlier: dk(C" + ambiguous_C3_vs_C3_B[0].dk_C2 + ") + [" + ambiguous_C3_vs_C3_B[0].modifier_key + " " + ambiguous_C3_vs_C3_B[0].key + "] > dk(" + ambiguous_C3_vs_C3_B[0].dk_C2 + ") here: ") + if (amb_1_2_mid.length > 0) { + warningTextArray[1] = warningTextArray[1] + ("C2 SECONDTEXT " + "ambiguous 1-2 rule: earlier: [" + amb_1_2_mid[0].modifier_key + " " + amb_1_2_mid[0].key + "] > \'" + new TextDecoder().decode(amb_1_2_mid[0].output) + "\' here: ") } - - if (duplicate_C3_vs_C3_B.length > 0) { - returnarray[1] = returnarray[1] + ("SECONDTEXT " + "duplicate y 5-5 rule: earlier: dk(C" + duplicate_C3_vs_C3_B[0].dk_C2 + ") + [" + duplicate_C3_vs_C3_B[0].modifier_key + " " + duplicate_C3_vs_C3_B[0].key + "] > dk(" + duplicate_C3_vs_C3_B[0].dk_C2 + ") here: ") - } - } - return returnarray - } - - public findUnAvailableRule(rule: rule_object[], index: number): string[] { - const returnarray: string[] = Array(3).fill(""); - const returnarray_sorted: string[] = Array(3).fill(""); - - // [0] rules with output 1,3,6 (key) - // [1] middle part 2,5 (dk) - // [2] lwft part 4 (prev_dk) - - // console.log("isAcceptableKeymanModifier check 0", this.isAcceptableKeymanModifier(rule[index].modifier_key), rule[index].modifier_key) - // console.log("isAcceptableKeymanModifier check 1", this.isAcceptableKeymanModifier(rule[index].modifier_deadkey), rule[index].modifier_deadkey) - // console.log("isAcceptableKeymanModifier check 2", this.isAcceptableKeymanModifier(rule[index].modifier_prev_deadkey), rule[index].modifier_prev_deadkey) - - - if (((rule[index].rule_type === "C0") || (rule[index].rule_type === "C1") || (rule[index].rule_type === "C4")) - && (!(this.isAcceptableKeymanModifier(rule[index].modifier_key)))) { - returnarray[1] = "unavailable modifier in: " - returnarray_sorted[0] = "unavailable modifier in: " } - else if - ((rule[index].rule_type === "C2" - && (!(this.isAcceptableKeymanModifier(rule[index].modifier_deadkey))))) { - returnarray[1] = "unavailable A modifier in: " - returnarray_sorted[1] = "unavailable modifier in: " - } - else if ((rule[index].rule_type === "C2") - && (!(this.isAcceptableKeymanModifier(rule[index].modifier_key)))) { - returnarray[0] = "unavailable B modifier in: " - returnarray_sorted[0] = "unavailable modifier in: " - } - - - else if ((rule[index].rule_type === "C3") - && (!(this.isAcceptableKeymanModifier(rule[index].modifier_prev_deadkey)))) { - returnarray[0] = "" - returnarray_sorted[2] = "" - } - else if ((rule[index].rule_type === "C3") - && (!(this.isAcceptableKeymanModifier((rule[index].modifier_deadkey))))) { - returnarray[1] = "" - returnarray_sorted[1] = "" - } - else if ((rule[index].rule_type === "C3") - && (!(this.isAcceptableKeymanModifier(rule[index].modifier_key)))) { - returnarray[2] = "" - returnarray_sorted[0] = "" - } - - - /* console.log("resultttt ", - (returnarray_sorted[0] === "" && returnarray_sorted[1] === "" && returnarray_sorted[2] === ""), - rule[index].rule_type, - rule[index].modifier_key, - rule[index].modifier_deadkey, - rule[index].modifier_prev_deadkey, - "--", - returnarray, - "--", - returnarray_sorted)*/ - - return returnarray_sorted - return returnarray - } - public reviewRules(rule: rule_object[], index: number): string[] { - const returnarray_sorted: string[] = Array(3).fill(""); - - // [0] rules with output 1,3,6 (key) - // [1] middle part 2,5 (dk) - // [2] lwft part 4 (prev_dk) - - // +++++++++++++++++++++++++ first unavailable rules ++++++++++++++++++++++++++++++++++++++ - console.log("reviewRules isAcceptableKeymanModifier check 0 ", this.isAcceptableKeymanModifier(rule[index].modifier_key), rule[index].modifier_key) - console.log("reviewRules isAcceptableKeymanModifier check 1", this.isAcceptableKeymanModifier(rule[index].modifier_deadkey), rule[index].modifier_deadkey) - console.log("reviewRules isAcceptableKeymanModifier check 2", this.isAcceptableKeymanModifier(rule[index].modifier_prev_deadkey), rule[index].modifier_prev_deadkey) - - /* - if (((rule[index].rule_type === "C0") || (rule[index].rule_type === "C1") || (rule[index].rule_type === "C4")) - && (!(this.isAcceptableKeymanModifier(rule[index].modifier_key)))) { - returnarray[1] = "unavailable modifier in: " - returnarray_sorted[0] = "unavailable modifier in: " - } - - else if - ((rule[index].rule_type === "C2" - && (!(this.isAcceptableKeymanModifier(rule[index].modifier_deadkey))))) { - returnarray[1] = "unavailable A modifier in: " - returnarray_sorted[1] = "unavailable modifier in: " - - } - else if ((rule[index].rule_type === "C2") - && (!(this.isAcceptableKeymanModifier(rule[index].modifier_key)))) { - returnarray[0] = "unavailable B modifier in: " - returnarray_sorted[0] = "unavailable modifier in: " - } - */ - - if (rule[index].rule_type === "C3") { - - if (!(this.isAcceptableKeymanModifier(rule[index].modifier_prev_deadkey))) { - returnarray_sorted[2] = "unavailable modifier in: " - } - - if (!(this.isAcceptableKeymanModifier(rule[index].modifier_deadkey))) { - returnarray_sorted[1] = "unavailable modifier in: " - } - - if (!(this.isAcceptableKeymanModifier(rule[index].modifier_key))) { - returnarray_sorted[0] = "unavailable modifier in: " - } - } - // +++++++++++++++++++++++++ then ambiguous/duplicate rules ++++++++++++++++++++++++++++++++++++++ - if (rule[index].rule_type === "C3") { // 1-4 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > 'Ñ' - const ambibguous_C3_vs_C1 = rule.filter((curr, idx) => + const amb_1_4_mid = rule.filter((curr, idx) => ((curr.rule_type === "C0") || (curr.rule_type === "C1")) && curr.modifier_key === rule[index].modifier_prev_deadkey && curr.key === rule[index].prev_deadkey - //&& rule[index].uniqueA === 0 // without this there will be no warning + //&& rule[index].uniqueA === 0 // include and the first occurance will be printed //&& (idx < index) ); // 2-4 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(C1) - const ambibguous_C3_vs_C2_B = rule.filter((curr, idx) => + const amb_2_4_mid = rule.filter((curr, idx) => ((curr.rule_type === "C2")) && curr.modifier_deadkey === rule[index].modifier_prev_deadkey && curr.deadkey === rule[index].prev_deadkey - && String(curr.dk_C2) === String(rule[index].dk_prev) // dup - // && rule[index].uniqueA === 0 // without this there will be no warning - //&& (idx < index) + && curr.dk_C2 === rule[index].dk_prev + // && rule[index].uniqueA === 0 // include and the first occurance will be printed + // && (idx < index) ); // 6-3 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'B' - const ambiguous_C3_vs_C2_B2 = rule.filter((curr, idx) => + const dup_6_3_bot = rule.filter((curr, idx) => (curr.rule_type === "C2") - && String(curr.dk_prev) === String(rule[index].dk_prev) // amb + && curr.dk_prev === rule[index].dk_prev && curr.modifier_key === rule[index].modifier_key && curr.key === rule[index].key - && (new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output)) // amb + && (new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output)) // && rule[index].uniqueB !== 0 // && idx < index ); // 6-3 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'Ã' - const duplicate_C3_vs_C2_B2 = rule.filter((curr, idx) => + const dup_6_3_mid = rule.filter((curr, idx) => (curr.rule_type === "C2") - && String(curr.dk_prev) === String(rule[index].dk_prev) // dup + && curr.dk_prev === rule[index].dk_prev && curr.modifier_key === rule[index].modifier_key && curr.key === rule[index].key - && new TextDecoder().decode(curr.output) === new TextDecoder().decode(rule[index].output) // dup + && new TextDecoder().decode(curr.output) === new TextDecoder().decode(rule[index].output) // && rule[index].uniqueB === 0 // && idx < index ); // 4-4 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > 'dk(C1)' - const ambiguous_C3_vs_C3 = rule.filter((curr, idx) => + const amb_4_4_mid = rule.filter((curr, idx) => curr.rule_type === "C3" && curr.modifier_prev_deadkey === rule[index].modifier_prev_deadkey - && (String(curr.dk_prev) !== String(rule[index].dk_prev)) + && curr.dk_prev !== rule[index].dk_prev && curr.prev_deadkey === rule[index].prev_deadkey && rule[index].uniqueA !== 0 && idx < index ); // 4-4 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(C11) - const duplicate_C3_vs_C3 = rule.filter((curr, idx) => + const dup_4_4_mid = rule.filter((curr, idx) => curr.rule_type === "C3" && curr.modifier_prev_deadkey === rule[index].modifier_prev_deadkey && curr.prev_deadkey === rule[index].prev_deadkey - && (String(curr.dk_prev) === String(rule[index].dk_prev)) - // && rule[index].uniqueA !== 0 + && curr.dk_prev === rule[index].dk_prev && idx < index + // && rule[index].uniqueA !== 0 ); // 6-6 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'B' - const ambiguous_C3_vs_C3_C = rule.filter((curr, idx) => + const amb_6_6_bot = rule.filter((curr, idx) => (curr.rule_type === "C3") - && String(curr.dk_C2) === String(rule[index].dk_C2) // no need to convert to string + && curr.dk_C2 === rule[index].dk_C2 && rule[index].uniqueA !== 0 - && String(curr.dk) === String(rule[index].dk) + && curr.dk === rule[index].dk && curr.modifier_key === rule[index].modifier_key && curr.key === rule[index].key - && (new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output)) // amb + && (new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output)) && idx < index ); // 6-6 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'Ã' - const duplicate_C3_vs_C3_C = rule.filter((curr, idx) => + const dup_6_6_bot = rule.filter((curr, idx) => (curr.rule_type === "C3") - && String(curr.dk_C2) === String(rule[index].dk_C2) + && curr.dk_C2 === rule[index].dk_C2 && curr.modifier_key === rule[index].modifier_key && curr.key === rule[index].key - && (new TextDecoder().decode(curr.output) === new TextDecoder().decode(rule[index].output)) // dup + && (new TextDecoder().decode(curr.output) === new TextDecoder().decode(rule[index].output)) && idx < index ); // 5-5 - const ambiguous_C3_vs_C3_B = rule.filter((curr, idx) => + const amb_5_5_mid = rule.filter((curr, idx) => (curr.rule_type === "C3") && curr.modifier_key === rule[index].modifier_key && curr.key === rule[index].key - && String(curr.dk_C2) === String(rule[index].dk_C2) // no need to convert to string - //&& String(curr.dk) === String(rule[index].dk) - && (new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output)) // amb - //&& rule[index].uniqueA !== 0 + && curr.dk_C2 === rule[index].dk_C2 + && (new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output)) && idx < index + //&& rule[index].uniqueA !== 0 + //&& String(curr.dk) === String(rule[index].dk) ); // 5-5 - const duplicate_C3_vs_C3_B = rule.filter((curr, idx) => + const dup_5_5_mid = rule.filter((curr, idx) => (curr.rule_type === "C3") && curr.modifier_deadkey === rule[index].modifier_deadkey && curr.deadkey === rule[index].deadkey - && String(curr.dk_prev) === String(rule[index].dk_prev) // no need to convert to string - && String(curr.dk_C2) === String(rule[index].dk_C2) // no need to convert to string - && String(curr.dk) === String(rule[index].dk) + && curr.dk_prev === rule[index].dk_prev + && curr.dk_C2 === rule[index].dk_C2 + && curr.dk === rule[index].dk && rule[index].uniqueB === 0 //&& idx < index ); - if (ambiguous_C3_vs_C3_C.length > 0) { - returnarray_sorted[2] = returnarray_sorted[2] + ("THIRDTEXT " + "ambiguous y 6-6 rule: earlier: dk(B" + ambiguous_C3_vs_C3_C[0].dk_C2 + ") + [" + ambiguous_C3_vs_C3_C[0].modifier_key + " " + ambiguous_C3_vs_C3_C[0].key + "] > \'" + new TextDecoder().decode(ambiguous_C3_vs_C3_C[0].output) + "\' here: ") + if (amb_1_4_mid.length > 0) { + warningTextArray[0] = warningTextArray[0] + ("C3 FIRSTTEXT " + "ambiguous 1-4 rule: earlier(Todo check if print out or not): [" + amb_1_4_mid[0].modifier_key + " " + amb_1_4_mid[0].key + "] > \'" + new TextDecoder().decode(amb_1_4_mid[0].output) + "\' here: ") } - if (duplicate_C3_vs_C3_C.length > 0) { - returnarray_sorted[2] = returnarray_sorted[2] + ("THIRDTEXT " + "duplicate y 6-6x rule: earlier: dk(B" + duplicate_C3_vs_C3_C[0].dk_C2 + ") + [" + duplicate_C3_vs_C3_C[0].modifier_key + " " + duplicate_C3_vs_C3_C[0].key + "] > \'" + new TextDecoder().decode(duplicate_C3_vs_C3_C[0].output) + "\' here: ") - + if (amb_2_4_mid.length > 0) { + warningTextArray[0] = warningTextArray[0] + ("C3 FIRSTTEXT " + "ambiguous 2-4 rule: earlier(Todo check if print out or not): [" + amb_2_4_mid[0].modifier_deadkey + " " + amb_2_4_mid[0].deadkey + "] > dk(C" + amb_2_4_mid[0].dk_C2 + ") here: ") } - if (ambibguous_C3_vs_C1.length > 0) { - returnarray_sorted[0] = returnarray_sorted[0] + ("FIRSTTEXT " + "ambiguous 1-4 rule: earlier(Todo check if print out or not): [" + ambibguous_C3_vs_C1[0].modifier_key + " " + ambibguous_C3_vs_C1[0].key + "] > \'" + new TextDecoder().decode(ambibguous_C3_vs_C1[0].output) + "\' here: ") + + if (dup_6_3_bot.length > 0) { + warningTextArray[1] = warningTextArray[1] + ("C3 SECONDTEXT " + "ambiguous y 6-3 rule: earlier: dk(C" + dup_6_3_bot[0].dk_C2 + ") + [" + dup_6_3_bot[0].modifier_key + " " + dup_6_3_bot[0].key + "] > \'" + new TextDecoder().decode(dup_6_3_bot[0].output) + "\' here: ") } - if (ambibguous_C3_vs_C2_B.length > 0) { - returnarray_sorted[0] = returnarray_sorted[0] + ("FIRSTTEXT " + "ambiguous 2-4 rule: earlier(Todo check if print out or not): [" + ambibguous_C3_vs_C2_B[0].modifier_deadkey + " " + ambibguous_C3_vs_C2_B[0].deadkey + "] > dk(C" + ambibguous_C3_vs_C2_B[0].dk_C2 + ") here: )\'") + if (dup_6_3_mid.length > 0) { + warningTextArray[1] = warningTextArray[1] + ("C3 SECONDTEXT " + "duplicate y 6-3 rule: earlier: dk(C" + dup_6_3_mid[0].dk_C2 + ") + [" + dup_6_3_mid[0].modifier_key + " " + dup_6_3_mid[0].key + "] > \'" + new TextDecoder().decode(dup_6_3_mid[0].output) + "\' here: ") } - if (ambiguous_C3_vs_C2_B2.length > 0) { - returnarray_sorted[1] = returnarray_sorted[1] + ("SECONDTEXT " + "ambiguous y 6-3 rule: earlier: dk(C" + ambiguous_C3_vs_C2_B2[0].dk_C2 + ") + [" + ambiguous_C3_vs_C2_B2[0].modifier_key + " " + ambiguous_C3_vs_C2_B2[0].key + "] > \'" + new TextDecoder().decode(ambiguous_C3_vs_C2_B2[0].output) + "\' here: ") + if (amb_4_4_mid.length > 0) { + warningTextArray[0] = warningTextArray[0] + ("C3 FIRSTTEXT " + "ambiguous 4-4 rule: earlier: [" + amb_4_4_mid[0].modifier_prev_deadkey + " " + amb_4_4_mid[0].prev_deadkey + "] > dk(C" + amb_4_4_mid[0].dk_prev + ") here: ") } - if (duplicate_C3_vs_C2_B2.length > 0) { - returnarray_sorted[1] = returnarray_sorted[1] + ("SECONDTEXT " + "duplicate y 6-3 rule: earlier: dk(C" + duplicate_C3_vs_C2_B2[0].dk_C2 + ") + [" + duplicate_C3_vs_C2_B2[0].modifier_key + " " + duplicate_C3_vs_C2_B2[0].key + "] > \'" + new TextDecoder().decode(duplicate_C3_vs_C2_B2[0].output) + "\' here: ") + if (dup_4_4_mid.length > 0) { + warningTextArray[0] = warningTextArray[0] + ("C3 FIRSTTEXT " + "duplicate 4-4 rule: earlier: [" + dup_4_4_mid[0].modifier_prev_deadkey + " " + dup_4_4_mid[0].prev_deadkey + "] > dk(C" + dup_4_4_mid[0].dk_prev + ") here: ") } - if (ambiguous_C3_vs_C3.length > 0) { - returnarray_sorted[0] = returnarray_sorted[0] + ("FIRSTTEXT " + "ambiguous 4-4 rule: earlier: [" + ambiguous_C3_vs_C3[0].modifier_deadkey + " " + ambiguous_C3_vs_C3[0].deadkey + "] > dk(C" + ambiguous_C3_vs_C3[0].dk_C2 + "here: )\'") + if (amb_5_5_mid.length > 0) { + warningTextArray[1] = warningTextArray[1] + ("C3 SECONDTEXT " + "ambiguous y 5-5 rule: earlier: dk(B" + amb_5_5_mid[0].dk_prev + ") + [" + amb_5_5_mid[0].modifier_deadkey + " " + amb_5_5_mid[0].deadkey + "] > dk(B" + amb_5_5_mid[0].dk_C2 + ") here: ") } - if (duplicate_C3_vs_C3.length > 0) { - returnarray_sorted[0] = returnarray_sorted[0] + ("FIRSTTEXT " + "duplicate 4-4 rule: earlier: [" + duplicate_C3_vs_C3[0].modifier_deadkey + " " + duplicate_C3_vs_C3[0].deadkey + "] > dk(C" + duplicate_C3_vs_C3[0].dk_C2 + "here: )\'") + if (dup_5_5_mid.length > 0) { + warningTextArray[1] = warningTextArray[1] + ("C3 SECONDTEXT " + "duplicate y 5-5 rule: earlier: dk(B" + dup_5_5_mid[0].dk_prev + ") + [" + dup_5_5_mid[0].modifier_deadkey + " " + dup_5_5_mid[0].deadkey + "] > dk(B" + dup_5_5_mid[0].dk_C2 + ") here: ") } - if (ambiguous_C3_vs_C3_B.length > 0) { - returnarray_sorted[1] = returnarray_sorted[1] + ("SECONDTEXT " + "ambiguous y 5-5 rule: earlier: dk(C" + ambiguous_C3_vs_C3_B[0].dk_C2 + ") + [" + ambiguous_C3_vs_C3_B[0].modifier_key + " " + ambiguous_C3_vs_C3_B[0].key + "] > dk(" + ambiguous_C3_vs_C3_B[0].dk_C2 + ") here: ") + if (amb_6_6_bot.length > 0) { + warningTextArray[2] = warningTextArray[2] + ("C3 THIRDTEXT " + "ambiguous y 6-6 rule: earlier: dk(B" + amb_6_6_bot[0].dk_C2 + ") + [" + amb_6_6_bot[0].modifier_key + " " + amb_6_6_bot[0].key + "] > \'" + new TextDecoder().decode(amb_6_6_bot[0].output) + "\' here: ") } - if (duplicate_C3_vs_C3_B.length > 0) { - returnarray_sorted[1] = returnarray_sorted[1] + ("SECONDTEXT " + "duplicate y 5-5 rule: earlier: dk(C" + duplicate_C3_vs_C3_B[0].dk_C2 + ") + [" + duplicate_C3_vs_C3_B[0].modifier_key + " " + duplicate_C3_vs_C3_B[0].key + "] > dk(" + duplicate_C3_vs_C3_B[0].dk_C2 + ") here: ") + if (dup_6_6_bot.length > 0) { + warningTextArray[2] = warningTextArray[2] + ("C3 THIRDTEXT " + "duplicate y 6-6x rule: earlier: dk(B" + dup_6_6_bot[0].dk_C2 + ") + [" + dup_6_6_bot[0].modifier_key + " " + dup_6_6_bot[0].key + "] > \'" + new TextDecoder().decode(dup_6_6_bot[0].output) + "\' here: ") } } - if (returnarray_sorted[0] !== "") returnarray_sorted[0] = "c WARNING C3 " + returnarray_sorted[0] - if (returnarray_sorted[1] !== "") returnarray_sorted[1] = "c WARNING C3 " + returnarray_sorted[1] - if (returnarray_sorted[2] !== "") returnarray_sorted[2] = "c WARNING C3 " + returnarray_sorted[2] + if (warningTextArray[0] !== "") warningTextArray[0] = "c WARNING: " + warningTextArray[0] + if (warningTextArray[1] !== "") warningTextArray[1] = "c WARNING: " + warningTextArray[1] + if (warningTextArray[2] !== "") warningTextArray[2] = "c WARNING: " + warningTextArray[2] - return returnarray_sorted + return warningTextArray } - - /** * @brief member function to map Ukelele keycodes to a Windows Keycodes * @param pos Ukelele (=mac) keycodes @@ -2170,7 +1499,7 @@ export class KeylayoutToKmnConverter { if (pos === 0x1F) return "K_O" /* O */ if (pos === 0x23) return "K_P" /* P */ if (pos === 0x21) return "K_LBRKT" /* [ */ - if (pos === 0x1E) return "K_RBRKT" /* ] */ + if (pos === 0x1E) return "K_RBRKT" /* ] */ // this is (1E) 30 not 36 (24) !!! if (pos === 0x31) return "K_SPACE" /* \ */ if (pos === 0x2A) return "K_BKSLASH" /* \ */ // 42 for ISO correct?? // if (pos === 0x30) return "K_?C1" /* \ */ // 48 for ANSI correct?? @@ -2208,7 +1537,7 @@ export class KeylayoutToKmnConverter { //---------------------------------------------------------------------------------------------------- public createData_Rules(data_ukelele: convert_object): string { - let warningtextArray: string[] = Array(3).fill(""); + //let warningtextArray: string[] = Array(3).fill(""); const maxkey: number = 50 let data: string = "" @@ -2242,7 +1571,7 @@ export class KeylayoutToKmnConverter { //const unique_CAll_Rules: rule_object[] = data_ukelele.ArrayOf_Rules console.log("xx data_ukelele.ArrayOf_Rules", data_ukelele.ArrayOf_Rules.length) - console.log("xx data_ukelele.ArrayOf_Rules", this.writeDataset(data_ukelele.ArrayOf_Rules)) + //console.log("xx data_ukelele.ArrayOf_Rules", this.writeDataset(data_ukelele.ArrayOf_Rules)) console.log("xx unique_CAll_Rules", unique_CAll_Rules.length) // console.log("xx unique_CAll_Rules", this.writeDataset(unique_CAll_Rules)) @@ -2251,13 +1580,13 @@ export class KeylayoutToKmnConverter { //................................................ C0 C1 ................................................................ //................................................ C0 C1 ................................................................ - for (let i = 0; i < unique_CAll_Rules.length; i++) { + for (let k = 0; k < unique_CAll_Rules.length; k++) { - if ((unique_CAll_Rules[i].rule_type === "C0") || (unique_CAll_Rules[i].rule_type === "C1")) { + if ((unique_CAll_Rules[k].rule_type === "C0") || (unique_CAll_Rules[k].rule_type === "C1")) { // lookup key nr of the key that is being processed let keyNr: number = 0; for (let j = 0; j < maxkey; j++) { - if (this.map_UkeleleKC_To_VK(j) === unique_CAll_Rules[i].key) + if (this.map_UkeleleKC_To_VK(j) === unique_CAll_Rules[k].key) keyNr = j } @@ -2266,27 +1595,18 @@ export class KeylayoutToKmnConverter { continue // add a line after rules of each key - if (unique_CAll_Rules[i].key !== keymarker) + if (unique_CAll_Rules[k].key !== keymarker) data += '\n' + //--------------------------------------------------------------------------------------------- - const ambiq_Array: string[] = this.findAmbiguousRules(unique_CAll_Rules, i) - const unav_Array: string[] = this.findUnAvailableRule(unique_CAll_Rules, i) - const new_WarningTextArray: string[] = Array(3).fill(""); - - - new_WarningTextArray[0] = ambiq_Array[0] + unav_Array[0] - new_WarningTextArray[1] = ambiq_Array[1] + unav_Array[1] - new_WarningTextArray[2] = ambiq_Array[2] + unav_Array[2] - - if (new TextDecoder().decode(unique_CAll_Rules[i].output) !== "") { - // if no warning - if (new_WarningTextArray[0] === "") - data += "+ [" + (unique_CAll_Rules[i].modifier_key + ' ' + unique_CAll_Rules[i].key).trim() + `] > \'` + new TextDecoder().decode(unique_CAll_Rules[i].output) + '\'\n' - else - // if warning available - data += "c C0 WARNING: " + new_WarningTextArray[0] + (unique_CAll_Rules[i].modifier_key + ' ' + unique_CAll_Rules[i].key).trim() + `] > \'` + new TextDecoder().decode(unique_CAll_Rules[i].output) + '\'\n' - } - keymarker = unique_CAll_Rules[i].key + + const warn_text = this.reviewRules(unique_CAll_Rules, k) + + // if warning contains "duplicate" we do not write this rule even if it has other warnings since it does not make sense to write twice + // if ((warn_text[2].indexOf("duplicate") < 0)) { + data += warn_text[2] + "+ [" + (unique_CAll_Rules[k].modifier_key + ' ' + unique_CAll_Rules[k].key).trim() + `] > \'` + new TextDecoder().decode(unique_CAll_Rules[k].output) + '\'\n' + // } + keymarker = unique_CAll_Rules[k].key } } data += "\n c ########## C2 #################################################################\n" @@ -2298,65 +1618,18 @@ export class KeylayoutToKmnConverter { if (unique_CAll_Rules[k].rule_type === "C2") { - warningtextArray = this.findAmbiguousRules(unique_CAll_Rules, k) - - const ambiq_Array: string[] = this.findAmbiguousRules(unique_CAll_Rules, k) - const unav_Array: string[] = this.findUnAvailableRule(unique_CAll_Rules, k) - const new_WarningTextArray: string[] = Array(3).fill(""); - - new_WarningTextArray[0] = ambiq_Array[0] + unav_Array[0] - new_WarningTextArray[1] = ambiq_Array[1] + unav_Array[1] - new_WarningTextArray[2] = ambiq_Array[2] + unav_Array[2] - // console.log("new_WarningTextArray after", new_WarningTextArray) - - // swap todo remove - warningtextArray[0] = ambiq_Array[1] + unav_Array[1] - warningtextArray[1] = ambiq_Array[0] + unav_Array[0] - warningtextArray[2] = ambiq_Array[2] + unav_Array[2] - - // unique First unique second - if ((warningtextArray[0] === "") && (warningtextArray[1] === "")) { - if (unique_CAll_Rules[k].uniqueB !== 0) { - data += "+ [" + unique_CAll_Rules[k].modifier_deadkey + " " + unique_CAll_Rules[k].deadkey + "] > dk(C" + String(unique_CAll_Rules[k].dk_C2) + ")\n" - } - data += "dk(C" + String(unique_CAll_Rules[k].dk_C2) + ") + [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'\n" - } - - if ((new_WarningTextArray[0] !== "") && (new_WarningTextArray[1] === "")) { - console.log("cond MET ",) - - if (unique_CAll_Rules[k].uniqueB !== 0) { - data += "C WARNING C2 xx" + new_WarningTextArray[0] + "+ [" + unique_CAll_Rules[k].modifier_deadkey + " " + unique_CAll_Rules[k].deadkey + "] > dk(C" + String(unique_CAll_Rules[k].dk_C2) + ")\n" - } - // if (unique_CAll_Rules[k].uniqueB !== 0) { - data += "dk(C" + String(unique_CAll_Rules[k].dk_C2) + ") + [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'\n" - // } - data += "\n" - continue - } - - - if ((new_WarningTextArray[0] === "") && (new_WarningTextArray[1] !== "")) { - console.log("I am here with: ") - - // if (unique_CAll_Rules[k].uniqueB !== 0) { - data += "C WARNING C2 yy 0" + new_WarningTextArray[1] + "+ [" + unique_CAll_Rules[k].modifier_deadkey + " " + unique_CAll_Rules[k].deadkey + "] > dk(C" + String(unique_CAll_Rules[k].dk_C2) + ")\n" - // } - if (unique_CAll_Rules[k].uniqueB !== 0) { - data += "dk(C" + String(unique_CAll_Rules[k].dk_C2) + ") + [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'\n" - } - continue - } + const warn_text = this.reviewRules(unique_CAll_Rules, k) - if ((new_WarningTextArray[1] !== "") && (new_WarningTextArray[0] !== "")) { + //SECONDTEXT print + // if ((warn_text[1].indexOf("duplicate") < 0)) { + data += warn_text[1] + "+ [" + unique_CAll_Rules[k].modifier_deadkey + " " + unique_CAll_Rules[k].deadkey + "] > dk(C" + String(unique_CAll_Rules[k].dk_C2) + ")\n" + // } - if (unique_CAll_Rules[k].uniqueB !== 0) { - data += "C WARNING C2 xx 1" + new_WarningTextArray[1] + "+ [" + unique_CAll_Rules[k].modifier_deadkey + " " + unique_CAll_Rules[k].deadkey + "] > dk(C" + String(unique_CAll_Rules[k].dk_C2) + ")\n" - } if (unique_CAll_Rules[k].uniqueB !== 0) { - data += "C WARNING C2 yy 1" + new_WarningTextArray[0] + "dk(C" + String(unique_CAll_Rules[k].dk_C2) + ") + [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'\n" - } - } + // THIRDTEXT print OK + // if ((warn_text[2].indexOf("duplicate") < 0)) { + data += warn_text[2] + "dk(C" + String(unique_CAll_Rules[k].dk_C2) + ") + [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'\n" data += "\n" + // } } } @@ -2369,36 +1642,28 @@ export class KeylayoutToKmnConverter { for (let k = 0; k < unique_CAll_Rules.length; k++) { if (unique_CAll_Rules[k].rule_type === "C3") { - const warn_text = this.reviewRules(unique_CAll_Rules, k) - /*console.log("warn_text[0] ", warn_text[0], warn_text[0].indexOf("duplicate")) - console.log("warn_text[1] ", warn_text[1], warn_text[1].indexOf("duplicate")) - console.log("warn_text[2] ", warn_text[2], warn_text[2].indexOf("duplicate"))*/ - // just print out what's in the array // FIRSTTEXT print - if ((warn_text[0].indexOf("duplicate") < 0)) { - data += warn_text[0] + " [" + unique_CAll_Rules[k].modifier_prev_deadkey + " " + unique_CAll_Rules[k].prev_deadkey + "] > dk(A" + String(unique_CAll_Rules[k].dk_prev) + ")\n" - } + // if ((warn_text[0].indexOf("duplicate") < 0)) { + data += warn_text[0] + " [" + unique_CAll_Rules[k].modifier_prev_deadkey + " " + unique_CAll_Rules[k].prev_deadkey + "] > dk(A" + String(unique_CAll_Rules[k].dk_prev) + ")\n" + // } //SECONDTEXT print - if ((warn_text[1].indexOf("duplicate") < 0)) { - data += warn_text[1] + "dk(A" + String(unique_CAll_Rules[k].dk_prev) + ") + [" + unique_CAll_Rules[k].modifier_deadkey + " " + unique_CAll_Rules[k].deadkey + "] > dk(B" + String(unique_CAll_Rules[k].dk_C2) + ")\n" - } + // if ((warn_text[1].indexOf("duplicate") < 0)) { + data += warn_text[1] + "dk(A" + String(unique_CAll_Rules[k].dk_prev) + ") + [" + unique_CAll_Rules[k].modifier_deadkey + " " + unique_CAll_Rules[k].deadkey + "] > dk(B" + String(unique_CAll_Rules[k].dk_C2) + ")\n" + // } // THIRDTEXT print OK - if ((warn_text[2].indexOf("duplicate") < 0)) { - data += warn_text[2] + "dk(B" + String(unique_CAll_Rules[k].dk_C2) + ") + [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'\n" - } + // if ((warn_text[2].indexOf("duplicate") < 0)) { + data += warn_text[2] + "dk(B" + String(unique_CAll_Rules[k].dk_C2) + ") + [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'\n" + // } data += "\n" } } - - - data += '\n' return data } From 1ee09904175e1c24523c6e3225a8c3a6376a6ec3 Mon Sep 17 00:00:00 2001 From: Sabine Date: Wed, 19 Feb 2025 11:19:20 +0100 Subject: [PATCH 052/251] feat(developer): kmc-convert tidy up --- .../keylayout-to-kmn-converter.ts | 142 ++++++++---------- 1 file changed, 63 insertions(+), 79 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index c869b8393c4..f269fd86cd1 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -75,6 +75,8 @@ import boxXmlArray = util.boxXmlArray;*/ // when I run german with uniqueCAll why will there be [ ] without key anf modifier // 77 replace uniqueA 0, >0 with true, false // what if keylayout file is not correct e.g missing > + // check for keys < 50 whern working with keys + // add links to HEADLINE of kmc-convert document @@ -122,8 +124,9 @@ export interface rule_object { }; export interface convert_object { - ArrayOf_Modifiers: string[][], - ArrayOf_Rules: rule_object[], + keylayout_filename: string, + arrayOf_Modifiers: string[][], + arrayOf_Rules: rule_object[], }; @@ -221,12 +224,15 @@ export class KeylayoutToKmnConverter { */ public convert(jsonObj: any): convert_object { + const jsonObj_any: any = jsonObj + const keylayout_file: string = jsonObj_any.keyboard['@_name'] + ".keylayout" const modifierBehavior: string[][] = [] // modifier for each keymapselect const RuleObject: rule_object[] = [] // an array of objects which hold data for a kmn rule const DataObject: convert_object = { - ArrayOf_Modifiers: modifierBehavior, // e.g. 18 modifiersCombinations in 8 KeyMapSelect(behaviors) - ArrayOf_Rules: RuleObject + keylayout_filename: keylayout_file, + arrayOf_Modifiers: modifierBehavior, // e.g. 18 modifiersCombinations in 8 KeyMapSelect(behaviors) + arrayOf_Rules: RuleObject }; // create an array of modifier Combinations (e.g. shift? leftShift caps? ) @@ -249,6 +255,7 @@ export class KeylayoutToKmnConverter { */ //TODO need to use export const USVirtualKeyCodes here public write(data_ukelele: convert_object): boolean { + let data: string = "\n" // add top part of kmn file: STORES @@ -311,7 +318,7 @@ export class KeylayoutToKmnConverter { let action_id: string - const isCapsused: boolean = this.checkIfCapsIsUsed(data_ukelele.ArrayOf_Modifiers) + const isCapsused: boolean = this.checkIfCapsIsUsed(data_ukelele.arrayOf_Modifiers) // loop keys 0-50 (= all keys we use) for (let j = 0; j <= KeylayoutToKmnConverter.used_Keys_count; j++) { @@ -331,7 +338,7 @@ export class KeylayoutToKmnConverter { if (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] !== "") { // loop behaviours - for (let l = 0; l < data_ukelele.ArrayOf_Modifiers[i].length; l++) { + for (let l = 0; l < data_ukelele.arrayOf_Modifiers[i].length; l++) { if (this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']))) { RuleObj = new Rules( @@ -348,7 +355,7 @@ export class KeylayoutToKmnConverter { /* dk for C2*/ 0, /* unique B */ 0, - /* modifier_key*/ this.create_kmn_modifier(data_ukelele.ArrayOf_Modifiers[i][l], isCapsused), + /* modifier_key*/ this.create_kmn_modifier(data_ukelele.arrayOf_Modifiers[i][l], isCapsused), /* key */ this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), /* output */ new TextEncoder().encode(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output']), ) @@ -369,12 +376,12 @@ export class KeylayoutToKmnConverter { // ...............e. g. 0) returnarray2D.push(returnarray) @@ -1133,7 +1147,7 @@ export class KeylayoutToKmnConverter { } public checkIfCapsIsUsed(keylayout_modifier: string[][]): boolean { - return keylayout_modifier.flat().flat().includes("caps") + return JSON.stringify(keylayout_modifier).includes("caps") } // todo check conditions command comes through which should not! @@ -1265,11 +1279,11 @@ export class KeylayoutToKmnConverter { const amb_3_3_bot = rule.filter((curr, idx) => (curr.rule_type === "C2") && curr.dk_C2 === rule[index].dk_C2 - && rule[index].uniqueB !== 0 && curr.modifier_key === rule[index].modifier_key && curr.key === rule[index].key - && (new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output)) + && new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output) && idx < index + // && rule[index].uniqueB !== 0 ); //3-3 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'Ã' @@ -1282,7 +1296,6 @@ export class KeylayoutToKmnConverter { && new TextDecoder().decode(curr.output) === new TextDecoder().decode(rule[index].output) && idx < index ); - //1-2 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > 'Ñ' const amb_1_2_mid = rule.filter((curr, idx) => ((curr.rule_type === "C0") || (curr.rule_type === "C1")) @@ -1543,7 +1556,7 @@ export class KeylayoutToKmnConverter { let data: string = "" let keymarker: string = "" - const data_CAll: rule_object[] = data_ukelele.ArrayOf_Rules.filter((curr) => { + const data_CAll: rule_object[] = data_ukelele.arrayOf_Rules.filter((curr) => { if ((curr.output !== new TextEncoder().encode("") || curr.output !== undefined) && (curr.rule_type === "C0") || (curr.rule_type === "C1") || (curr.rule_type === "C2") || (curr.rule_type === "C3")) { return curr; @@ -1568,13 +1581,13 @@ export class KeylayoutToKmnConverter { } return unique; }, []); - //const unique_CAll_Rules: rule_object[] = data_ukelele.ArrayOf_Rules + //const unique_CAll_Rules: rule_object[] = data_ukelele.arrayOf_Rules - console.log("xx data_ukelele.ArrayOf_Rules", data_ukelele.ArrayOf_Rules.length) - //console.log("xx data_ukelele.ArrayOf_Rules", this.writeDataset(data_ukelele.ArrayOf_Rules)) + console.log("xx data_ukelele.arrayOf_Rules", data_ukelele.arrayOf_Rules.length) + //console.log("xx data_ukelele.arrayOf_Rules", this.writeDataset(data_ukelele.arrayOf_Rules)) console.log("xx unique_CAll_Rules", unique_CAll_Rules.length) - // console.log("xx unique_CAll_Rules", this.writeDataset(unique_CAll_Rules)) + console.log("xx unique_CAll_Rules", this.writeDataset(unique_CAll_Rules)) //................................................ C0 C1 ................................................................ //................................................ C0 C1 ................................................................ @@ -1669,55 +1682,26 @@ export class KeylayoutToKmnConverter { public createData_Stores(data_ukelele: convert_object): string { - let data: string = "" + let data: string = "" + + data += "c\n" + data += "c Keyman keyboard generated by kmn-convert\n" + data += "c from original file: " + data_ukelele.keylayout_filename + "\n" + data += "c\n" + data += "\n" + + data += "store(&VERSION) \'10.0\'\n" + data += "store(&TARGETS) \'any\'\n" + data += "store(&KEYBOARDVERSION) \'1.0\'\n" + data += "store(©RIGHT) '© 2024 SIL International\'\n" + // TODO what else ?? + + data += "\n" + data += "begin Unicode > use(main)\n\n" + data += "group(main) using keys\n\n" + + data += "\n" - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // ~~~~ draft print ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - if (KeylayoutToKmnConverter.print_draft) { - data += "c\n" - data += "c Keyman keyboard generated by kmn-convert\n" - data += "c\n" - data += "\n" - - data += '\########## OK #################################################################\n' - data += "store(&VERSION) \'10.0\'\n" - data += "store(&TARGETS) \'any\'\n" - data += "store(&KEYBOARDVERSION) \'1.0\'\n" - data += "store(©RIGHT) '© 2024 SIL International\'\n" - // TODO what else ?? - - data += '\########## OK #################################################################\n' - data += "\n" - data += "begin Unicode > use(main)\n\n" - data += "group(main) using keys\n\n" - - data += '\########## OK #################################################################\n' - data += "Tipp: if K_? is replaced by undefined-> no enry in kmn_Key_Name=> add K_? there and it will be shown here\n" - data += "Tipp: keys that are marked with sction do not aoear in ukelele_Array_output->do not appear in kmn\n" - data += "\n" - } - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // ~~~~ draft print end ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - else { - data += "c\n" - data += "c Keyman keyboard generated by kmn-convert\n" - data += "c\n" - data += "\n" - - data += "store(&VERSION) \'10.0\'\n" - data += "store(&TARGETS) \'any\'\n" - data += "store(&KEYBOARDVERSION) \'1.0\'\n" - data += "store(©RIGHT) '© 2024 SIL International\'\n" - // TODO what else ?? - - data += "\n" - data += "begin Unicode > use(main)\n\n" - data += "group(main) using keys\n\n" - - data += "\n" - } return data } From c10313ef24695023398a4dd5c53be4205679d574 Mon Sep 17 00:00:00 2001 From: Sabine Date: Wed, 19 Feb 2025 13:06:34 +0100 Subject: [PATCH 053/251] feat(developer): kmc-convert more tidy up --- .../keylayout-to-kmn-converter.ts | 652 +++++++----------- 1 file changed, 245 insertions(+), 407 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index f269fd86cd1..628efbb8efc 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -6,82 +6,79 @@ import { CompilerCallbacks, CompilerOptions } from "@keymanapp/developer-utils"; import { ConverterToKmnArtifacts } from "../converter-artifacts.js"; -/*import { util } from '@keymanapp/common-types'; //_S2 -import boxXmlArray = util.boxXmlArray;*/ -{ - // TODO keylayout->kmn - // modifiers: The identifier of the element to use for this range of hardware keyboard types. - // defaultIndex: The table number to use for modifier key combinations which are not explicitly specified by any element within the . - // write read, convert, write - // tests for 3 functions read write convert - // add data to object - // Use filter functions - // action/output:use filter etc to shorten func - // deadkeyables:use filter etc to shorten func - // dk-> for all action:use filter etc to shorten func - // remove unneccessary data from dataObject - // rename symbols - // remove part using kmn_key_Name1 - // remove unnecceaasry map_UkeleleKC_To_kmn_Key_Name_Array_Position_n etc - // loop throught ANSI, JIS- at moment only use [keyMapSet_count] (keyMapSet_count=0) - // remove funcs at teh end - // import { makePathToFixture } from '../../test/helpers/index.js'; - // Mapping 0->30 or 0->K_A-> missing entries in mapping - // Replace any-types - // Several steps action-> action-> action->character ( not only action->character) - // TODO waht about using actions twice in a row??? -> error msg if chain >4 - // Usable for all keylayout files - // Return conditions - // Use callbacks as for writeFileSync - // Tests throws - // Conditions NCAPS,OPT;... - // TODO move func outside of class - // Functions as object methods? - // objects contain only used stuff READ in: -- out: only read arrays / CONVERT in: only read arrays out: return only to write arrays - // Use catch blocks for file read - // read: answer : + [K_A] > 'a' is OK / TODO which format to use in output ? + [K_A] > 'a' (character code) or + [K_A] > U+0061 (virt Keycode) - // read TODO which stores? - // one entry vs several entry in tags - // false arrangement of tags ? - // no added NCAPS when first modifier in modifierMap does not contain "caps" or"caps?" - // use length to clear array instead of defining evetry time new (modifierMap_ONE_InKeymapSelect.length=0 - // naming of for-loop var i,j,k?... - // warning if contrADICTING RULES E:G: [ 'modifier_C0', 'SHIFT NCAPS', 'K_C', 'c'], vs [ 'modifier_C0', 'SHIFT NCAPS', 'K_C', 'C' ], - // print NCAPS as the first of the modifiers in create_kmn_modifier - // use boxXmlArray from codebase instead of my own - // where are rules for action+none ( a, e, u, etc) - // order of object member var - // readfilesync with paths better way? - // rearrange code to use read, convert, write - // TODO rewrite explanantion for object instead of array - // remove all any types - // check code for code styles keyman - // public dk: number, //todo remove one - // todo use from elsewhere boxXmlArray_S - // prev_deadkeys_Ch: Uint8Array, /* Todo needed?*/ - // Todo remove print_draft - // TODO throws - // Todo files/path !!! - // TODO need to use export const USVirtualKeyCodes here - // start Tests v ToDo remove...................................... - // TODO remove: test files: checkif kmn gets the same output as ukelele file(except for C3 t works well :)) - // ToDo needed methods - // Filter functions use the same type - // where to put documentation - // dk <-> dk_C2 ??? - // check if we use the same algorithm to get Block1 data - // check uniqueA, uniqueV, dk_prv, dk, dk_C2 - // check duplicate rule conditions which do I need; which can go - // when I run german with uniqueCAll why will there be [ ] without key anf modifier - // 77 replace uniqueA 0, >0 with true, false - // what if keylayout file is not correct e.g missing > - // check for keys < 50 whern working with keys - // add links to HEADLINE of kmc-convert document - - -} -import { XMLParser } from 'fast-xml-parser'; // for reading a file +// TODO keylayout->kmn +// OK modifiers: The identifier of the element to use for this range of hardware keyboard types. +// OK defaultIndex: The table number to use for modifier key combinations which are not explicitly specified by any element within the . +// OK write read, convert, write +// tests for 3 functions read write convert +// OK add data to object +// OK Use filter functions +// OK action/output:use filter etc to shorten func +// OK deadkeyables:use filter etc to shorten func +// OK dk-> for all action:use filter etc to shorten func +// OK remove unneccessary data from dataObject +// rename symbols +// OK remove part using kmn_key_Name1 +// OK remove unnecceaasry map_UkeleleKC_To_kmn_Key_Name_Array_Position_n etc +// OK loop throught ANSI, JIS- at moment only use [keyMapSet_count] (keyMapSet_count=0) +// OK remove funcs at teh end +// OK import { makePathToFixture } from '../../test/helpers/index.js'; +// OK Mapping 0->30 or 0->K_A-> missing entries in mapping +// OK Replace any-types +// OK Several steps action-> action-> action->character ( not only action->character) +// TODO waht about using actions twice in a row??? -> error msg if chain >4 +// OK Usable for all keylayout files +// Return conditions +// OK Use callbacks as for writeFileSync +// Tests throws +// Conditions NCAPS,OPT;... +// TODO move func outside of class +// Functions as object methods? +// objects contain only used stuff READ in: -- out: only read arrays / CONVERT in: only read arrays out: return only to write arrays +// OK Use catch blocks for file read +// OK read: answer : + [K_A] > 'a' is OK / TODO which format to use in output ? + [K_A] > 'a' (character code) or + [K_A] > U+0061 (virt Keycode) +// read TODO which stores? +// OK one entry vs several entry in tags +// false arrangement of tags ? +// OK no added NCAPS when first modifier in modifierMap does not contain "caps" or"caps?" +// use length to clear array instead of defining evetry time new (modifierMap_ONE_InKeymapSelect.length=0 +// OK naming of for-loop var i,j,k?... +// OK warning if contrADICTING RULES E:G: [ 'modifier_C0', 'SHIFT NCAPS', 'K_C', 'c'], vs [ 'modifier_C0', 'SHIFT NCAPS', 'K_C', 'C' ], +// OK print NCAPS as the first of the modifiers in create_kmn_modifier +// OK use boxXmlArray from codebase instead of my own +// OK where are rules for action+none ( a, e, u, etc) +// OK order of object member var +// OK readfilesync with paths better way? +// OK rearrange code to use read, convert, write +// OK TODO rewrite explanantion for object instead of array +// OK remove all any types +// check code for code styles keyman +// public dk: number, //todo remove one +// OK todo use from elsewhere boxXmlArray_S +// OK prev_deadkeys_Ch: Uint8Array, /* Todo needed?*/ +// OK Todo remove print_draft +// TODO throws +// OK Todo files/path !!! +// TODO need to use export const USVirtualKeyCodes here +// start Tests v ToDo remove...................................... +// TODO remove: test files: checkif kmn gets the same output as ukelele file(except for C3 t works well :)) +// ToDo needed methods +// Filter functions use the same type +// where to put documentation +// dk <-> dk_C2 ??? +// check if we use the same algorithm to get Block1 data +// check uniqueA, uniqueV, dk_prv, dk, dk_C2 +// OK check duplicate rule conditions which do I need; which can go +// OK when I run german with uniqueCAll why will there be [ ] without key anf modifier +// replace uniqueA 0, >0 with true, false +// what if keylayout file is not correct e.g missing > +// check for keys < 50 whern working with keys +// add links to HEADLINE of kmc-convert document + +// TODO more Data stores to add ?? + +import { XMLParser } from 'fast-xml-parser'; // for reading an xml file import { readFileSync } from 'fs'; import { util } from '@keymanapp/common-types'; import boxXmlArray = util.boxXmlArray; @@ -131,12 +128,10 @@ export interface convert_object { export class KeylayoutToKmnConverter { + static readonly INPUT_FILE_EXTENSION = '.keylayout'; static readonly OUTPUT_FILE_EXTENSION = '.kmn'; - - //Todo remove print_draft - static print_draft = false - static used_Keys_count = 50 + static readonly USED_KEYS_COUNT = 50 // TODO use callbacks what about /*private*/ for options //constructor(/*private*/ _callbacks: CompilerCallbacks, /*private*/ _options: CompilerOptions) { @@ -165,7 +160,6 @@ export class KeylayoutToKmnConverter { } console.log(' _S2 then CONVERT ........................................'); - //const outArray: convert_object = await this.convert(inArray); const outArray: convert_object = await this.convert(JsonO); if (!outArray) { @@ -199,7 +193,6 @@ export class KeylayoutToKmnConverter { }; try { - //const xmlFile = readFileSync(`${process.cwd()}/data/MySample.keylayout`, 'utf8') xmlFile = readFileSync((process.cwd() + "\\data" + filename.substring(filename.lastIndexOf("\\"))).replace(" ", ""), 'utf8'); const parser = new XMLParser(options); @@ -225,17 +218,17 @@ export class KeylayoutToKmnConverter { public convert(jsonObj: any): convert_object { const jsonObj_any: any = jsonObj - const keylayout_file: string = jsonObj_any.keyboard['@_name'] + ".keylayout" const modifierBehavior: string[][] = [] // modifier for each keymapselect - const RuleObject: rule_object[] = [] // an array of objects which hold data for a kmn rule + const ruleObject: rule_object[] = [] // an array of objects which hold data for a kmn rule + const keylayout_file: string = jsonObj_any.keyboard['@_name'] + ".keylayout" const DataObject: convert_object = { keylayout_filename: keylayout_file, arrayOf_Modifiers: modifierBehavior, // e.g. 18 modifiersCombinations in 8 KeyMapSelect(behaviors) - arrayOf_Rules: RuleObject + arrayOf_Rules: ruleObject }; - // create an array of modifier Combinations (e.g. shift? leftShift caps? ) + // create an array of modifier combinations (e.g. shift? leftShift caps? ) and store in convert_object for (let j = 0; j < jsonObj.keyboard.modifierMap.keyMapSelect.length; j++) { const singleModifierSet: string[] = [] for (let k = 0; k < jsonObj.keyboard.modifierMap.keyMapSelect[j].modifier.length; k++) { @@ -243,7 +236,6 @@ export class KeylayoutToKmnConverter { } modifierBehavior.push(singleModifierSet) } - return this.createRuleData(DataObject, jsonObj) } @@ -261,11 +253,11 @@ export class KeylayoutToKmnConverter { // add top part of kmn file: STORES data += this.createData_Stores(data_ukelele) - // add lower part of kmn file: RULES + // add bottom part of kmn file: RULES data += this.createData_Rules(data_ukelele) /*writeFileSync("data/MyResult.kmn", data, { flag: "w" })*/ - this.callbacks.fs.writeFileSync("data/MyResult.kmn", new TextEncoder().encode(data)) // not usable here since it takes UInt8array data + this.callbacks.fs.writeFileSync("data/MyResult.kmn", new TextEncoder().encode(data)) // ToDo conditions? if (data.length > 0) @@ -296,7 +288,7 @@ export class KeylayoutToKmnConverter { // loop behaviors ( in ukelele it is possible to define multiple modifier combinations that behave in the same) for (let i = 0; i < jsonObj.keyboard.keyMapSet[0].keyMap.length; i++) { // loop keys 0-50 (= all keys we use) - for (let j = 0; j <= KeylayoutToKmnConverter.used_Keys_count; j++) { + for (let j = 0; j <= KeylayoutToKmnConverter.USED_KEYS_COUNT; j++) { if ((jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] !== undefined)) { testArray_Ukelele.push(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output']) @@ -321,7 +313,7 @@ export class KeylayoutToKmnConverter { const isCapsused: boolean = this.checkIfCapsIsUsed(data_ukelele.arrayOf_Modifiers) // loop keys 0-50 (= all keys we use) - for (let j = 0; j <= KeylayoutToKmnConverter.used_Keys_count; j++) { + for (let j = 0; j <= KeylayoutToKmnConverter.USED_KEYS_COUNT; j++) { // loop behaviors (in ukelele it is possible to define multiple modifier combinations that behave in the same way) for (let i = 0; i < jsonObj.keyboard.keyMapSet[0].keyMap.length; i++) { @@ -699,174 +691,20 @@ export class KeylayoutToKmnConverter { } } } - - // --------------------------------------------------------------------------------------------------------------------- - // --------------------------------------------------------------------------------------------------------------------- - - - //--------------------------------------------------------------------------------------------- - //--------------------------------------------------------------------------------------------- - //--------------------------------------------------------------------------------------------- - // TODO remove: test files: checkif kmn gets the same output as ukelele file - //--------------------------------------------------------------------------------------------- - //--------------------------------------------------------------------------------------------- - //--------------------------------------------------------------------------------------------- - /* - //remove entries that are available in both arrays - for (let i = 0; i < (testArray_Ukelele.length); i++) { - for (let j = 0; j < (testArray_kmn.length); j++) { - if (testArray_Ukelele[i] === testArray_kmn[j]) { - testArray_Ukelele[i] = "" - testArray_kmn[j] = "" - } - } - } - // remove empty fields - const testArray_Ukelele_filter = testArray_Ukelele.filter((el) => (el !== "")) - const testArray_kmn_filter = testArray_kmn.filter((el) => (el !== "")) - // should be empty now - if (testArray_kmn_filter.length !== testArray_Ukelele_filter.length) - console.log("OOOOHHHH DIFFERENT AMOUNTS ") - else - console.log("####### SAME AMOUNTS :)) ", - "testArray_kmn_filter:", testArray_kmn_filter, "testArray_Ukelele_filter:", testArray_Ukelele_filter) - - const testArray_Ukelele_action_uni: string[] = testArray_Ukelele_action.filter(function (item, pos, self) { - return self.indexOf(item) == pos; - }) - - //remove entries that are available in both arrays - for (let i = 0; i < (testArray_Ukelele_action_uni.length); i++) { - for (let j = 0; j < (testArray_kmn_action1.length); j++) { - if (testArray_Ukelele_action_uni[i] === testArray_kmn_action1[j]) { - testArray_Ukelele_action_uni[i] = "" - testArray_kmn_action1[j] = "" - } - } - } - // remove empty fields - const testArray_Ukelele_action_uni_filter = testArray_Ukelele_action_uni.filter((el) => (el !== "")) - const testArray_kmn_action_uni_filter = testArray_kmn_action1.filter((el) => (el !== "")) - // should be empty now - if ((testArray_kmn_action_uni_filter.length === 0) && (testArray_Ukelele_action_uni_filter.length === 0)) - console.log("####### SAME AMOUNTS :)) HERE ALSo", - "testArray_kmn_action_uni_filter:", testArray_kmn_action_uni_filter, "testArray_Ukelele_action_uni_filter:", testArray_Ukelele_action_uni_filter) - else - console.log("OOOOHHHH DIFFERENT AMOUNTS ")*/ - - - - // test modifiers - - /* - if (this.create_kmn_modifier("", true) === "NCAPS") console.log("testNr 1 OK "); else console.log("testNr 1 NOT OK - ", (this.create_kmn_modifier("", true))) - if (this.create_kmn_modifier("", false) === "") console.log("testNr 2 OK "); else console.log("testNr 2 NOT OK - ", (this.create_kmn_modifier("", false))) - if (this.create_kmn_modifier("caps", true) === "CAPS") console.log("testNr 5 OK "); else console.log("testNr 5 NOT OK - ", (this.create_kmn_modifier("caps", true))) - if (this.create_kmn_modifier("6caps", true) === "CAPS") console.log("testNr 6 OK "); else console.log("testNr 6 NOT OK - ", (this.create_kmn_modifier("6caps", true))) - if (this.create_kmn_modifier("rightControl", false) === "CTRL") console.log("testNr 13 OK "); else console.log("testNr 13 NOT OK - ", (this.create_kmn_modifier("rightControl", false))) - if (this.create_kmn_modifier("ComMand", false) === "ComMand") console.log("testNr 26 OK "); else console.log("testNr 26 NOT OK - ", (this.create_kmn_modifier("ComMand", false))) - if (this.create_kmn_modifier("rshift?", false) === "") console.log("testNr 19 OK "); else console.log("testNr 19 NOT OK - ", (this.create_kmn_modifier("Shift?", false))) - if (this.create_kmn_modifier("rshift?", true) === "NCAPS") console.log("testNr 20 OK "); else console.log("testNr 20 NOT OK - ", (this.create_kmn_modifier("Shift?", true))) - if (this.create_kmn_modifier("rshift", false) === "SHIFT") console.log("testNr 8 OK "); else console.log("testNr 8 NOT OK - ", (this.create_kmn_modifier("rshift", false))) - if (this.create_kmn_modifier("rightshift", false) === "SHIFT") console.log("testNr 9 OK "); else console.log("testNr 9 NOT OK - ", (this.create_kmn_modifier("rshift", false))) - if (this.create_kmn_modifier("anyOption", false) === "RALT") console.log("testNr 4 OK "); else console.log("testNr 4 NOT OK - ", (this.create_kmn_modifier("anyOption", false))) - if (this.create_kmn_modifier("anyShift", false) === "SHIFT") console.log("testNr 7 OK "); else console.log("testNr 7NOT OK - ", (this.create_kmn_modifier("anyShift", false))) - if (this.create_kmn_modifier("rightShift? rightOption", false) === "RALT") console.log("testNr 17 OK "); else console.log("testNr 17 NOT OK - ", (this.create_kmn_modifier("rightShift? rightOption", false))) - if (this.create_kmn_modifier("option", false) === "RALT") console.log("testNr 15 OK "); else console.log("testNr 15 NOT OK - ", (this.create_kmn_modifier("option", false))) - if (this.create_kmn_modifier("rightOption", false) === "RALT") console.log("testNr 10 OK "); else console.log("testNr 10 NOT OK - ", (this.create_kmn_modifier("rightOption", false))) - if (this.create_kmn_modifier("anyOption", true) === "NCAPS RALT") console.log("testNr 3 OK "); else console.log("testNr 3 NOT OK - ", (this.create_kmn_modifier("anyOption", true))) - if (this.create_kmn_modifier("shift? caps", true) === "CAPS") console.log("testNr 21 OK "); else console.log("testNr 21 NOT OK - ", (this.create_kmn_modifier("shift? caps", true))) - if (this.create_kmn_modifier("caps?", false) === "") console.log("testNr 11 OK "); else console.log("testNr 11 NOT OK - ", (this.create_kmn_modifier("caps?", false))) - if (this.create_kmn_modifier("caps?", false) === "") console.log("testNr 22 OK "); else console.log("testNr 22 NOT OK - ", (this.create_kmn_modifier("caps?", false))) - if (this.create_kmn_modifier("caps?", true) === "NCAPS") console.log("testNr 12 OK "); else console.log("testNr 12 NOT OK - ", (this.create_kmn_modifier("caps?", true))) - if (this.create_kmn_modifier("shift? caps", true) === "CAPS") console.log("testNr 23 OK "); else console.log("testNr 23 NOT OK - ", (this.create_kmn_modifier("shift? caps", true))) - if (this.create_kmn_modifier("shift? caps", false) === "CAPS") console.log("testNr 24 OK "); else console.log("testNr 24 NOT OK - ", (this.create_kmn_modifier("shift? caps", false))) - if (this.create_kmn_modifier("shift caps?", true) === "SHIFT NCAPS") console.log("testNr 28 OK "); else console.log("testNr 28 NOT OK - ", (this.create_kmn_modifier("shift caps?", true))) - if (this.create_kmn_modifier("shift", true) === "NCAPS SHIFT") console.log("testNr 29 OK "); else console.log("testNr 29 NOT OK - ", (this.create_kmn_modifier("shift", true))) - if (this.create_kmn_modifier("shift", true) === "NCAPS SHIFT") console.log("testNr 30 OK "); else console.log("testNr 30 NOT OK - ", (this.create_kmn_modifier("shift", true))) - if (this.create_kmn_modifier("shift caps?", true) === "SHIFT NCAPS") console.log("testNr 27 OK "); else console.log("testNr 27 NOT OK - ", (this.create_kmn_modifier("shift caps?", true))) - if (this.create_kmn_modifier("rightShift anyOption", false) === "SHIFT RALT") console.log("testNr 18 OK "); else console.log("testNr 18 NOT OK - ", (this.create_kmn_modifier("rightShift anyOption", false))) - if (this.create_kmn_modifier("rightControl", true) === "NCAPS CTRL") console.log("testNr 14 OK "); else console.log("testNr 14 NOT OK - ", (this.create_kmn_modifier("rightControl", true))) - if (this.create_kmn_modifier("Caps", true) === "CAPS") console.log("testNr 28 OK "); else console.log("testNr 28 NOT OK - ", (this.create_kmn_modifier("Caps", true))) - if (this.create_kmn_modifier("caps", true) === "CAPS") console.log("testNr 31 OK "); else console.log("testNr 31 NOT OK - ", (this.create_kmn_modifier("Caps", true))) - if (this.create_kmn_modifier("anyOption", true) === "NCAPS RALT") console.log("testNr 32 OK "); else console.log("testNr 32 NOT OK - ", (this.create_kmn_modifier("anyOption", true))) - if (this.create_kmn_modifier("anyOption", false) === "RALT") console.log("testNr 32 OK "); else console.log("testNr 32 NOT OK - ", (this.create_kmn_modifier("anyOption", false))) - if (this.create_kmn_modifier("Caps", true) === "CAPS") console.log("testNr 33 OK "); else console.log("testNr 33 NOT OK - ", (this.create_kmn_modifier("Caps", true))) - if (this.create_kmn_modifier("caps", false) === "CAPS") console.log("testNr 34 OK "); else console.log("testNr 34 NOT OK - ", (this.create_kmn_modifier("Caps", false))) - if (this.create_kmn_modifier("shift rightShift", false) === "SHIFT") console.log("testNr 25 OK "); else console.log("testNr 25 NOT OK - ", (this.create_kmn_modifier("shift rightShift", false))) - - if (this.create_kmn_modifier("shift? caps?", true) === "NCAPS") console.log("testNr 18 OK "); else console.log("testNr 18 NOT OK - ", (this.create_kmn_modifier("shift? caps?", true))) - if (this.create_kmn_modifier("shift? caps?", false) === "") console.log("testNr 18a OK "); else console.log("testNr 18a NOT OK - ", (this.create_kmn_modifier("shift? caps?", false))) - - if (this.create_kmn_modifier("", true) === "NCAPS") console.log("testNr 40 OK "); else console.log("testNr 40 NOT OK - ", (this.create_kmn_modifier("", true))) - if (this.create_kmn_modifier("shift? caps? ", true) === "NCAPS") console.log("testNr 41 OK "); else console.log("testNr 41 NOT OK - ", (this.create_kmn_modifier("shift? caps? ", true))) - if (this.create_kmn_modifier("anyShift caps?", true) === "SHIFT NCAPS") console.log("testNr 42 OK "); else console.log("testNr 42 NOT OK - ", (this.create_kmn_modifier("anyShift caps?", true))) - if (this.create_kmn_modifier("shift? rightShift caps?", true) === "SHIFT NCAPS") console.log("testNr 44 OK "); else console.log("testNr 44 NOT OK - ", (this.create_kmn_modifier("shift? rightShift caps?", true))) - if (this.create_kmn_modifier("shift? leftShift caps?", true) === "SHIFT NCAPS") console.log("testNr 45 OK "); else console.log("testNr 45 NOT OK - ", (this.create_kmn_modifier("shift? leftShift caps?", true))) - if (this.create_kmn_modifier("shift leftShift caps ", true) === "SHIFT CAPS") console.log("testNr 46 OK "); else console.log("testNr 46 NOT OK - ", (this.create_kmn_modifier("shift leftShift caps ", true))) - if (this.create_kmn_modifier("caps", true) === "CAPS") console.log("testNr 47 OK "); else console.log("testNr 47 NOT OK - ", (this.create_kmn_modifier("caps", true))) - if (this.create_kmn_modifier("anyOption", true) === "NCAPS RALT") console.log("testNr 48 OK "); else console.log("testNr 48 NOT OK - ", (this.create_kmn_modifier("anyOption", true))) - if (this.create_kmn_modifier("Caps", true) === "CAPS") console.log("testNr 49 OK "); else console.log("testNr 49 NOT OK - ", (this.create_kmn_modifier("Caps", true))) - if (this.create_kmn_modifier("anyShift caps? anyOption ?", true) === "SHIFT NCAPS RALT") console.log("testNr 50 OK "); else console.log("testNr 50 NOT OK - ", (this.create_kmn_modifier("anyShift caps? anyOption ?", true))) - if (this.create_kmn_modifier("caps anyOption ?", true) === "CAPS RALT") console.log("testNr 51 OK "); else console.log("testNr 51 NOT OK - ", (this.create_kmn_modifier("caps anyOption ?", true))) - if (this.create_kmn_modifier("anyShift? caps? anyOption? anyControl", true) === "NCAPS CTRL") console.log("testNr 52 OK "); else console.log("testNr 52 NOT OK - ", (this.create_kmn_modifier("anyShift? caps? anyOption? anyControl", true))) - if (this.create_kmn_modifier("anyShift? caps? anyOption anyControl", true) === "NCAPS RALT CTRL") console.log("testNr 53 OK "); else console.log("testNr 53 NOT OK - ", (this.create_kmn_modifier("anyShift? caps? anyOption anyControl", true))) - if (this.create_kmn_modifier("command", false) === "command") console.log("testNr 16 OK "); else console.log("testNr 16 NOT OK - ", (this.create_kmn_modifier("command", false))) - if (this.create_kmn_modifier("XXX", false) === "command") console.log("testNr 16 OK "); else console.log("testNr 16 NOT OK - ", (this.create_kmn_modifier("XXX", false))) - - - if (this.create_kmn_modifier("", false) === "") console.log("testNr 40 OK "); else console.log("testNr 40 NOT OK - ", (this.create_kmn_modifier("", false))) - if (this.create_kmn_modifier("shift? caps? ", false) === "") console.log("testNr 41 OK "); else console.log("testNr 41 NOT OK - ", (this.create_kmn_modifier("shift? caps? ", false))) - if (this.create_kmn_modifier("anyShift caps?", false) === "SHIFT") console.log("testNr 42 OK "); else console.log("testNr 42 NOT OK - ", (this.create_kmn_modifier("anyShift caps?", false))) - if (this.create_kmn_modifier("shift? rightShift caps?", false) === "SHIFT") console.log("testNr 44 OK "); else console.log("testNr 44 NOT OK - ", (this.create_kmn_modifier("shift? rightShift caps?", false))) - if (this.create_kmn_modifier("shift? leftShift caps?", false) === "SHIFT") console.log("testNr 45 OK "); else console.log("testNr 45 NOT OK - ", (this.create_kmn_modifier("shift? leftShift caps?", false))) - if (this.create_kmn_modifier("shift leftShift caps ", false) === "SHIFT CAPS") console.log("testNr 46 OK "); else console.log("testNr 46 NOT OK - ", (this.create_kmn_modifier("shift leftShift caps ", false))) - if (this.create_kmn_modifier("caps", false) === "CAPS") console.log("testNr 47 OK "); else console.log("testNr 47 NOT OK - ", (this.create_kmn_modifier("caps", false))) - if (this.create_kmn_modifier("anyOption", false) === "RALT") console.log("testNr 48 OK "); else console.log("testNr 48 NOT OK - ", (this.create_kmn_modifier("anyOption", false))) - if (this.create_kmn_modifier("Caps", false) === "CAPS") console.log("testNr 49 OK "); else console.log("testNr 49 NOT OK - ", (this.create_kmn_modifier("Caps", false))) - if (this.create_kmn_modifier("anyShift caps? anyOption ?", false) === "SHIFT RALT") console.log("testNr 50 OK "); else console.log("testNr 50 NOT OK - ", (this.create_kmn_modifier("anyShift caps? anyOption ?", false))) - if (this.create_kmn_modifier("caps anyOption ?", false) === "CAPS RALT") console.log("testNr 51 OK "); else console.log("testNr 51 NOT OK - ", (this.create_kmn_modifier("caps anyOption ?", false))) - if (this.create_kmn_modifier("anyShift? caps? anyOption? anyControl", false) === "CTRL") console.log("testNr 52 OK "); else console.log("testNr 52 NOT OK - ", (this.create_kmn_modifier("anyShift? caps? anyOption? anyControl", false))) - if (this.create_kmn_modifier("anyShift? caps? anyOption anyControl", false) === "RALT CTRL") console.log("testNr 53 OK "); else console.log("testNr 53 NOT OK - ", (this.create_kmn_modifier("anyShift? caps? anyOption anyControl", false))) - if (this.create_kmn_modifier("CAPS", false) === "CAPS") console.log("testNr 531 OK "); else console.log("testNr 531 NOT OK - ", (this.create_kmn_modifier("CAPS", true))) - if (this.create_kmn_modifier("shift leftShift caps", false) === "SHIFT CAPS") console.log("testNr 532 OK "); else console.log("testNr 532 NOT OK - ", (this.create_kmn_modifier("shift leftShift caps", false))) - if (this.create_kmn_modifier("shift leftShift caps", true) === "SHIFT CAPS") console.log("testNr 532 OK "); else console.log("testNr 532 NOT OK - ", (this.create_kmn_modifier("shift leftShift caps", true))) - - console.log("------------------ ") - - if (this.isAcceptableKeymanModifier("SHIFT CAPS") === true) console.log("testNr A 1 OK "); else console.log("testNr A 1 NOT OK - ", (this.isAcceptableKeymanModifier("SHIFT CAPS"))) - if (this.isAcceptableKeymanModifier("SHIFT") === true) console.log("testNr A 2 OK "); else console.log("testNr A 2 NOT OK - ", (this.isAcceptableKeymanModifier("SHIFT"))) - if (this.isAcceptableKeymanModifier("shift") === true) console.log("testNr A 12 OK "); else console.log("testNr A 12 NOT OK - ", (this.isAcceptableKeymanModifier("shift"))) - if (this.isAcceptableKeymanModifier("SHIFT ") === true) console.log("testNr A 3 OK "); else console.log("testNr A 3 NOT OK - ", (this.isAcceptableKeymanModifier("SHIFT "))) - if (this.isAcceptableKeymanModifier(" SHIFT ") === true) console.log("testNr A 10 OK "); else console.log("testNr A 10 NOT OK - ", (this.isAcceptableKeymanModifier(" SHIFT "))) - if (this.isAcceptableKeymanModifier(" SHIFT") === true) console.log("testNr A 11 OK "); else console.log("testNr A 11 NOT OK - ", (this.isAcceptableKeymanModifier(" SHIFT"))) - if (this.isAcceptableKeymanModifier("rightshift") === false) console.log("testNr A 4 OK "); else console.log("testNr A 4 NOT OK - ", (this.isAcceptableKeymanModifier("rightshift"))) - if (this.isAcceptableKeymanModifier("rightshift ") === false) console.log("testNr A 5 OK "); else console.log("testNr A 5 NOT OK - ", (this.isAcceptableKeymanModifier("rightshift "))) - if (this.isAcceptableKeymanModifier(" ") === true) console.log("testNr A 6 OK "); else console.log("testNr A 6 NOT OK - ", (this.isAcceptableKeymanModifier(" "))) - if (this.isAcceptableKeymanModifier("") === true) console.log("testNr A 7 OK "); else console.log("testNr A 7 NOT OK - ", (this.isAcceptableKeymanModifier(""))) - if (this.isAcceptableKeymanModifier("rightoption") === false) console.log("testNr A 8 OK "); else console.log("testNr A 8 NOT OK - ", (this.isAcceptableKeymanModifier("rightoption"))) - if (this.isAcceptableKeymanModifier("abc") === false) console.log("testNr A 9 OK "); else console.log("testNr A 9 NOT OK - ", (this.isAcceptableKeymanModifier("abc"))) - if (this.isAcceptableKeymanModifier("ralt") === true) console.log("testNr A 13 OK "); else console.log("testNr A 13 NOT OK - ", (this.isAcceptableKeymanModifier("ralt"))) - */ - - //--------------------------------------------------------------------------------------------- - //--------------------------------------------------------------------------------------------- - //--------------------------------------------------------------------------------------------- - // Test files end - //--------------------------------------------------------------------------------------------- - //--------------------------------------------------------------------------------------------- - //--------------------------------------------------------------------------------------------- - data_ukelele.arrayOf_Rules = ObjectArray return data_ukelele } + + // --------------------------------------------------------------------------------------------------------------------- + // --------------------------------------------------------------------------------------------------------------------- + public get_KecCode_arr__From__ActionId(data: any, search: string): string[] { const returnarray: string[] = [] for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { - if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'] < KeylayoutToKmnConverter.used_Keys_count) { + if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'] < KeylayoutToKmnConverter.USED_KEYS_COUNT) { returnarray.push(this.map_UkeleleKC_To_VK(Number(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']))) } } @@ -879,7 +717,7 @@ export class KeylayoutToKmnConverter { for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { - if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'] < KeylayoutToKmnConverter.used_Keys_count) { + if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'] < KeylayoutToKmnConverter.USED_KEYS_COUNT) { returnarray.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']) } } @@ -894,12 +732,11 @@ export class KeylayoutToKmnConverter { for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { const returnarray: string[] = [] if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search[k][0]) { - if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'] < KeylayoutToKmnConverter.used_Keys_count) { + if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'] < KeylayoutToKmnConverter.USED_KEYS_COUNT) { returnarray.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']) returnarray.push(this.map_UkeleleKC_To_VK(Number(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']))) returnarray.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action']) returnarray.push(data.keyboard.keyMapSet[0].keyMap[i]['@_index']) - returnarray.push(search[k][2]) } } @@ -1004,7 +841,7 @@ export class KeylayoutToKmnConverter { // loop behaviors ( in ukelele it is possible to define multiple modifier combinations that behave in the same) for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { - for (let j = 0; j <= KeylayoutToKmnConverter.used_Keys_count; j++) { + for (let j = 0; j <= KeylayoutToKmnConverter.USED_KEYS_COUNT; j++) { if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { for (let k = 0; k < modi[data.keyboard.keyMapSet[0].keyMap[i]['@_index']].length; k++) { const returnarray: string[] = [] @@ -1025,7 +862,6 @@ export class KeylayoutToKmnConverter { } } } - // remove duplicates const [unique_returnarray] = returnarray2D.reduce((acc, curr) => { const [uniq, set] = acc; @@ -1096,24 +932,29 @@ export class KeylayoutToKmnConverter { for (let i = 0; i < modifier_state.length; i++) { - if (isCAPSused && (String(keylayout_modifier).toUpperCase().indexOf("CAPS") === -1)) + if (isCAPSused && (keylayout_modifier).toUpperCase().indexOf("CAPS") === -1) kmn_ncaps = " NCAPS " // if we find a modifier containing a '?' e.g. SHIFT?: => SHIFT is not neccessary. If it is not neccessary we don`t write this modifier - if ((String(modifier_state[i]).toUpperCase().includes('?') && (!String(modifier_state[i]).toUpperCase().includes('CAPS?')))) add_modifier = ""; + if (modifier_state[i].toUpperCase().includes('?') && (!modifier_state[i].toUpperCase().includes('CAPS?'))) add_modifier = ""; // TODO is this correct: caps? => caps is not neccessary. If its not neccessary and isCAPSused we need to write out NCAPS. Correct? - else if ((isCAPSused) && (String(modifier_state[i]).toUpperCase().includes('CAPS?'))) add_modifier = "NCAPS "; - else if ((!isCAPSused) && (String(modifier_state[i]).toUpperCase().includes('CAPS?'))) add_modifier = ""; - else if ((String(modifier_state[i]).toUpperCase().includes('CAPS'))) add_modifier = "CAPS "; - else if ((isCAPSused) && (String(modifier_state[i]).toUpperCase().includes('NCAPS'))) add_modifier = "NCAPS "; - - // we do not use the right or left version of a modifier ( e.g. rightshift, leftshift). If they are used in keylayout files they will not be changed but used as is. - // Later when we write out the rules to the kmn file instead of writing those rules we print out a warning - else if ((String(modifier_state[i]).toUpperCase() === 'ANYOPTION') || (String(modifier_state[i]).toUpperCase() === 'OPTION')) add_modifier = "RALT "; - else if ((String(modifier_state[i]).toUpperCase() === 'RIGHTOPTION')) add_modifier = "RALT "; - else if ((String(modifier_state[i]).toUpperCase() === 'ANYSHIFT') || (String(modifier_state[i]).toUpperCase() === 'SHIFT')) add_modifier = "SHIFT "; - else if ((String(modifier_state[i]).toUpperCase() === 'ANYCONTROL') || (String(modifier_state[i]).toUpperCase() === 'CONTROL')) add_modifier = "RCTRL "; + else if (isCAPSused && (modifier_state[i].toUpperCase().includes('CAPS?'))) add_modifier = "NCAPS "; + else if (!isCAPSused && (modifier_state[i].toUpperCase().includes('CAPS?'))) add_modifier = ""; + else if (modifier_state[i].toUpperCase().includes('CAPS')) add_modifier = "CAPS "; + else if (isCAPSused && (modifier_state[i].toUpperCase().includes('NCAPS'))) add_modifier = "NCAPS "; + + // Keyman does not use the right or left version of a modifier (e.g. rightshift, leftshift). If those are used in keylayout files + // they will not be changed but written to the kmn as they are with a warning placed in front of them + else if ((modifier_state[i].toUpperCase() === 'ANYSHIFT') || (modifier_state[i].toUpperCase() === 'SHIFT')) add_modifier = "SHIFT "; + else if ((modifier_state[i].toUpperCase() === "LEFTSHIFT") || (modifier_state[i].toUpperCase() === "LSHIFT")) add_modifier = "SHIFT "; + else if ((modifier_state[i].toUpperCase() === "RIGHTSHIFT") || (modifier_state[i].toUpperCase() === "RSHIFT")) add_modifier = "SHIFT "; + else if ((modifier_state[i].toUpperCase() === 'ANYCONTROL') || (modifier_state[i].toUpperCase() === 'CONTROL')) add_modifier = "RCTRL "; + else if ((modifier_state[i].toUpperCase() === "LEFTCONTROL") || (modifier_state[i].toUpperCase() === "LCONTROL")) add_modifier = "CTRL "; + else if ((modifier_state[i].toUpperCase() === "RIGHTCONTROL") || (modifier_state[i].toUpperCase() === "LCONTROL")) add_modifier = "CTRL "; + else if ((modifier_state[i].toUpperCase() === "LEFTOPTION") || (modifier_state[i].toUpperCase() === "LOPTION")) add_modifier = "RALT "; + else if ((modifier_state[i].toUpperCase() === "RIGHTOPTION") || (modifier_state[i].toUpperCase() === "ROPTION")) add_modifier = "RALT "; + else if ((modifier_state[i].toUpperCase() === 'ANYOPTION') || (modifier_state[i].toUpperCase() === 'OPTION')) add_modifier = "RALT "; else add_modifier = String(modifier_state[i]) + " " kmn_modifier += kmn_ncaps + add_modifier @@ -1121,36 +962,16 @@ export class KeylayoutToKmnConverter { // remove duplicate and empty entries const duplicate_modifier_array: string[] = kmn_modifier.split(" ").filter(item => item) - const unique_Modifier: string[] = duplicate_modifier_array.filter(function (item, pos, self) { - return self.indexOf(item) === pos; // ToDo == or === ???? - }) - - //ToDo review lower part - const unique_Modifier_string: string = unique_Modifier.join(" ").replace(/\s+/g, " ").trim() - - const modifier_array: string[] = unique_Modifier_string.split(" "); - - for (let i = 0; i < modifier_array.length; i++) { - if ((modifier_array[i].toUpperCase() === "RIGHTSHIFT") || (modifier_array[i].toUpperCase() === "RSHIFT")) modifier_array[i] = "SHIFT" - else if ((modifier_array[i].toUpperCase() === "LEFTSHIFT") || (modifier_array[i].toUpperCase() === "LSHIFT")) modifier_array[i] = "SHIFT" - else if ((modifier_array[i].toUpperCase() === "LEFTCONTROL") || (modifier_array[i].toUpperCase() === "LCONTROL")) modifier_array[i] = "CTRL" - else if ((modifier_array[i].toUpperCase() === "RIGHTCONTROL") || (modifier_array[i].toUpperCase() === "LCONTROL")) modifier_array[i] = "CTRL" - else if ((modifier_array[i].toUpperCase() === "LEFTOPTION") || (modifier_array[i].toUpperCase() === "LOPTION")) modifier_array[i] = "RALT" - else if ((modifier_array[i].toUpperCase() === "RIGHTOPTION") || (modifier_array[i].toUpperCase() === "ROPTION")) modifier_array[i] = "RALT" - } - - const unique_modifier_array: string[] = modifier_array.filter(function (item, pos, self) { - return self.indexOf(item) == pos; + const unique_modifier: string[] = duplicate_modifier_array.filter(function (item, pos, self) { + return self.indexOf(item) === pos; }) - - return unique_modifier_array.flat().toString().replace(/,/g, " ") + return unique_modifier.flat().toString().replace(/,/g, " ") } public checkIfCapsIsUsed(keylayout_modifier: string[][]): boolean { return JSON.stringify(keylayout_modifier).includes("caps") } - // todo check conditions command comes through which should not! public isAcceptableKeymanModifier(keylayout_modifier: string): boolean { let iskKeymanModifier: boolean = true const modifier_single: string[] = keylayout_modifier.split(" "); @@ -1168,8 +989,12 @@ export class KeylayoutToKmnConverter { || (modifier_single[i].toUpperCase() === "RCTRL") || (modifier_single[i].toUpperCase() === "") - ) { iskKeymanModifier = iskKeymanModifier && true } - else { iskKeymanModifier = iskKeymanModifier && false } + ) { + iskKeymanModifier &&= true + } + else { + iskKeymanModifier &&= false + } } return iskKeymanModifier } @@ -1177,50 +1002,52 @@ export class KeylayoutToKmnConverter { // definition of comparisons 1-1, 2-4, 6-6, ... see https://docs.google.com/document/d/12J3NGO6RxIthCpZDTR8FYSRjiMgXJDLwPY2z9xqKzJ0/edit?tab=t.0 // todo remove comments n filters after check of several keylayout files public reviewRules(rule: rule_object[], index: number): string[] { + const warningTextArray: string[] = Array(3).fill(""); // +++++++++++++++++++++++++ check unavailable modifiers ++++++++++++++++++++++++++++++++++++++ - if (((rule[index].rule_type === "C0") || (rule[index].rule_type === "C1") || (rule[index].rule_type === "C4"))) { + // Todo remoce C1-C3's and other markers + if ((rule[index].rule_type === "C0") || (rule[index].rule_type === "C1")) { - if (!(this.isAcceptableKeymanModifier(rule[index].modifier_key))) { + if (!this.isAcceptableKeymanModifier(rule[index].modifier_key)) { warningTextArray[2] = "C1 unavailable modifier in: " } } if (rule[index].rule_type === "C2") { if - (!(this.isAcceptableKeymanModifier(rule[index].modifier_deadkey))) { + (!this.isAcceptableKeymanModifier(rule[index].modifier_deadkey)) { warningTextArray[1] = "C2 unavailable modifier in: " } - if (!(this.isAcceptableKeymanModifier(rule[index].modifier_key))) { + if (!this.isAcceptableKeymanModifier(rule[index].modifier_key)) { warningTextArray[2] = "C2 unavailable modifier in: " } } - if (rule[index].rule_type === "C3") { - if (!(this.isAcceptableKeymanModifier(rule[index].modifier_prev_deadkey))) { + if (!this.isAcceptableKeymanModifier(rule[index].modifier_prev_deadkey)) { warningTextArray[2] = "C3 unavailable modifier in: " } - if (!(this.isAcceptableKeymanModifier(rule[index].modifier_deadkey))) { + if (!this.isAcceptableKeymanModifier(rule[index].modifier_deadkey)) { warningTextArray[1] = "C3 unavailable modifier in: " } - if (!(this.isAcceptableKeymanModifier(rule[index].modifier_key))) { + if (!this.isAcceptableKeymanModifier(rule[index].modifier_key)) { warningTextArray[0] = "C3 unavailable modifier in: " } - } + + // +++++++++++++++++++++++++ check ambiguous/duplicate rules ++++++++++++++++++++++++++++++++++++++ - if (((rule[index].rule_type === "C0") || (rule[index].rule_type === "C1"))) { + if ((rule[index].rule_type === "C0") || (rule[index].rule_type === "C1")) { // 1-1 + [CAPS K_N] > 'N' <-> + [CAPS K_N] > 'A' - const amb_1_1_bot = rule.filter((curr, idx) => ( + const amb_1_1 = rule.filter((curr, idx) => ( curr.rule_type === "C0" || curr.rule_type === "C1") && curr.modifier_prev_deadkey === "" && curr.prev_deadkey === "" @@ -1233,7 +1060,7 @@ export class KeylayoutToKmnConverter { ); // 1-1 + [CAPS K_N] > 'N' <-> + [CAPS K_N] > 'N' - const dup_1_1_bot = rule.filter((curr, idx) => + const dup_1_1 = rule.filter((curr, idx) => (curr.rule_type === "C0" || curr.rule_type === "C1") && curr.modifier_prev_deadkey === "" && curr.prev_deadkey === "" @@ -1245,19 +1072,19 @@ export class KeylayoutToKmnConverter { && idx < index ); - if (amb_1_1_bot.length > 0) { - warningTextArray[2] = warningTextArray[2] + ("C1 ambiguous 1-1 rule: earlier: [" + amb_1_1_bot[0].modifier_key + " " + amb_1_1_bot[0].key + "] > \'" + new TextDecoder().decode(amb_1_1_bot[0].output) + "\' here: [") + if (amb_1_1.length > 0) { + warningTextArray[2] = warningTextArray[2] + ("C1 ambiguous 1-1 rule: earlier: [" + amb_1_1[0].modifier_key + " " + amb_1_1[0].key + "] > \'" + new TextDecoder().decode(amb_1_1[0].output) + "\' here: [") } - if (dup_1_1_bot.length > 0) { - warningTextArray[2] = warningTextArray[2] + ("C1 duplicate 1-1 rule: earlier: [" + dup_1_1_bot[0].modifier_key + " " + dup_1_1_bot[0].key + "] > \'" + new TextDecoder().decode(dup_1_1_bot[0].output) + "\' here: [") + if (dup_1_1.length > 0) { + warningTextArray[2] = warningTextArray[2] + ("C1 duplicate 1-1 rule: earlier: [" + dup_1_1[0].modifier_key + " " + dup_1_1[0].key + "] > \'" + new TextDecoder().decode(dup_1_1[0].output) + "\' here: [") } } if (rule[index].rule_type === "C2") { // 2-2 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(C1) - const amb_2_2_mid = rule.filter((curr, idx) => + const amb_2_2 = rule.filter((curr, idx) => curr.rule_type === "C2" && curr.modifier_deadkey === rule[index].modifier_deadkey && curr.deadkey === rule[index].deadkey @@ -1276,7 +1103,7 @@ export class KeylayoutToKmnConverter { ); //3-3 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'B' - const amb_3_3_bot = rule.filter((curr, idx) => + const amb_3_3 = rule.filter((curr, idx) => (curr.rule_type === "C2") && curr.dk_C2 === rule[index].dk_C2 && curr.modifier_key === rule[index].modifier_key @@ -1287,7 +1114,7 @@ export class KeylayoutToKmnConverter { ); //3-3 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'Ã' - const dup_3_3_bot = rule.filter((curr, idx) => + const dup_3_3 = rule.filter((curr, idx) => (curr.rule_type === "C2") && curr.dk_C2 === rule[index].dk_C2 && rule[index].uniqueB === 0 @@ -1296,8 +1123,9 @@ export class KeylayoutToKmnConverter { && new TextDecoder().decode(curr.output) === new TextDecoder().decode(rule[index].output) && idx < index ); + //1-2 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > 'Ñ' - const amb_1_2_mid = rule.filter((curr, idx) => + const amb_1_2 = rule.filter((curr, idx) => ((curr.rule_type === "C0") || (curr.rule_type === "C1")) && curr.modifier_key === rule[index].modifier_deadkey && curr.key === rule[index].deadkey @@ -1305,27 +1133,27 @@ export class KeylayoutToKmnConverter { //&& (idx < index) // include and the first occurance will be printed ); - if (amb_2_2_mid.length > 0) { - warningTextArray[1] = warningTextArray[1] + ("C2 SECONDTEXT " + "ambiguous 2-2 rule: earlier: [" + amb_2_2_mid[0].modifier_deadkey + " " + amb_2_2_mid[0].deadkey + "] > dk(C" + amb_2_2_mid[0].dk_C2 + ") here: ") + if (amb_2_2.length > 0) { + warningTextArray[1] = warningTextArray[1] + ("C2 SECONDTEXT " + "ambiguous 2-2 rule: earlier: [" + amb_2_2[0].modifier_deadkey + " " + amb_2_2[0].deadkey + "] > dk(C" + amb_2_2[0].dk_C2 + ") here: ") } if (dup_2_2.length > 0) { warningTextArray[1] = warningTextArray[1] + ("C2 SECONDTEXT " + "duplicate 2-2 rule: earlier: [" + dup_2_2[0].modifier_deadkey + " " + dup_2_2[0].deadkey + "] > dk(C" + dup_2_2[0].dk_C2 + ") here: ") } - if (amb_3_3_bot.length > 0) { - warningTextArray[2] = warningTextArray[2] + ("C2 THIRDTEXT " + "ambiguous y 3-3 rule: earlier: dk(C" + amb_3_3_bot[0].dk_C2 + ") + [" + amb_3_3_bot[0].modifier_key + " " + amb_3_3_bot[0].key + "] > \'" + new TextDecoder().decode(amb_3_3_bot[0].output) + "\' here: ") + if (amb_3_3.length > 0) { + warningTextArray[2] = warningTextArray[2] + ("C2 THIRDTEXT " + "ambiguous y 3-3 rule: earlier: dk(C" + amb_3_3[0].dk_C2 + ") + [" + amb_3_3[0].modifier_key + " " + amb_3_3[0].key + "] > \'" + new TextDecoder().decode(amb_3_3[0].output) + "\' here: ") } - if (dup_3_3_bot.length > 0) { - warningTextArray[2] = warningTextArray[2] + ("C2 THIRDTEXT " + "duplicate y 3-3 rule: earlier: dk(C" + dup_3_3_bot[0].dk_C2 + ") + [" + dup_3_3_bot[0].modifier_key + " " + dup_3_3_bot[0].key + "] > \'" + new TextDecoder().decode(dup_3_3_bot[0].output) + "\' here: ") + if (dup_3_3.length > 0) { + warningTextArray[2] = warningTextArray[2] + ("C2 THIRDTEXT " + "duplicate y 3-3 rule: earlier: dk(C" + dup_3_3[0].dk_C2 + ") + [" + dup_3_3[0].modifier_key + " " + dup_3_3[0].key + "] > \'" + new TextDecoder().decode(dup_3_3[0].output) + "\' here: ") } - if (amb_1_2_mid.length > 0) { - warningTextArray[1] = warningTextArray[1] + ("C2 SECONDTEXT " + "ambiguous 1-2 rule: earlier: [" + amb_1_2_mid[0].modifier_key + " " + amb_1_2_mid[0].key + "] > \'" + new TextDecoder().decode(amb_1_2_mid[0].output) + "\' here: ") + if (amb_1_2.length > 0) { + warningTextArray[1] = warningTextArray[1] + ("C2 SECONDTEXT " + "ambiguous 1-2 rule: earlier: [" + amb_1_2[0].modifier_key + " " + amb_1_2[0].key + "] > \'" + new TextDecoder().decode(amb_1_2[0].output) + "\' here: ") } } if (rule[index].rule_type === "C3") { // 1-4 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > 'Ñ' - const amb_1_4_mid = rule.filter((curr, idx) => + const amb_1_4 = rule.filter((curr, idx) => ((curr.rule_type === "C0") || (curr.rule_type === "C1")) && curr.modifier_key === rule[index].modifier_prev_deadkey && curr.key === rule[index].prev_deadkey @@ -1334,7 +1162,7 @@ export class KeylayoutToKmnConverter { ); // 2-4 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(C1) - const amb_2_4_mid = rule.filter((curr, idx) => + const amb_2_4 = rule.filter((curr, idx) => ((curr.rule_type === "C2")) && curr.modifier_deadkey === rule[index].modifier_prev_deadkey && curr.deadkey === rule[index].prev_deadkey @@ -1344,7 +1172,7 @@ export class KeylayoutToKmnConverter { ); // 6-3 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'B' - const dup_6_3_bot = rule.filter((curr, idx) => + const amb_6_3 = rule.filter((curr, idx) => (curr.rule_type === "C2") && curr.dk_prev === rule[index].dk_prev && curr.modifier_key === rule[index].modifier_key @@ -1355,7 +1183,7 @@ export class KeylayoutToKmnConverter { ); // 6-3 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'Ã' - const dup_6_3_mid = rule.filter((curr, idx) => + const dup_6_3 = rule.filter((curr, idx) => (curr.rule_type === "C2") && curr.dk_prev === rule[index].dk_prev && curr.modifier_key === rule[index].modifier_key @@ -1376,7 +1204,7 @@ export class KeylayoutToKmnConverter { ); // 4-4 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(C11) - const dup_4_4_mid = rule.filter((curr, idx) => + const dup_4_4 = rule.filter((curr, idx) => curr.rule_type === "C3" && curr.modifier_prev_deadkey === rule[index].modifier_prev_deadkey && curr.prev_deadkey === rule[index].prev_deadkey @@ -1386,7 +1214,7 @@ export class KeylayoutToKmnConverter { ); // 6-6 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'B' - const amb_6_6_bot = rule.filter((curr, idx) => + const amb_6_6 = rule.filter((curr, idx) => (curr.rule_type === "C3") && curr.dk_C2 === rule[index].dk_C2 && rule[index].uniqueA !== 0 @@ -1399,7 +1227,7 @@ export class KeylayoutToKmnConverter { ); // 6-6 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'Ã' - const dup_6_6_bot = rule.filter((curr, idx) => + const dup_6_6 = rule.filter((curr, idx) => (curr.rule_type === "C3") && curr.dk_C2 === rule[index].dk_C2 && curr.modifier_key === rule[index].modifier_key @@ -1409,7 +1237,7 @@ export class KeylayoutToKmnConverter { ); // 5-5 - const amb_5_5_mid = rule.filter((curr, idx) => + const amb_5_5 = rule.filter((curr, idx) => (curr.rule_type === "C3") && curr.modifier_key === rule[index].modifier_key && curr.key === rule[index].key @@ -1419,8 +1247,9 @@ export class KeylayoutToKmnConverter { //&& rule[index].uniqueA !== 0 //&& String(curr.dk) === String(rule[index].dk) ); + // 5-5 - const dup_5_5_mid = rule.filter((curr, idx) => + const dup_5_5 = rule.filter((curr, idx) => (curr.rule_type === "C3") && curr.modifier_deadkey === rule[index].modifier_deadkey && curr.deadkey === rule[index].deadkey @@ -1431,44 +1260,44 @@ export class KeylayoutToKmnConverter { //&& idx < index ); - if (amb_1_4_mid.length > 0) { - warningTextArray[0] = warningTextArray[0] + ("C3 FIRSTTEXT " + "ambiguous 1-4 rule: earlier(Todo check if print out or not): [" + amb_1_4_mid[0].modifier_key + " " + amb_1_4_mid[0].key + "] > \'" + new TextDecoder().decode(amb_1_4_mid[0].output) + "\' here: ") + if (amb_1_4.length > 0) { + warningTextArray[0] = warningTextArray[0] + ("C3 FIRSTTEXT " + "ambiguous 1-4 rule: earlier(Todo check if print out or not): [" + amb_1_4[0].modifier_key + " " + amb_1_4[0].key + "] > \'" + new TextDecoder().decode(amb_1_4[0].output) + "\' here: ") } - if (amb_2_4_mid.length > 0) { - warningTextArray[0] = warningTextArray[0] + ("C3 FIRSTTEXT " + "ambiguous 2-4 rule: earlier(Todo check if print out or not): [" + amb_2_4_mid[0].modifier_deadkey + " " + amb_2_4_mid[0].deadkey + "] > dk(C" + amb_2_4_mid[0].dk_C2 + ") here: ") + if (amb_2_4.length > 0) { + warningTextArray[0] = warningTextArray[0] + ("C3 FIRSTTEXT " + "ambiguous 2-4 rule: earlier(Todo check if print out or not): [" + amb_2_4[0].modifier_deadkey + " " + amb_2_4[0].deadkey + "] > dk(C" + amb_2_4[0].dk_C2 + ") here: ") } - if (dup_6_3_bot.length > 0) { - warningTextArray[1] = warningTextArray[1] + ("C3 SECONDTEXT " + "ambiguous y 6-3 rule: earlier: dk(C" + dup_6_3_bot[0].dk_C2 + ") + [" + dup_6_3_bot[0].modifier_key + " " + dup_6_3_bot[0].key + "] > \'" + new TextDecoder().decode(dup_6_3_bot[0].output) + "\' here: ") + if (amb_6_3.length > 0) { + warningTextArray[1] = warningTextArray[1] + ("C3 SECONDTEXT " + "ambiguous y 6-3 rule: earlier: dk(C" + amb_6_3[0].dk_C2 + ") + [" + amb_6_3[0].modifier_key + " " + amb_6_3[0].key + "] > \'" + new TextDecoder().decode(amb_6_3[0].output) + "\' here: ") } - if (dup_6_3_mid.length > 0) { - warningTextArray[1] = warningTextArray[1] + ("C3 SECONDTEXT " + "duplicate y 6-3 rule: earlier: dk(C" + dup_6_3_mid[0].dk_C2 + ") + [" + dup_6_3_mid[0].modifier_key + " " + dup_6_3_mid[0].key + "] > \'" + new TextDecoder().decode(dup_6_3_mid[0].output) + "\' here: ") + if (dup_6_3.length > 0) { + warningTextArray[1] = warningTextArray[1] + ("C3 SECONDTEXT " + "duplicate y 6-3 rule: earlier: dk(C" + dup_6_3[0].dk_C2 + ") + [" + dup_6_3[0].modifier_key + " " + dup_6_3[0].key + "] > \'" + new TextDecoder().decode(dup_6_3[0].output) + "\' here: ") } if (amb_4_4_mid.length > 0) { warningTextArray[0] = warningTextArray[0] + ("C3 FIRSTTEXT " + "ambiguous 4-4 rule: earlier: [" + amb_4_4_mid[0].modifier_prev_deadkey + " " + amb_4_4_mid[0].prev_deadkey + "] > dk(C" + amb_4_4_mid[0].dk_prev + ") here: ") } - if (dup_4_4_mid.length > 0) { - warningTextArray[0] = warningTextArray[0] + ("C3 FIRSTTEXT " + "duplicate 4-4 rule: earlier: [" + dup_4_4_mid[0].modifier_prev_deadkey + " " + dup_4_4_mid[0].prev_deadkey + "] > dk(C" + dup_4_4_mid[0].dk_prev + ") here: ") + if (dup_4_4.length > 0) { + warningTextArray[0] = warningTextArray[0] + ("C3 FIRSTTEXT " + "duplicate 4-4 rule: earlier: [" + dup_4_4[0].modifier_prev_deadkey + " " + dup_4_4[0].prev_deadkey + "] > dk(C" + dup_4_4[0].dk_prev + ") here: ") } - if (amb_5_5_mid.length > 0) { - warningTextArray[1] = warningTextArray[1] + ("C3 SECONDTEXT " + "ambiguous y 5-5 rule: earlier: dk(B" + amb_5_5_mid[0].dk_prev + ") + [" + amb_5_5_mid[0].modifier_deadkey + " " + amb_5_5_mid[0].deadkey + "] > dk(B" + amb_5_5_mid[0].dk_C2 + ") here: ") + if (amb_5_5.length > 0) { + warningTextArray[1] = warningTextArray[1] + ("C3 SECONDTEXT " + "ambiguous y 5-5 rule: earlier: dk(B" + amb_5_5[0].dk_prev + ") + [" + amb_5_5[0].modifier_deadkey + " " + amb_5_5[0].deadkey + "] > dk(B" + amb_5_5[0].dk_C2 + ") here: ") } - if (dup_5_5_mid.length > 0) { - warningTextArray[1] = warningTextArray[1] + ("C3 SECONDTEXT " + "duplicate y 5-5 rule: earlier: dk(B" + dup_5_5_mid[0].dk_prev + ") + [" + dup_5_5_mid[0].modifier_deadkey + " " + dup_5_5_mid[0].deadkey + "] > dk(B" + dup_5_5_mid[0].dk_C2 + ") here: ") + if (dup_5_5.length > 0) { + warningTextArray[1] = warningTextArray[1] + ("C3 SECONDTEXT " + "duplicate y 5-5 rule: earlier: dk(B" + dup_5_5[0].dk_prev + ") + [" + dup_5_5[0].modifier_deadkey + " " + dup_5_5[0].deadkey + "] > dk(B" + dup_5_5[0].dk_C2 + ") here: ") } - if (amb_6_6_bot.length > 0) { - warningTextArray[2] = warningTextArray[2] + ("C3 THIRDTEXT " + "ambiguous y 6-6 rule: earlier: dk(B" + amb_6_6_bot[0].dk_C2 + ") + [" + amb_6_6_bot[0].modifier_key + " " + amb_6_6_bot[0].key + "] > \'" + new TextDecoder().decode(amb_6_6_bot[0].output) + "\' here: ") + if (amb_6_6.length > 0) { + warningTextArray[2] = warningTextArray[2] + ("C3 THIRDTEXT " + "ambiguous y 6-6 rule: earlier: dk(B" + amb_6_6[0].dk_C2 + ") + [" + amb_6_6[0].modifier_key + " " + amb_6_6[0].key + "] > \'" + new TextDecoder().decode(amb_6_6[0].output) + "\' here: ") } - if (dup_6_6_bot.length > 0) { - warningTextArray[2] = warningTextArray[2] + ("C3 THIRDTEXT " + "duplicate y 6-6x rule: earlier: dk(B" + dup_6_6_bot[0].dk_C2 + ") + [" + dup_6_6_bot[0].modifier_key + " " + dup_6_6_bot[0].key + "] > \'" + new TextDecoder().decode(dup_6_6_bot[0].output) + "\' here: ") + if (dup_6_6.length > 0) { + warningTextArray[2] = warningTextArray[2] + ("C3 THIRDTEXT " + "duplicate y 6-6x rule: earlier: dk(B" + dup_6_6[0].dk_C2 + ") + [" + dup_6_6[0].modifier_key + " " + dup_6_6[0].key + "] > \'" + new TextDecoder().decode(dup_6_6[0].output) + "\' here: ") } } @@ -1486,6 +1315,7 @@ export class KeylayoutToKmnConverter { */ // TODO finish all entries public map_UkeleleKC_To_VK(pos: number): string { + // ukelele KC --> // VK_US if (pos === 0x0A) return "K_BKQUOTE" /* ^ */ if (pos === 0x12) return "K_1" /* 1 */ @@ -1512,7 +1342,7 @@ export class KeylayoutToKmnConverter { if (pos === 0x1F) return "K_O" /* O */ if (pos === 0x23) return "K_P" /* P */ if (pos === 0x21) return "K_LBRKT" /* [ */ - if (pos === 0x1E) return "K_RBRKT" /* ] */ // this is (1E) 30 not 36 (24) !!! + if (pos === 0x1E) return "K_RBRKT" /* ] */ if (pos === 0x31) return "K_SPACE" /* \ */ if (pos === 0x2A) return "K_BKSLASH" /* \ */ // 42 for ISO correct?? // if (pos === 0x30) return "K_?C1" /* \ */ // 48 for ANSI correct?? @@ -1550,57 +1380,58 @@ export class KeylayoutToKmnConverter { //---------------------------------------------------------------------------------------------------- public createData_Rules(data_ukelele: convert_object): string { - //let warningtextArray: string[] = Array(3).fill(""); - const maxkey: number = 50 let data: string = "" let keymarker: string = "" - const data_CAll: rule_object[] = data_ukelele.arrayOf_Rules.filter((curr) => { - if ((curr.output !== new TextEncoder().encode("") || curr.output !== undefined) - && (curr.rule_type === "C0") || (curr.rule_type === "C1") || (curr.rule_type === "C2") || (curr.rule_type === "C3")) { - return curr; - } - else return "" - }); - const unique_CAll_Rules: rule_object[] = data_CAll.reduce((unique, o) => { - if (!unique.some((obj: { output: Uint8Array; rule_type: string; modifier_key: string; modifier_deadkey: string; prev_deadkey: string; modifier_prev_deadkey: string; deadkey: string; key: string }) => - new TextDecoder().decode(obj.output) === new TextDecoder().decode(o.output) - - && obj.rule_type === o.rule_type - && obj.modifier_key === o.modifier_key - && obj.key === o.key - - && obj.modifier_deadkey === o.modifier_deadkey - && obj.deadkey === o.deadkey - - && obj.modifier_prev_deadkey === o.modifier_prev_deadkey - && obj.prev_deadkey === o.prev_deadkey) - ) { - unique.push(o); - } - return unique; - }, []); - //const unique_CAll_Rules: rule_object[] = data_ukelele.arrayOf_Rules + // create array of all rules and remove duplicates + /* const data_rules: rule_object[] = data_ukelele.arrayOf_Rules.filter((curr) => { + if ((curr.output !== new TextEncoder().encode("") || curr.output !== undefined) + && (curr.rule_type === "C0") || (curr.rule_type === "C1") || (curr.rule_type === "C2") || (curr.rule_type === "C3")) { + return curr; + } + else return "" + }); + const unique_data_Rules: rule_object[] = data_rules.reduce((unique, o) => { + if (!unique.some((obj: { output: Uint8Array; rule_type: string; modifier_key: string; modifier_deadkey: string; prev_deadkey: string; modifier_prev_deadkey: string; deadkey: string; key: string }) => + new TextDecoder().decode(obj.output) === new TextDecoder().decode(o.output) + + && obj.rule_type === o.rule_type + && obj.modifier_key === o.modifier_key + && obj.key === o.key + + && obj.modifier_deadkey === o.modifier_deadkey + && obj.deadkey === o.deadkey + + && obj.modifier_prev_deadkey === o.modifier_prev_deadkey + && obj.prev_deadkey === o.prev_deadkey) + ) { + unique.push(o); + } + return unique; + }, []);*/ + // ToDo remove + const unique_data_Rules: rule_object[] = data_ukelele.arrayOf_Rules console.log("xx data_ukelele.arrayOf_Rules", data_ukelele.arrayOf_Rules.length) //console.log("xx data_ukelele.arrayOf_Rules", this.writeDataset(data_ukelele.arrayOf_Rules)) - - console.log("xx unique_CAll_Rules", unique_CAll_Rules.length) - console.log("xx unique_CAll_Rules", this.writeDataset(unique_CAll_Rules)) + console.log("xx unique_data_Rules", unique_data_Rules.length) + console.log("xx unique_data_Rules", this.writeDataset(unique_data_Rules)) //................................................ C0 C1 ................................................................ //................................................ C0 C1 ................................................................ //................................................ C0 C1 ................................................................ - for (let k = 0; k < unique_CAll_Rules.length; k++) { + for (let k = 0; k < unique_data_Rules.length; k++) { - if ((unique_CAll_Rules[k].rule_type === "C0") || (unique_CAll_Rules[k].rule_type === "C1")) { + if ((unique_data_Rules[k].rule_type === "C0") || (unique_data_Rules[k].rule_type === "C1")) { // lookup key nr of the key that is being processed let keyNr: number = 0; - for (let j = 0; j < maxkey; j++) { - if (this.map_UkeleleKC_To_VK(j) === unique_CAll_Rules[k].key) + for (let j = 0; j < KeylayoutToKmnConverter.USED_KEYS_COUNT; j++) { + if (this.map_UkeleleKC_To_VK(j) === unique_data_Rules[k].key) { keyNr = j + break + } } // skip keyNr 48 ( TAB ) @@ -1608,39 +1439,44 @@ export class KeylayoutToKmnConverter { continue // add a line after rules of each key - if (unique_CAll_Rules[k].key !== keymarker) + if (unique_data_Rules[k].key !== keymarker) data += '\n' //--------------------------------------------------------------------------------------------- - const warn_text = this.reviewRules(unique_CAll_Rules, k) + // add a warning in front of rules that use unavailable modifiers or ambiguous rules + const warn_text = this.reviewRules(unique_data_Rules, k) - // if warning contains "duplicate" we do not write this rule even if it has other warnings since it does not make sense to write twice + // ToDo include condition again + // if warning contains duplicate rules we do not write out this rule (even if there are other warnings for the same rule) since that rule had been written before // if ((warn_text[2].indexOf("duplicate") < 0)) { - data += warn_text[2] + "+ [" + (unique_CAll_Rules[k].modifier_key + ' ' + unique_CAll_Rules[k].key).trim() + `] > \'` + new TextDecoder().decode(unique_CAll_Rules[k].output) + '\'\n' + data += warn_text[2] + "+ [" + (unique_data_Rules[k].modifier_key + ' ' + unique_data_Rules[k].key).trim() + `] > \'` + new TextDecoder().decode(unique_data_Rules[k].output) + '\'\n' // } - keymarker = unique_CAll_Rules[k].key + keymarker = unique_data_Rules[k].key } } + // Todo remove this marker data += "\n c ########## C2 #################################################################\n" //................................................ C2 ................................................................... //................................................ C2 ................................................................... //................................................ C2 ................................................................... - for (let k = 0; k < unique_CAll_Rules.length; k++) { + for (let k = 0; k < unique_data_Rules.length; k++) { - if (unique_CAll_Rules[k].rule_type === "C2") { + if (unique_data_Rules[k].rule_type === "C2") { - const warn_text = this.reviewRules(unique_CAll_Rules, k) + const warn_text = this.reviewRules(unique_data_Rules, k) //SECONDTEXT print + // ToDo include condition again // if ((warn_text[1].indexOf("duplicate") < 0)) { - data += warn_text[1] + "+ [" + unique_CAll_Rules[k].modifier_deadkey + " " + unique_CAll_Rules[k].deadkey + "] > dk(C" + String(unique_CAll_Rules[k].dk_C2) + ")\n" + data += warn_text[1] + "+ [" + unique_data_Rules[k].modifier_deadkey + " " + unique_data_Rules[k].deadkey + "] > dk(C" + String(unique_data_Rules[k].dk_C2) + ")\n" // } // THIRDTEXT print OK + // ToDo include condition again // if ((warn_text[2].indexOf("duplicate") < 0)) { - data += warn_text[2] + "dk(C" + String(unique_CAll_Rules[k].dk_C2) + ") + [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'\n" + data += warn_text[2] + "dk(C" + String(unique_data_Rules[k].dk_C2) + ") + [" + unique_data_Rules[k].modifier_key + " " + unique_data_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_data_Rules[k].output) + "\'\n" data += "\n" // } } @@ -1652,25 +1488,27 @@ export class KeylayoutToKmnConverter { data += "\nc ########## C3 #################################################################\n" - for (let k = 0; k < unique_CAll_Rules.length; k++) { - if (unique_CAll_Rules[k].rule_type === "C3") { + for (let k = 0; k < unique_data_Rules.length; k++) { + if (unique_data_Rules[k].rule_type === "C3") { - const warn_text = this.reviewRules(unique_CAll_Rules, k) + const warn_text = this.reviewRules(unique_data_Rules, k) - // just print out what's in the array + // ToDo include condition again // FIRSTTEXT print // if ((warn_text[0].indexOf("duplicate") < 0)) { - data += warn_text[0] + " [" + unique_CAll_Rules[k].modifier_prev_deadkey + " " + unique_CAll_Rules[k].prev_deadkey + "] > dk(A" + String(unique_CAll_Rules[k].dk_prev) + ")\n" + data += warn_text[0] + " [" + unique_data_Rules[k].modifier_prev_deadkey + " " + unique_data_Rules[k].prev_deadkey + "] > dk(A" + String(unique_data_Rules[k].dk_prev) + ")\n" // } + // ToDo include condition again //SECONDTEXT print // if ((warn_text[1].indexOf("duplicate") < 0)) { - data += warn_text[1] + "dk(A" + String(unique_CAll_Rules[k].dk_prev) + ") + [" + unique_CAll_Rules[k].modifier_deadkey + " " + unique_CAll_Rules[k].deadkey + "] > dk(B" + String(unique_CAll_Rules[k].dk_C2) + ")\n" + data += warn_text[1] + "dk(A" + String(unique_data_Rules[k].dk_prev) + ") + [" + unique_data_Rules[k].modifier_deadkey + " " + unique_data_Rules[k].deadkey + "] > dk(B" + String(unique_data_Rules[k].dk_C2) + ")\n" // } + // ToDo include condition again // THIRDTEXT print OK // if ((warn_text[2].indexOf("duplicate") < 0)) { - data += warn_text[2] + "dk(B" + String(unique_CAll_Rules[k].dk_C2) + ") + [" + unique_CAll_Rules[k].modifier_key + " " + unique_CAll_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_CAll_Rules[k].output) + "\'\n" + data += warn_text[2] + "dk(B" + String(unique_data_Rules[k].dk_C2) + ") + [" + unique_data_Rules[k].modifier_key + " " + unique_data_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_data_Rules[k].output) + "\'\n" // } data += "\n" @@ -1682,26 +1520,26 @@ export class KeylayoutToKmnConverter { public createData_Stores(data_ukelele: convert_object): string { - let data: string = "" - data += "c\n" + let data: string = "" + data += "c ......................................................................\n" + data += "c ......................................................................\n" data += "c Keyman keyboard generated by kmn-convert\n" - data += "c from original file: " + data_ukelele.keylayout_filename + "\n" - data += "c\n" - data += "\n" + data += "c from Ukelele file: " + data_ukelele.keylayout_filename + "\n" + data += "c ......................................................................\n" + data += "c ......................................................................\n" + data += "c \n" data += "store(&VERSION) \'10.0\'\n" data += "store(&TARGETS) \'any\'\n" data += "store(&KEYBOARDVERSION) \'1.0\'\n" data += "store(©RIGHT) '© 2024 SIL International\'\n" - // TODO what else ?? data += "\n" data += "begin Unicode > use(main)\n\n" data += "group(main) using keys\n\n" data += "\n" - return data } From 176550ea5216932edf714f7f1252b0998361952f Mon Sep 17 00:00:00 2001 From: Sabine Date: Wed, 19 Feb 2025 17:04:39 +0100 Subject: [PATCH 054/251] feat(developer): kmc-convert even more tidy up --- .../keylayout-to-kmn-converter.ts | 194 +++++++++--------- 1 file changed, 96 insertions(+), 98 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 628efbb8efc..7d73cd09a36 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -373,9 +373,9 @@ export class KeylayoutToKmnConverter { if ((this.get_Action2ID_NoneOutput__From__ActionID_Id(jsonObj, action_id) !== undefined) && (this.get_Action2ID_NoneOutput__From__ActionID_Id(jsonObj, action_id) !== "")) { const outputchar: string = this.get_Action2ID_NoneOutput__From__ActionID_Id(jsonObj, action_id) - const resultArraySS_Key_Out: string[][] = this.get_Datat_array2D__From__ActionID_stateOutput(jsonObj, data_ukelele.arrayOf_Modifiers, action_id, outputchar, isCapsused) + const b1_KeyMapModiKey_arr: string[][] = this.get_Datat_array2D__From__ActionID_stateOutput(jsonObj, data_ukelele.arrayOf_Modifiers, action_id, outputchar, isCapsused) - for (let m = 0; m < resultArraySS_Key_Out.length; m++) { + for (let m = 0; m < b1_KeyMapModiKey_arr.length; m++) { RuleObj = new Rules( /* rule_type */ "C1", @@ -391,8 +391,8 @@ export class KeylayoutToKmnConverter { /* dk for C2*/ 0, /* unique B */ 0, - /* modifier_key*/ resultArraySS_Key_Out[m][5], - /* key */ resultArraySS_Key_Out[m][4], + /* modifier_key*/ b1_KeyMapModiKey_arr[m][5], + /* key */ b1_KeyMapModiKey_arr[m][4], /* output */ new TextEncoder().encode(outputchar) ) ObjectArray.push(RuleObj) @@ -409,24 +409,24 @@ export class KeylayoutToKmnConverter { // https://docs.google.com/document/d/1ISjACTA9aUBueTo1AoKnOsI6QR5kXeeD_maI0XUyXqg/edit?tab=t.0 ......... // ...................................................................................................... - const actionIdIndex2: number = this.get_ActionID_Index__From__ActionID_Id(jsonObj, action_id) + const b1_actionIndex: number = this.get_ActionID_Index__From__ActionID_Id(jsonObj, action_id) // loop all action-when and find state-next-pair - for (let l = 0; l < jsonObj.keyboard.actions.action[actionIdIndex2].when.length; l++) { + for (let l = 0; l < jsonObj.keyboard.actions.action[b1_actionIndex].when.length; l++) { // find state ="none" - next data - if ((jsonObj.keyboard.actions.action[actionIdIndex2].when[l]['@_state'] === "none") - && (jsonObj.keyboard.actions.action[actionIdIndex2].when[l]['@_next'] !== undefined)) { + if ((jsonObj.keyboard.actions.action[b1_actionIndex].when[l]['@_state'] === "none") + && (jsonObj.keyboard.actions.action[b1_actionIndex].when[l]['@_next'] !== undefined)) { // Data of Block Nr 5 .................................................................................................................... - /* eg: next = 1 */ const b5_value_next: string = jsonObj.keyboard.actions.action[actionIdIndex2].when[l]['@_next'] - /* eg: StateNextID = a16 */ const b5_actionId: string[] = jsonObj.keyboard.actions.action[actionIdIndex2]['@_id'] + /* eg: next = 1 */ const b5_value_next: string = jsonObj.keyboard.actions.action[b1_actionIndex].when[l]['@_next'] + /* eg: StateNextID = a18 */ const b5_actionId_arr: string[] = jsonObj.keyboard.actions.action[b1_actionIndex]['@_id'] // ....................................................................................................................................... // Data of Block Nr 4 .................................................................................................................... - /* eg: [ '6', '31', '32' ]*/ const b4_code_arr: string[] = this.get_KeyMap_Code_array__From__KeyMap_Action(jsonObj, b5_actionId) - /* eg: [['24', 0], ['24', 3]] */ const b4_keyBehaviour_arr: number[][] = this.get_KeyMap_Code_array__From__ActionID_Action(jsonObj, String(action_id)) - /* e.g. [['','caps?'], ['Caps']]*/ const b4_modifier2D_array: string[] = this.get_KeyMap_Modifier_array__From__behaviour_arr(data_ukelele.arrayOf_Modifiers, b4_keyBehaviour_arr) + /* eg: [ '24', '24' ]*/ const b4_code_arr: string[] = this.get_KeyMap_Code_array__From__KeyMap_Action(jsonObj, b5_actionId_arr) + /* eg: [['24', 0], ['24', 3]] */ const b4_keyBehaviour_arr: number[][] = this.get_KeyMap_Code_array__From__ActionID_Action(jsonObj, action_id) + /* e.g. [['','caps?'], ['Caps']]*/ const b4_modifier2D_arr: string[] = this.get_KeyMap_Modifier_array__From__behaviour_arr(data_ukelele.arrayOf_Modifiers, b4_keyBehaviour_arr) // ....................................................................................................................................... // Data of Block Nr 6 .................................................................................................................... @@ -435,13 +435,13 @@ export class KeylayoutToKmnConverter { // Data of Block Nr 1 .................................................................................................................... /* eg: ['49','K_SPACE','a0','0','Â'] */ const b1_keycode_arr: string[][] = this.get_KeyMap_Code_array__From__KeyMap_Action_array2D(jsonObj, b6_actionId_arr) - /* eg: ['K_SPACE','a0','0','NCAPS','Â']*/ const b1_KeyMapModiKeyArray: string[][] = this.get_KeyMapModiKeyArray__from__array(jsonObj, b1_keycode_arr, isCapsused) + /* eg: ['K_SPACE','a0','0','NCAPS','Â']*/ const b1_KeyMapModiKey_arr: string[][] = this.get_KeyMapModiKeyArray__from__array(jsonObj, b1_keycode_arr, isCapsused) // ....................................................................................................................................... - for (let n1 = 0; n1 < b4_modifier2D_array.length; n1++) { - for (let n2 = 0; n2 < b4_modifier2D_array[n1].length; n2++) { + for (let n1 = 0; n1 < b4_modifier2D_arr.length; n1++) { + for (let n2 = 0; n2 < b4_modifier2D_arr[n1].length; n2++) { for (let n3 = 0; n3 < b4_code_arr.length; n3++) { - for (let n4 = 0; n4 < b1_KeyMapModiKeyArray.length; n4++) { + for (let n4 = 0; n4 < b1_KeyMapModiKey_arr.length; n4++) { RuleObj = new Rules( /* rule_type */ "C2", @@ -451,17 +451,17 @@ export class KeylayoutToKmnConverter { /* dk_prev */ 0, /* unique A */ 0, - /* modifier_deadkey */ this.create_kmn_modifier(b4_modifier2D_array[n1][n2], isCapsused), + /* modifier_deadkey */ this.create_kmn_modifier(b4_modifier2D_arr[n1][n2], isCapsused), /* deadkey */ this.map_UkeleleKC_To_VK(Number(b4_code_arr[n3])), /* dk*/ 0, /* dk for C2*/ dk_counter_C2++, /* unique B */ 0, - /* modifier_key*/ b1_KeyMapModiKeyArray[n4][3], - /* key */ b1_KeyMapModiKeyArray[n4][0], - /* output */ new TextEncoder().encode(b1_KeyMapModiKeyArray[n4][4]), + /* modifier_key*/ b1_KeyMapModiKey_arr[n4][3], + /* key */ b1_KeyMapModiKey_arr[n4][0], + /* output */ new TextEncoder().encode(b1_KeyMapModiKey_arr[n4][4]), ) - if (b1_KeyMapModiKeyArray[n4][4] !== undefined) + if (b1_KeyMapModiKey_arr[n4][4] !== undefined) ObjectArray.push(RuleObj) } } @@ -479,25 +479,23 @@ export class KeylayoutToKmnConverter { // https://docs.google.com/document/d/1ISjACTA9aUBueTo1AoKnOsI6QR5kXeeD_maI0XUyXqg/edit?tab=t.0 ......... // ...................................................................................................... - const actionIdIndex: number = this.get_ActionID_Index__From__ActionID_Id(jsonObj, action_id) - // loop all action-when and find state-next-pair - for (let l = 0; l < jsonObj.keyboard.actions.action[actionIdIndex].when.length; l++) { + for (let l = 0; l < jsonObj.keyboard.actions.action[b1_actionIndex].when.length; l++) { // find state_next data - if ((jsonObj.keyboard.actions.action[actionIdIndex].when[l]['@_state'] !== "none") - && (jsonObj.keyboard.actions.action[actionIdIndex].when[l]['@_next'] !== undefined)) { + if ((jsonObj.keyboard.actions.action[b1_actionIndex].when[l]['@_state'] !== "none") + && (jsonObj.keyboard.actions.action[b1_actionIndex].when[l]['@_next'] !== undefined)) { // Data of Block Nr 5 .................................................................................................................... - /* eg: state = 3 */ const b5_value_state: string = jsonObj.keyboard.actions.action[actionIdIndex].when[l]['@_state'] - /* eg: next = 1 */ const b5_value_next: string = jsonObj.keyboard.actions.action[actionIdIndex].when[l]['@_next'] - /* eg: StateNextID = a16 */ const b5_actionId: string[] = jsonObj.keyboard.actions.action[actionIdIndex]['@_id'] + /* eg: state = 3 */ const b5_value_state: string = jsonObj.keyboard.actions.action[b1_actionIndex].when[l]['@_state'] + /* eg: next = 1 */ const b5_value_next: string = jsonObj.keyboard.actions.action[b1_actionIndex].when[l]['@_next'] + /* eg: StateNextID = a16 */ const b5_actionId_arr: string[] = jsonObj.keyboard.actions.action[b1_actionIndex]['@_id'] // ....................................................................................................................................... // Data of Block Nr 4 .................................................................................................................... - /* eg: [ '6', '31', '32' ]*/ const b4_code_arr: string[] = this.get_KeyMap_Code_array__From__KeyMap_Action(jsonObj, b5_actionId) + /* eg: [ '6', '24', '24' ]*/ const b4_code_arr: string[] = this.get_KeyMap_Code_array__From__KeyMap_Action(jsonObj, b5_actionId_arr) /* eg: [['24', 0], ['24', 3]] */ const b4_keyBehaviour_arr: number[][] = this.get_KeyMap_Code_array__From__ActionID_Action(jsonObj, String(action_id)) - /* e.g. [['','caps?'], ['Caps']]*/ const b4_modifier2D_array: string[] = this.get_KeyMap_Modifier_array__From__behaviour_arr(data_ukelele.arrayOf_Modifiers, b4_keyBehaviour_arr) + /* e.g. [['','caps?'], ['Caps']]*/ const b4_modifier2D_arr: string[] = this.get_KeyMap_Modifier_array__From__behaviour_arr(data_ukelele.arrayOf_Modifiers, b4_keyBehaviour_arr) // ....................................................................................................................................... // Data of Block Nr 3 .................................................................................................................... @@ -516,16 +514,16 @@ export class KeylayoutToKmnConverter { // Data of Block Nr 1 .................................................................................................................... /* eg: ['49','K_SPACE','a0','0','Â'] */ const b1_keycode_arr: string[][] = this.get_KeyMap_Code_array__From__KeyMap_Action_array2D(jsonObj, b6_actionId_arr) - /* eg: ['K_SPACE','a0','0','NCAPS','Â']*/ const b1_KeyMapModiKeyArray: string[][] = this.get_KeyMapModiKeyArray__from__array(jsonObj, b1_keycode_arr, isCapsused) + /* eg: ['K_SPACE','a0','0','NCAPS','Â']*/ const b1_KeyMapModiKey_arr: string[][] = this.get_KeyMapModiKeyArray__from__array(jsonObj, b1_keycode_arr, isCapsused) // ....................................................................................................................................... for (let n1 = 0; n1 < b2_modifier_arr_all.length; n1++) { for (let n2 = 0; n2 < b2_modifier_arr_all[n1].length; n2++) { for (let n3 = 0; n3 < b2_keyname_arr.length; n3++) { - for (let n4 = 0; n4 < b4_modifier2D_array.length; n4++) { - for (let n5 = 0; n5 < b4_modifier2D_array[n4].length; n5++) { + for (let n4 = 0; n4 < b4_modifier2D_arr.length; n4++) { + for (let n5 = 0; n5 < b4_modifier2D_arr[n4].length; n5++) { for (let n6 = 0; n6 < b4_code_arr.length; n6++) { - for (let n7 = 0; n7 < b1_KeyMapModiKeyArray.length; n7++) { + for (let n7 = 0; n7 < b1_KeyMapModiKey_arr.length; n7++) { RuleObj = new Rules( /* rule_type */ "C3", @@ -535,17 +533,17 @@ export class KeylayoutToKmnConverter { /* dk_prev */ dk_counter_C3_A++, /* unique A */ 0, - /* modifier_deadkey */ this.create_kmn_modifier(b4_modifier2D_array[n4][n5], isCapsused), + /* modifier_deadkey */ this.create_kmn_modifier(b4_modifier2D_arr[n4][n5], isCapsused), /* deadkey */ this.map_UkeleleKC_To_VK(Number(b4_code_arr[n6])), /* dk*/ dk_counter_C3_B++, /* dk for C2*/ 0, /* unique B */ 0, - /* modifier_key*/ b1_KeyMapModiKeyArray[n7][3], - /* key */ b1_KeyMapModiKeyArray[n7][0], - /* output */ new TextEncoder().encode(b1_KeyMapModiKeyArray[n7][4]), + /* modifier_key*/ b1_KeyMapModiKey_arr[n7][3], + /* key */ b1_KeyMapModiKey_arr[n7][0], + /* output */ new TextEncoder().encode(b1_KeyMapModiKey_arr[n7][4]), ) - if (b1_KeyMapModiKeyArray[n7][4] !== undefined) + if (b1_KeyMapModiKey_arr[n7][4] !== undefined) ObjectArray.push(RuleObj) } } @@ -556,43 +554,6 @@ export class KeylayoutToKmnConverter { } } } - - // ...................................................................................................... - // case C4: action + state none + Next .................................................................. - // ...............e. g. ................................................... - // a key is mapped to an action and then to a terminator ................................................ - // action:state(none) -> action:next -> terminators:output .............................................. - // action:id -> keyMap:action -> keyMap:code ( dk ) ..................................................... - // action:id -> keyMap:action -> keyMap:code ( key) ..................................................... - // ...................................................................................................... - - const next_id: string = this.get_ActionID_Next__From__ActionID_None(jsonObj, action_id) - - for (let l = 0; l < data_ukelele.arrayOf_Modifiers[i].length; l++) { - if (new TextEncoder().encode(this.get_Terminator_Output__From__Terminator_State(jsonObj, next_id)).length !== 0) { - - RuleObj = new Rules( - /* rule_type */ "C4", - - /* modifier_prev_deadkey*/ "", - /* prev_deadkey */ "", - /* dk_prev */ 0, - /* unique A */ 0, - - /* modifier_deadkey */ "", - /* deadkey */ "", - /* dk*/ 0, - /* dk for C2*/ 0, - /* unique B */ 0, - - /* modifier_key*/ this.create_kmn_modifier(data_ukelele.arrayOf_Modifiers[i][l], isCapsused), - /* key */ this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), - /* output */ new TextEncoder().encode(this.get_Terminator_Output__From__Terminator_State(jsonObj, next_id)) - ) - } - if (this.get_Terminator_Output__From__Terminator_State(jsonObj, next_id) !== "") - ObjectArray.push(RuleObj) - } } else console.log("ERROR : some entries are not available") @@ -698,7 +659,11 @@ export class KeylayoutToKmnConverter { // --------------------------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------------------------- - + /* + in: Block 3 - b3_actionId a19 + out: Block 2 - b2_keyname_arr ['K_8', 'K_M] + do: create array of Array of Keycode eg: ['K_8', 'K_M] from an actionId a16 + */ public get_KecCode_arr__From__ActionId(data: any, search: string): string[] { const returnarray: string[] = [] for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { @@ -712,6 +677,11 @@ export class KeylayoutToKmnConverter { } return returnarray } + /* + in: Block 5 - b5_actionId_arr a16, a18 + out: Block 4 - b4_code_arr [ '6', '31', '32' ] + do: create array of keycodes from an array of keymapIndex + */ public get_KeyMap_Code_array__From__KeyMap_Action(data: any, search: string[]): string[] { const returnarray: string[] = [] for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { @@ -725,6 +695,11 @@ export class KeylayoutToKmnConverter { } return returnarray } + /* + in: Block 6 - b6_actionId_arr [ 'a9','1','â'] + out: Block 1 - b1_keycode_arr ['49','K_SPACE','a0','0','Â'] + do: create array of ['49','K_SPACE','a0','0','Â'] from create array of [ 'a9','1','â'] + */ public get_KeyMap_Code_array__From__KeyMap_Action_array2D(data: any, search: string[][]): string[][] { const returnarray2D: string[][] = [] for (let k = 0; k < search.length; k++) { @@ -747,6 +722,11 @@ export class KeylayoutToKmnConverter { } return returnarray2D } + /* + in: action_id a19 + out: b1_actionIndex behav. 1 + do: get the actionIdIndex from action id a18 + */ public get_ActionID_Index__From__ActionID_Id(data: any, search: string): number { for (let i = 0; i < data.keyboard.actions.action.length; i++) { if (data.keyboard.actions.action[i]['@_id'] === search) @@ -754,17 +734,12 @@ export class KeylayoutToKmnConverter { } return 0 } - public get_ActionID_Next__From__ActionID_None(data: any, search: string): string { - for (let i = 0; i < data.keyboard.actions.action.length; i++) { - if (data.keyboard.actions.action[i]['@_id'] === search) { - for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { - if (data.keyboard.actions.action[i].when[j]['@_state'] === "none") - return data.keyboard.actions.action[i].when[j]['@_next'] - } - } - } - return "" - } + + /* + in: Block 5 - b5_value_state state = 3 + out: Block 3 - b3_actionId a19 + do: get the actionIdI from state / next + */ public get_ActionID_Id__From__ActionID_next(data: any, search: string): string { if (search !== "none") { for (let i = 0; i < data.keyboard.actions.action.length; i++) { @@ -777,6 +752,11 @@ export class KeylayoutToKmnConverter { } return "" } + /* + in: Block 5 - b5_value_next next = 1 + out: Block 6 - b6_actionId_arr 'a9','1','â'] + do: create array of [ 'a9','1','â'] from state / next + */ public get_ActionID_Output_array__From__ActionID_State(data: any, search: string) { const returnarray2D: string[][] = [] for (let i = 0; i < data.keyboard.actions.action.length; i++) { @@ -793,6 +773,11 @@ export class KeylayoutToKmnConverter { } return returnarray2D } + /* + in: Block 1 - action_id a18 + out: Block 6 - outputchar 'A' + do: create output Array from action_id + */ public get_Action2ID_NoneOutput__From__ActionID_Id(data: any, search: string): string { let OutputValue: string = "" for (let i = 0; i < data.keyboard.actions.action.length; i++) { @@ -806,6 +791,11 @@ export class KeylayoutToKmnConverter { } return OutputValue } + /* + in: Block 1 - b1_keycode_arr ['49','K_SPACE','a0','0','Â'] + out: Block 1 - b1_KeyMapModiKey_arr ['K_SPACE','a0','0','NCAPS','Â'] + do: create array of key+modi+out from array of b1_keycode_arr + */ public get_KeyMapModiKeyArray__from__array(data: any, search: string[][], isCAPSused: boolean): string[][] { const returnarray: string[][] = [] @@ -836,6 +826,12 @@ export class KeylayoutToKmnConverter { ); return unique_returnarray } + /* ?? + in: Block C1 - action_id a19 + in: Block C1 - out 'A' + out: Block C1 - b1_KeyMapModiKey_arr + do: create array of key+mod+out from array of b1_KeyMapModiKey_arr + */ public get_Datat_array2D__From__ActionID_stateOutput(data: any, modi: any, search: string, outchar: string, isCapsused: boolean): string[][] { const returnarray2D: string[][] = [] @@ -876,14 +872,11 @@ export class KeylayoutToKmnConverter { return unique_returnarray } - public get_Terminator_Output__From__Terminator_State(data: any, search: string): string { - for (let i = 0; i < data.keyboard.terminators.when.length; i++) { - if (data.keyboard.terminators.when[i]['@_state'] === search) { - return data.keyboard.terminators.when[i]['@_output'] - } - } - return "" - } + /* + in: Block - action_id a19 + out: Block 4 - b4_keyBehaviour_arr [['24', 0], ['24', 3]] + do: create array of [['24', 0], ['24', 3]] from behaviour id + */ public get_KeyMap_Code_array__From__ActionID_Action(data: any, search: string): number[][] { const mapIndexArray_max: number[][] = [] for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { @@ -900,6 +893,11 @@ export class KeylayoutToKmnConverter { } return mapIndexArray_max } + /* + in: Block 4 - b4_keyBehaviour_arr [['24', 0], ['24', 3]] + out: Block 4 - b4_modifier2D_arr [['','caps?'], ['Caps']] + do: create array of from array of b4_keyBehaviour_arr + */ public get_KeyMap_Modifier_array__From__behaviour_arr(data: any, search: number[][]): string[] { const mapIndexArray_max: string[] = [] for (let i = 0; i < search.length; i++) { From b649e75e415b48958452c2b35d149fbba81d3b47 Mon Sep 17 00:00:00 2001 From: Sabine Date: Fri, 21 Feb 2025 08:04:32 +0100 Subject: [PATCH 055/251] feat(developer): review createRuleData to simplify creation of C2 and C3 rules --- .../keylayout-to-kmn-converter.ts | 892 +++++++++--------- 1 file changed, 453 insertions(+), 439 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 7d73cd09a36..c19fe720929 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -7,18 +7,18 @@ import { CompilerCallbacks, CompilerOptions } from "@keymanapp/developer-utils"; import { ConverterToKmnArtifacts } from "../converter-artifacts.js"; -// TODO keylayout->kmn +// Todo remove these todos +// OK TODO keylayout->kmn // OK modifiers: The identifier of the element to use for this range of hardware keyboard types. // OK defaultIndex: The table number to use for modifier key combinations which are not explicitly specified by any element within the . // OK write read, convert, write -// tests for 3 functions read write convert // OK add data to object // OK Use filter functions // OK action/output:use filter etc to shorten func // OK deadkeyables:use filter etc to shorten func // OK dk-> for all action:use filter etc to shorten func -// OK remove unneccessary data from dataObject -// rename symbols +// OK remove unneccessary data from data_object +// OK rename symbols // OK remove part using kmn_key_Name1 // OK remove unnecceaasry map_UkeleleKC_To_kmn_Key_Name_Array_Position_n etc // OK loop throught ANSI, JIS- at moment only use [keyMapSet_count] (keyMapSet_count=0) @@ -27,22 +27,13 @@ import { ConverterToKmnArtifacts } from "../converter-artifacts.js"; // OK Mapping 0->30 or 0->K_A-> missing entries in mapping // OK Replace any-types // OK Several steps action-> action-> action->character ( not only action->character) -// TODO waht about using actions twice in a row??? -> error msg if chain >4 // OK Usable for all keylayout files -// Return conditions // OK Use callbacks as for writeFileSync -// Tests throws -// Conditions NCAPS,OPT;... -// TODO move func outside of class -// Functions as object methods? -// objects contain only used stuff READ in: -- out: only read arrays / CONVERT in: only read arrays out: return only to write arrays +// OK objects contain only used stuff READ in: -- out: only read arrays / CONVERT in: only read arrays out: return only to write arrays // OK Use catch blocks for file read // OK read: answer : + [K_A] > 'a' is OK / TODO which format to use in output ? + [K_A] > 'a' (character code) or + [K_A] > U+0061 (virt Keycode) -// read TODO which stores? // OK one entry vs several entry in tags -// false arrangement of tags ? // OK no added NCAPS when first modifier in modifierMap does not contain "caps" or"caps?" -// use length to clear array instead of defining evetry time new (modifierMap_ONE_InKeymapSelect.length=0 // OK naming of for-loop var i,j,k?... // OK warning if contrADICTING RULES E:G: [ 'modifier_C0', 'SHIFT NCAPS', 'K_C', 'c'], vs [ 'modifier_C0', 'SHIFT NCAPS', 'K_C', 'C' ], // OK print NCAPS as the first of the modifiers in create_kmn_modifier @@ -53,30 +44,40 @@ import { ConverterToKmnArtifacts } from "../converter-artifacts.js"; // OK rearrange code to use read, convert, write // OK TODO rewrite explanantion for object instead of array // OK remove all any types -// check code for code styles keyman -// public dk: number, //todo remove one +// OK public dk: number, //todo remove one // OK todo use from elsewhere boxXmlArray_S // OK prev_deadkeys_Ch: Uint8Array, /* Todo needed?*/ // OK Todo remove print_draft -// TODO throws // OK Todo files/path !!! -// TODO need to use export const USVirtualKeyCodes here -// start Tests v ToDo remove...................................... -// TODO remove: test files: checkif kmn gets the same output as ukelele file(except for C3 t works well :)) -// ToDo needed methods -// Filter functions use the same type -// where to put documentation -// dk <-> dk_C2 ??? -// check if we use the same algorithm to get Block1 data -// check uniqueA, uniqueV, dk_prv, dk, dk_C2 +// OK start Tests v ToDo remove...................................... +// OK TODO remove: test files: checkif kmn gets the same output as ukelele file(except for C3 t works well :)) +// OK ToDo needed methods +// OK where to put documentation +// OK dk <-> id_deadkey ??? +// OK check if we use the same algorithm to get Block1 data +// OK check unique_prev_deadkey, unique_deadkey, dk_prv, dk, id_deadkey // OK check duplicate rule conditions which do I need; which can go // OK when I run german with uniqueCAll why will there be [ ] without key anf modifier -// replace uniqueA 0, >0 with true, false +// OK add links to HEADLINE of kmc-convert document +// OK TODO more Data stores to add ?? +// tests for 3 functions read write convert +// Return conditions +// Tests throws +// Conditions NCAPS,OPT;... +// TODO move func outside of class +// Functions as object methods? +// use length to clear array instead of defining new every time (modifierMap_ONE_InKeymapSelect.length=0 +// Filter functions use the same type +// TODO need to use export const USVirtualKeyCodes here +// replace unique_prev_deadkey 0, >0 with true, false +// TODO waht about using actions twice in a row??? -> error msg if chain >4 // what if keylayout file is not correct e.g missing > // check for keys < 50 whern working with keys -// add links to HEADLINE of kmc-convert document +// check code for code styles keyman +// read TODO which stores? +// does order of modifier matter ? +// NO OUTPUT FOR SPACE in C0C1 !!! -// TODO more Data stores to add ?? import { XMLParser } from 'fast-xml-parser'; // for reading an xml file import { readFileSync } from 'fs'; @@ -106,14 +107,13 @@ export interface rule_object { modifier_prev_deadkey: string, /* string of modifiers for the first key (e.g. "NCAPS RALT CTRL") */ prev_deadkey: string, /* name of the first key (e.g. K_U) */ - dk_prev: number, /* dk count for prev-deadkeys */ - uniqueA: number, /* ToDo */ + id_prev_deadkey: number, /* dk id for prev-deadkeys */ + unique_prev_deadkey: number, /* marks the first prev_dk */ modifier_deadkey: string, /* string of modifiers for the second key (e.g. "NCAPS RALT CTRL") */ deadkey: string, /* name of the second key */ - dk: number, /* Todo needed?*/ - dk_C2: number, /* dk count for deadkeys */ - uniqueB: number, /* ToDo */ + id_deadkey: number, /* dk id for deadkeys */ + unique_deadkey: number, /* marks the first dk */ modifier_key: string, /* string of modifiers for the third key (e.g. "NCAPS RALT CTRL") */ key: string, /* name of the third key (e.g. K_U) */ @@ -131,7 +131,7 @@ export class KeylayoutToKmnConverter { static readonly INPUT_FILE_EXTENSION = '.keylayout'; static readonly OUTPUT_FILE_EXTENSION = '.kmn'; - static readonly USED_KEYS_COUNT = 50 + static readonly USED_KEYS_COUNT = 51 // TODO use callbacks what about /*private*/ for options //constructor(/*private*/ _callbacks: CompilerCallbacks, /*private*/ _options: CompilerOptions) { @@ -153,14 +153,14 @@ export class KeylayoutToKmnConverter { } console.log(' _S2 first READ file ........................................in:', inputFilename); - const JsonO: object = this.read(inputFilename) + const jsonO: object = this.read(inputFilename) - if (!JsonO) { + if (!jsonO) { return null; } console.log(' _S2 then CONVERT ........................................'); - const outArray: convert_object = await this.convert(JsonO); + const outArray: convert_object = await this.convert(jsonO); if (!outArray) { return null; @@ -168,8 +168,8 @@ export class KeylayoutToKmnConverter { console.log(' _S2 then WRITE to kmn .....................................'); - const out: boolean = this.write(outArray) - if (!out) { + const out_text: boolean = this.write(outArray) + if (!out_text) { return null; } @@ -193,18 +193,21 @@ export class KeylayoutToKmnConverter { }; try { - //const xmlFile = readFileSync(`${process.cwd()}/data/MySample.keylayout`, 'utf8') xmlFile = readFileSync((process.cwd() + "\\data" + filename.substring(filename.lastIndexOf("\\"))).replace(" ", ""), 'utf8'); const parser = new XMLParser(options); - jsonObj = parser.parse(xmlFile); // get plain Object - boxArrays(jsonObj.keyboard);// jsonObj now contains only arrays; no single fields - - console.log("inputFilename read", filename) + jsonObj = parser.parse(xmlFile); // get plain Object + boxArrays(jsonObj.keyboard); // jsonObj now contains only arrays; no single fields } catch { // Todo how to break correctly; return what?? console.log(" FILE NOT FOUND") } + console.log("jsonobj ",jsonObj.keyboard.actions.action[0] ) + console.log("tttttt ", ) + + + + return jsonObj } @@ -217,18 +220,19 @@ export class KeylayoutToKmnConverter { */ public convert(jsonObj: any): convert_object { - const jsonObj_any: any = jsonObj const modifierBehavior: string[][] = [] // modifier for each keymapselect - const ruleObject: rule_object[] = [] // an array of objects which hold data for a kmn rule + const rule_object: rule_object[] = [] // an array of objects which hold data for a kmn rule + + const jsonObj_any: any = jsonObj const keylayout_file: string = jsonObj_any.keyboard['@_name'] + ".keylayout" - const DataObject: convert_object = { + const data_object: convert_object = { keylayout_filename: keylayout_file, - arrayOf_Modifiers: modifierBehavior, // e.g. 18 modifiersCombinations in 8 KeyMapSelect(behaviors) - arrayOf_Rules: ruleObject + arrayOf_Modifiers: modifierBehavior, // ukelele uses behaviours e.g. 18 modifiersCombinations in 8 KeyMapSelect(behaviors) + arrayOf_Rules: rule_object }; - // create an array of modifier combinations (e.g. shift? leftShift caps? ) and store in convert_object + // create an array of modifier combinations (e.g. shift? leftShift caps? ) and store in data_object for (let j = 0; j < jsonObj.keyboard.modifierMap.keyMapSelect.length; j++) { const singleModifierSet: string[] = [] for (let k = 0; k < jsonObj.keyboard.modifierMap.keyMapSelect[j].modifier.length; k++) { @@ -236,7 +240,8 @@ export class KeylayoutToKmnConverter { } modifierBehavior.push(singleModifierSet) } - return this.createRuleData(DataObject, jsonObj) + // fill rules into arrayOf_Rules of data_object + return this.createRuleData(data_object, jsonObj) } @@ -256,7 +261,6 @@ export class KeylayoutToKmnConverter { // add bottom part of kmn file: RULES data += this.createData_Rules(data_ukelele) - /*writeFileSync("data/MyResult.kmn", data, { flag: "w" })*/ this.callbacks.fs.writeFileSync("data/MyResult.kmn", new TextEncoder().encode(data)) // ToDo conditions? @@ -268,62 +272,31 @@ export class KeylayoutToKmnConverter { // TODO move outside of class? // ToDo keep only uint8array-version - // for more info about mapping and cases C0-C4 see https://docs.google.com/document/d/1ISjACTA9aUBueTo1AoKnOsI6QR5kXeeD_maI0XUyXqg/edit?tab=t.0 - + // for more info about mapping and cases C0-C4 see https://docs.google.com/document/d/12J3NGO6RxIthCpZDTR8FYSRjiMgXJDLwPY2z9xqKzJ0/edit?tab=t.0#heading=h.g7jwx3lx0ydd public createRuleData(data_ukelele: convert_object, jsonObj: any): convert_object { - const ObjectArray: rule_object[] = [] + + const object_array: rule_object[] = [] let dk_counter_C3_A: number = 0 - let dk_counter_C3_B: number = 0 let dk_counter_C2: number = 0 - - // start Tests v ToDo remove...................................... - /*const testArray_Ukelele: string[] = [] - let testArray_Ukelele_count = 0 - const testArray_Ukelele_action: string[] = [] - let testArray_Ukelele_action_count = 0 - const testArray_kmn: string[] = [] - //const testArray_kmn_action1: string[] = [] - let testArray_kmn_count = 0 - - // loop behaviors ( in ukelele it is possible to define multiple modifier combinations that behave in the same) - for (let i = 0; i < jsonObj.keyboard.keyMapSet[0].keyMap.length; i++) { - // loop keys 0-50 (= all keys we use) - for (let j = 0; j <= KeylayoutToKmnConverter.USED_KEYS_COUNT; j++) { - - if ((jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] !== undefined)) { - testArray_Ukelele.push(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output']) - testArray_Ukelele_count++ - } - } - } - - for (let k = 0; k < jsonObj.keyboard.actions.action.length; k++) { - for (let j = 0; j < jsonObj.keyboard.actions.action[k].when.length; j++) { - if (jsonObj.keyboard.actions.action[k].when[j]['@_output'] !== undefined) { - testArray_Ukelele_action.push(jsonObj.keyboard.actions.action[k].when[j]['@_output']) - testArray_Ukelele_action_count++ - } - } - }*/ - // End Tests ToDo remove ^....................................... - - let action_id: string + // check if we use CAPS in a modifier. In this case we need to add NCAPS const isCapsused: boolean = this.checkIfCapsIsUsed(data_ukelele.arrayOf_Modifiers) // loop keys 0-50 (= all keys we use) - for (let j = 0; j <= KeylayoutToKmnConverter.USED_KEYS_COUNT; j++) { + for (let j = 0; j < KeylayoutToKmnConverter.USED_KEYS_COUNT; j++) { // loop behaviors (in ukelele it is possible to define multiple modifier combinations that behave in the same way) for (let i = 0; i < jsonObj.keyboard.keyMapSet[0].keyMap.length; i++) { - let RuleObj: rule_object - // ...................................................................................................... - // case C0: output ...................................................................................... - // a key is mapped to a character directly ( code-> output) ............................................. - // ...............e. g. ...................................................... - // ...................................................................................................... + let rule_obj: rule_object + + // ............................................................................................................................... + // case C0: output ............................................................................................................... + // C0 see: https://docs.google.com/document/d/12J3NGO6RxIthCpZDTR8FYSRjiMgXJDLwPY2z9xqKzJ0/edit?tab=t.0#heading=h.g7jwx3lx0ydd ... + // a key is mapped to a character directly ( code-> output) ...................................................................... + // ...............e. g. ............................................................................... + // ............................................................................................................................... if ((jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] !== undefined)) { @@ -333,136 +306,158 @@ export class KeylayoutToKmnConverter { for (let l = 0; l < data_ukelele.arrayOf_Modifiers[i].length; l++) { if (this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']))) { - RuleObj = new Rules( - /* rule_type */ "C0", + rule_obj = new Rules( + /* rule_type */ "C0", - /* modifier_prev_deadkey*/ "", - /* prev_deadkey */ "", - /* dk_prev */ 0, - /* unique A */ 0, + /* modifier_prev_deadkey*/ "", + /* prev_deadkey */ "", + /* id_prev_deadkey */ 0, + /* unique A */ 0, - /* modifier_deadkey */ "", - /* deadkey */ "", - /* dk*/ 0, - /* dk for C2*/ 0, - /* unique B */ 0, + /* modifier_deadkey */ "", + /* deadkey */ "", + /* dk for C2*/ 0, + /* unique B */ 0, - /* modifier_key*/ this.create_kmn_modifier(data_ukelele.arrayOf_Modifiers[i][l], isCapsused), - /* key */ this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), - /* output */ new TextEncoder().encode(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output']), + /* modifier_key*/ this.create_kmn_modifier(data_ukelele.arrayOf_Modifiers[i][l], isCapsused), + /* key */ this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), + /* output */ new TextEncoder().encode(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output']), ) if (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] !== "") - ObjectArray.push(RuleObj) + object_array.push(rule_obj) } } } } else if (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] !== undefined) { - action_id = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] - // ...................................................................................................... - // case C1: action + state none + output ................................................................ - // a key is mapped to an action and then to an output ................................................... - // KeyMap:code->KeyMap:action->action:action_state(none)->action_output ................................. - // ...............e. g. KeyMap:action->action:action_state(none)->action_output .......................................................... + // ...............e. g. ................................................... - // replace state x with all rules that result in 14 ( ............................................................................ + // replace state x with all rules that result in 14 ( for action id a18 ...................................................................................................................... for (let l = 0; l < jsonObj.keyboard.actions.action[b1_actionIndex].when.length; l++) { + if ((jsonObj.keyboard.actions.action[b1_actionIndex].when[l]['@_state'] === "none") // find "none" + && (jsonObj.keyboard.actions.action[b1_actionIndex].when[l]['@_next'] !== undefined)) { // find "next" - // find state ="none" - next data - if ((jsonObj.keyboard.actions.action[b1_actionIndex].when[l]['@_state'] === "none") - && (jsonObj.keyboard.actions.action[b1_actionIndex].when[l]['@_next'] !== undefined)) { + // Data of Block Nr 5 ..................................................................................................................................................................... + // of this state(none)-next-pair get value of next (next="1") ............................................................................................................................. + /* eg: 1 */ const b5_value_next: string = jsonObj.keyboard.actions.action[b1_actionIndex].when[l]['@_next'] + // ........................................................................................................................................................................................ - // Data of Block Nr 5 .................................................................................................................... - /* eg: next = 1 */ const b5_value_next: string = jsonObj.keyboard.actions.action[b1_actionIndex].when[l]['@_next'] - /* eg: StateNextID = a18 */ const b5_actionId_arr: string[] = jsonObj.keyboard.actions.action[b1_actionIndex]['@_id'] - // ....................................................................................................................................... - // Data of Block Nr 4 .................................................................................................................... - /* eg: [ '24', '24' ]*/ const b4_code_arr: string[] = this.get_KeyMap_Code_array__From__KeyMap_Action(jsonObj, b5_actionId_arr) - /* eg: [['24', 0], ['24', 3]] */ const b4_keyBehaviour_arr: number[][] = this.get_KeyMap_Code_array__From__ActionID_Action(jsonObj, action_id) - /* e.g. [['','caps?'], ['Caps']]*/ const b4_modifier2D_arr: string[] = this.get_KeyMap_Modifier_array__From__behaviour_arr(data_ukelele.arrayOf_Modifiers, b4_keyBehaviour_arr) - // ....................................................................................................................................... + // Data of Block Nr 4 ..................................................................................................................................................................... + // with present action_id (a18) find all keycode-behaviour-pairs that use this action (a18) => (keymapIndex 0/keycode 24 and keymapIndex 3/keycode 24) .................................... + // from these create an array of modifier combinations e.g. [['','caps?'], ['Caps']] ..................................................................................................... + /* eg: [['24', 0], ['24', 3]] */ const b4_deadkey_arr: number[][] = this.get_KeyMap_Code_array__From__ActionID_Action(jsonObj, action_id) + /* e.g. [['','caps?'], ['Caps']]*/ const b4_deadkeyModifier_arr: string[] = this.get_KeyMap_Modifier_array__From__behaviour_arr(data_ukelele.arrayOf_Modifiers, b4_deadkey_arr) + // ........................................................................................................................................................................................ - // Data of Block Nr 6 .................................................................................................................... - /* eg: [ 'a9','1','â'] */ const b6_actionId_arr: string[][] = this.get_ActionID_Output_array__From__ActionID_State(jsonObj, b5_value_next) - // ....................................................................................................................................... - // Data of Block Nr 1 .................................................................................................................... - /* eg: ['49','K_SPACE','a0','0','Â'] */ const b1_keycode_arr: string[][] = this.get_KeyMap_Code_array__From__KeyMap_Action_array2D(jsonObj, b6_actionId_arr) - /* eg: ['K_SPACE','a0','0','NCAPS','Â']*/ const b1_KeyMapModiKey_arr: string[][] = this.get_KeyMapModiKeyArray__from__array(jsonObj, b1_keycode_arr, isCapsused) - // ....................................................................................................................................... - - for (let n1 = 0; n1 < b4_modifier2D_arr.length; n1++) { - for (let n2 = 0; n2 < b4_modifier2D_arr[n1].length; n2++) { - for (let n3 = 0; n3 < b4_code_arr.length; n3++) { - for (let n4 = 0; n4 < b1_KeyMapModiKey_arr.length; n4++) { - - RuleObj = new Rules( - /* rule_type */ "C2", - - /* modifier_prev_deadkey*/ "", - /* prev_deadkey */ "", - /* dk_prev */ 0, - /* unique A */ 0, - - /* modifier_deadkey */ this.create_kmn_modifier(b4_modifier2D_arr[n1][n2], isCapsused), - /* deadkey */ this.map_UkeleleKC_To_VK(Number(b4_code_arr[n3])), - /* dk*/ 0, - /* dk for C2*/ dk_counter_C2++, - /* unique B */ 0, - - /* modifier_key*/ b1_KeyMapModiKey_arr[n4][3], - /* key */ b1_KeyMapModiKey_arr[n4][0], - /* output */ new TextEncoder().encode(b1_KeyMapModiKey_arr[n4][4]), + // Data of Block Nr 6 ..................................................................................................................................................................... + // create an array[action id,state,output] from all state-output-pairs that use state = b5_value_next (e.g. use 1 in ) ...................................... + /* eg: [ 'a9','1','â'] */ const b6_actionId_arr: string[][] = this.get_ActionID_Output_array__From__ActionID_State(jsonObj, b5_value_next) + // ........................................................................................................................................................................................ + + + // Data of Block Nr 1 .................................................................................................................................................................... + // create array[Keycode,Keyname,action id,actionIndex,output] and array[Keyname,action id,behaviour,modifier,output] ...................................................................... + /* eg: ['0','K_A','a9','0','â'] */ const b1_keycode_arr: string[][] = this.get_KeyMap_Code_array__From__KeyMap_Action_array2D(jsonObj, b6_actionId_arr) + /* eg: ['K_A','a9','0','NCAPS','â']*/ const b1_modifierKey_arr: string[][] = this.get_KeyMapModiKeyArray__from__array(jsonObj, b1_keycode_arr, isCapsused) + // ....................................................................................................................................................................................... + + for (let n1 = 0; n1 < b4_deadkeyModifier_arr.length; n1++) { + for (let n2 = 0; n2 < b4_deadkeyModifier_arr[n1].length; n2++) { + for (let n3 = 0; n3 < b4_deadkey_arr.length; n3++) { + for (let n4 = 0; n4 < b1_modifierKey_arr.length; n4++) { + + rule_obj = new Rules( + /* rule_type */ "C2", + + /* modifier_prev_deadkey*/ "", + /* prev_deadkey */ "", + /* id_prev_deadkey */ 0, + /* unique A */ 0, + + /* modifier_deadkey */ this.create_kmn_modifier(b4_deadkeyModifier_arr[n1][n2], isCapsused), + /* deadkey */ this.map_UkeleleKC_To_VK(Number(b4_deadkey_arr[n3][0])), + /* dk for C2*/ dk_counter_C2++, + /* unique B */ 0, + + /* modifier_key*/ b1_modifierKey_arr[n4][3], + /* key */ b1_modifierKey_arr[n4][0], + /* output */ new TextEncoder().encode(b1_modifierKey_arr[n4][4]), ) - if (b1_KeyMapModiKey_arr[n4][4] !== undefined) - ObjectArray.push(RuleObj) + if (b1_modifierKey_arr[n4][4] !== undefined) + object_array.push(rule_obj) } } } @@ -470,81 +465,85 @@ export class KeylayoutToKmnConverter { } } - // ...................................................................................................... - // case C3: action + state Nr + Next .................................................................... - // ...............e. g. ....................................................... - // replace state x with all rules that result in 1 ( ................................................................................ + // replace state x with all rules that result in 1 ( for action id a16 ............................................................................................................................. + for (let l = 0; l < jsonObj.keyboard.actions.action[b1_actionIndex].when.length; l++) { if ((jsonObj.keyboard.actions.action[b1_actionIndex].when[l]['@_state'] !== "none") && (jsonObj.keyboard.actions.action[b1_actionIndex].when[l]['@_next'] !== undefined)) { - // Data of Block Nr 5 .................................................................................................................... - /* eg: state = 3 */ const b5_value_state: string = jsonObj.keyboard.actions.action[b1_actionIndex].when[l]['@_state'] - /* eg: next = 1 */ const b5_value_next: string = jsonObj.keyboard.actions.action[b1_actionIndex].when[l]['@_next'] - /* eg: StateNextID = a16 */ const b5_actionId_arr: string[] = jsonObj.keyboard.actions.action[b1_actionIndex]['@_id'] - // ....................................................................................................................................... - - // Data of Block Nr 4 .................................................................................................................... - /* eg: [ '6', '24', '24' ]*/ const b4_code_arr: string[] = this.get_KeyMap_Code_array__From__KeyMap_Action(jsonObj, b5_actionId_arr) - /* eg: [['24', 0], ['24', 3]] */ const b4_keyBehaviour_arr: number[][] = this.get_KeyMap_Code_array__From__ActionID_Action(jsonObj, String(action_id)) - /* e.g. [['','caps?'], ['Caps']]*/ const b4_modifier2D_arr: string[] = this.get_KeyMap_Modifier_array__From__behaviour_arr(data_ukelele.arrayOf_Modifiers, b4_keyBehaviour_arr) - // ....................................................................................................................................... - - // Data of Block Nr 3 .................................................................................................................... - /* eg: actioniD = a17 */ const b3_actionId: string = this.get_ActionID_Id__From__ActionID_next(jsonObj, b5_value_state) - // ....................................................................................................................................... - - // Data of Block Nr 2 .................................................................................................................... - /* eg: ['K_8', 'K_M] */ const b2_keyname_arr: string[] = this.get_KecCode_arr__From__ActionId(jsonObj, b3_actionId) - /* eg: index=3 */ const b2_keyBehaviour_arr: number[][] = this.get_KeyMap_Code_array__From__ActionID_Action(jsonObj, String(b3_actionId)) - /* e.g. [[ '0','1shift? caps?']]*/ const b2_modifier_arr_all: string[] = this.get_KeyMap_Modifier_array__From__behaviour_arr(data_ukelele.arrayOf_Modifiers, b2_keyBehaviour_arr) - // ....................................................................................................................................... - - // Data of Block Nr 6 .................................................................................................................... + // Data of Block Nr 5 ........................................................................................................................................................................ + // of this state-next-pair get value of next (next="1") and state="3" ........................................................................................................................ + /* e.g. state = 3 */ const b5_value_state: string = jsonObj.keyboard.actions.action[b1_actionIndex].when[l]['@_state'] + /* e.g. next = 1 */ const b5_value_next: string = jsonObj.keyboard.actions.action[b1_actionIndex].when[l]['@_next'] + // ........................................................................................................................................................................................... + + // Data of Block Nr 4 ........................................................................................................................................................................ + // with present action_id (a16) find all keycode-behaviour-pairs that use this action (a16) => (keymapIndex 3/keycode 32) .................................................................... + // from these create an array of modifier combinations e.g. [ [ 'anyOption', 'Caps' ] ] ..................................................................................................... + /* e.g. [['32', 3]] */ const b4_deadkey_arr: number[][] = this.get_KeyMap_Code_array__From__ActionID_Action(jsonObj, String(action_id)) + /* e.g. [ [ 'anyOption', 'Caps' ] ]*/ const b4_deadkeyModifier_arr: string[] = this.get_KeyMap_Modifier_array__From__behaviour_arr(data_ukelele.arrayOf_Modifiers, b4_deadkey_arr) + // ........................................................................................................................................................................................... + + // Data of Block Nr 3 ........................................................................................................................................................................ + // get an action id from a state-output-pair that use state = b5_value_state (e.g. use 3 in ) ................................................................. + /* e.g. actioniD = a17 */ const b3_actionId: string = this.get_ActionID_Id__From__ActionID_next(jsonObj, b5_value_state) + // ........................................................................................................................................................................................... + + // Data of Block Nr 2 ....................................................................................................................................................................... + // with present action_id (a17) find all keynames and behaviours that use this action (a17) => (keymapIndex 3/keycode 28) .................................................................... + // from these create an array of modifier combinations e.g. [ [ 'anyOption', 'Caps' ] ] ..................................................................................................... + /* eg: index=3 */ const b2_prev_deadkey_arr: number[][] = this.get_KeyMap_Code_array__From__ActionID_Action(jsonObj, String(b3_actionId)) + /* e.g. [ [ 'anyOption', 'Caps' ] ] */ const b2_prev_deadkeyModifier_arr: string[] = this.get_KeyMap_Modifier_array__From__behaviour_arr(data_ukelele.arrayOf_Modifiers, b2_prev_deadkey_arr) + // ........................................................................................................................................................................................... + + // Data of Block Nr 6 ........................................................................................................................................................................ + // create an array[action id,state,output] from all state-output-pairs that use state = b5_value_next (e.g. use 1 in ) ......................................... /* eg: [ 'a9','1','â'] */ const b6_actionId_arr: string[][] = this.get_ActionID_Output_array__From__ActionID_State(jsonObj, b5_value_next) - // ....................................................................................................................................... + // ........................................................................................................................................................................................... - // Data of Block Nr 1 .................................................................................................................... + // Data of Block Nr 1 ....................................................................................................................................................................... + // create array[Keycode,Keyname,action id,actionIndex,output] and array[Keyname,action id,behaviour,modifier,output] ......................................................................... /* eg: ['49','K_SPACE','a0','0','Â'] */ const b1_keycode_arr: string[][] = this.get_KeyMap_Code_array__From__KeyMap_Action_array2D(jsonObj, b6_actionId_arr) - /* eg: ['K_SPACE','a0','0','NCAPS','Â']*/ const b1_KeyMapModiKey_arr: string[][] = this.get_KeyMapModiKeyArray__from__array(jsonObj, b1_keycode_arr, isCapsused) - // ....................................................................................................................................... - - for (let n1 = 0; n1 < b2_modifier_arr_all.length; n1++) { - for (let n2 = 0; n2 < b2_modifier_arr_all[n1].length; n2++) { - for (let n3 = 0; n3 < b2_keyname_arr.length; n3++) { - for (let n4 = 0; n4 < b4_modifier2D_arr.length; n4++) { - for (let n5 = 0; n5 < b4_modifier2D_arr[n4].length; n5++) { - for (let n6 = 0; n6 < b4_code_arr.length; n6++) { - for (let n7 = 0; n7 < b1_KeyMapModiKey_arr.length; n7++) { - - RuleObj = new Rules( - /* rule_type */ "C3", - - /* modifier_prev_deadkey*/ this.create_kmn_modifier(b2_modifier_arr_all[n1][n2], isCapsused), - /* prev_deadkey */ b2_keyname_arr[n3], - /* dk_prev */ dk_counter_C3_A++, - /* unique A */ 0, - - /* modifier_deadkey */ this.create_kmn_modifier(b4_modifier2D_arr[n4][n5], isCapsused), - /* deadkey */ this.map_UkeleleKC_To_VK(Number(b4_code_arr[n6])), - /* dk*/ dk_counter_C3_B++, - /* dk for C2*/ 0, - /* unique B */ 0, - - /* modifier_key*/ b1_KeyMapModiKey_arr[n7][3], - /* key */ b1_KeyMapModiKey_arr[n7][0], - /* output */ new TextEncoder().encode(b1_KeyMapModiKey_arr[n7][4]), + /* eg: ['K_SPACE','a0','0','NCAPS','Â'] */ const b1_modifierKey_arr: string[][] = this.get_KeyMapModiKeyArray__from__array(jsonObj, b1_keycode_arr, isCapsused) + // ........................................................................................................................................................................................... + + for (let n1 = 0; n1 < b2_prev_deadkeyModifier_arr.length; n1++) { + for (let n2 = 0; n2 < b2_prev_deadkeyModifier_arr[n1].length; n2++) { + for (let n3 = 0; n3 < b2_prev_deadkey_arr.length; n3++) { + for (let n4 = 0; n4 < b4_deadkeyModifier_arr.length; n4++) { + for (let n5 = 0; n5 < b4_deadkeyModifier_arr[n4].length; n5++) { + for (let n6 = 0; n6 < b4_deadkey_arr.length; n6++) { + for (let n7 = 0; n7 < b1_modifierKey_arr.length; n7++) { + + rule_obj = new Rules( + /* rule_type */ "C3", + /* modifier_prev_deadkey*/ this.create_kmn_modifier(b2_prev_deadkeyModifier_arr[n1][n2], isCapsused), + /* prev_deadkey */ this.map_UkeleleKC_To_VK(Number(b2_prev_deadkey_arr[n3][0])), + /* id_prev_deadkey */ dk_counter_C3_A++, + /* unique A */ 0, + + /* modifier_deadkey */ this.create_kmn_modifier(b4_deadkeyModifier_arr[n4][n5], isCapsused), + /* deadkey */ this.map_UkeleleKC_To_VK(Number(b4_deadkey_arr[n6][0])), + /* dk for C2*/ 0, + /* unique B */ 0, + + /* modifier_key*/ b1_modifierKey_arr[n7][3], + /* key */ b1_modifierKey_arr[n7][0], + /* output */ new TextEncoder().encode(b1_modifierKey_arr[n7][4]), ) - if (b1_KeyMapModiKey_arr[n7][4] !== undefined) - ObjectArray.push(RuleObj) + if (b1_modifierKey_arr[n7][4] !== undefined) + object_array.push(rule_obj) } } } @@ -563,7 +562,7 @@ export class KeylayoutToKmnConverter { // --------------------------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------------------------- // now prepare for printing i.e. check for duplicate C2 and C3 rules and mark first occurance of rule - // add nr to uniqueA, uniqueB if it is the first occurence of declaration of dk e.g. [NCAPS RALT K_8] > dk(C12) + // add nr to unique_prev_deadkey, unique_deadkey if it is the first occurence of declaration of dk e.g. [NCAPS RALT K_8] > dk(C12) // --------------------------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------------------------- let unique_dkB_count = 0 @@ -571,27 +570,27 @@ export class KeylayoutToKmnConverter { //----------------------------------- -dk---------------------------------- // first rule is always unique - ObjectArray[0].uniqueB = unique_dkB_count - ObjectArray[0].dk_C2 = unique_dkB_count + object_array[0].unique_deadkey = unique_dkB_count + object_array[0].id_deadkey = unique_dkB_count unique_dkB_count++ - for (let i = 0; i < ObjectArray.length; i++) { - if ((ObjectArray[i].modifier_deadkey !== "") && (ObjectArray[i].deadkey !== "")) { + for (let i = 0; i < object_array.length; i++) { + if ((object_array[i].modifier_deadkey !== "") && (object_array[i].deadkey !== "")) { let isUnique_dkB: boolean = true // check if not used before for (let j = 0; j < i; j++) { - if ((ObjectArray[i].modifier_deadkey === ObjectArray[j].modifier_deadkey) - && (ObjectArray[i].deadkey === ObjectArray[j].deadkey)) { + if ((object_array[i].modifier_deadkey === object_array[j].modifier_deadkey) + && (object_array[i].deadkey === object_array[j].deadkey)) { isUnique_dkB = isUnique_dkB && false } } if (isUnique_dkB) { const ruleArray: string[] = [] - ObjectArray[i].uniqueB = unique_dkB_count - ruleArray.push(ObjectArray[i].modifier_deadkey) - ruleArray.push(ObjectArray[i].deadkey) + object_array[i].unique_deadkey = unique_dkB_count + ruleArray.push(object_array[i].modifier_deadkey) + ruleArray.push(object_array[i].deadkey) ruleArray.push(String(unique_dkB_count)) unique_dkB_count++ unique_ruleArrayC2.push(ruleArray) @@ -603,36 +602,36 @@ export class KeylayoutToKmnConverter { let unique_dkA_count = 0 // first rule is always unique - ObjectArray[0].uniqueA = unique_dkA_count + object_array[0].unique_prev_deadkey = unique_dkA_count unique_dkA_count++ - for (let i = 0; i < ObjectArray.length; i++) { - if ((ObjectArray[i].modifier_prev_deadkey !== "") && (ObjectArray[i].prev_deadkey !== "")) { + for (let i = 0; i < object_array.length; i++) { + if ((object_array[i].modifier_prev_deadkey !== "") && (object_array[i].prev_deadkey !== "")) { let isUnique_dkA: boolean = true // check if not used before for (let j = 0; j < i; j++) { - if ((ObjectArray[i].modifier_prev_deadkey === ObjectArray[j].modifier_prev_deadkey) - && (ObjectArray[i].prev_deadkey === ObjectArray[j].prev_deadkey)) { + if ((object_array[i].modifier_prev_deadkey === object_array[j].modifier_prev_deadkey) + && (object_array[i].prev_deadkey === object_array[j].prev_deadkey)) { isUnique_dkA = isUnique_dkA && false } } if (isUnique_dkA) { - ObjectArray[i].uniqueA = unique_dkA_count + object_array[i].unique_prev_deadkey = unique_dkA_count unique_dkA_count++ // check if first part of C3 rule contains already defined rule for (let k = 0; k < unique_ruleArrayC2.length; k++) { - if ((unique_ruleArrayC2[k][0] === ObjectArray[i].modifier_deadkey) && ((unique_ruleArrayC2[k][1] === ObjectArray[i].deadkey))) - ObjectArray[i].uniqueB = Number(unique_ruleArrayC2[k][2]) + if ((unique_ruleArrayC2[k][0] === object_array[i].modifier_deadkey) && ((unique_ruleArrayC2[k][1] === object_array[i].deadkey))) + object_array[i].unique_deadkey = Number(unique_ruleArrayC2[k][2]) } } if (isUnique_dkA) { const ruleArray: string[] = [] - ObjectArray[i].uniqueB = unique_dkB_count - ruleArray.push(ObjectArray[i].modifier_prev_deadkey) - ruleArray.push(ObjectArray[i].prev_deadkey) + object_array[i].unique_deadkey = unique_dkB_count + ruleArray.push(object_array[i].modifier_prev_deadkey) + ruleArray.push(object_array[i].prev_deadkey) ruleArray.push(String(unique_dkB_count)) unique_dkB_count++ unique_ruleArrayC2.push(ruleArray) @@ -640,19 +639,19 @@ export class KeylayoutToKmnConverter { } } - for (let i = 0; i < ObjectArray.length; i++) { + for (let i = 0; i < object_array.length; i++) { for (let j = 0; j < unique_ruleArrayC2.length; j++) { - if ((ObjectArray[i].modifier_prev_deadkey === unique_ruleArrayC2[j][0]) && (ObjectArray[i].prev_deadkey === unique_ruleArrayC2[j][1])) { + if ((object_array[i].modifier_prev_deadkey === unique_ruleArrayC2[j][0]) && (object_array[i].prev_deadkey === unique_ruleArrayC2[j][1])) { // write unique nr into rule obj - ObjectArray[i].dk_prev = Number(unique_ruleArrayC2[j][2]) + object_array[i].id_prev_deadkey = Number(unique_ruleArrayC2[j][2]) } - if ((ObjectArray[i].modifier_deadkey === unique_ruleArrayC2[j][0]) && (ObjectArray[i].deadkey === unique_ruleArrayC2[j][1])) { + if ((object_array[i].modifier_deadkey === unique_ruleArrayC2[j][0]) && (object_array[i].deadkey === unique_ruleArrayC2[j][1])) { // write nr into rule obj - ObjectArray[i].dk_C2 = Number(unique_ruleArrayC2[j][2]) + object_array[i].id_deadkey = Number(unique_ruleArrayC2[j][2]) } } } - data_ukelele.arrayOf_Rules = ObjectArray + data_ukelele.arrayOf_Rules = object_array return data_ukelele } @@ -677,11 +676,11 @@ export class KeylayoutToKmnConverter { } return returnarray } - /* - in: Block 5 - b5_actionId_arr a16, a18 - out: Block 4 - b4_code_arr [ '6', '31', '32' ] - do: create array of keycodes from an array of keymapIndex - */ + /* + in: Block 5 - b5_actionId_arr a16, a18 + out: Block 4 - b4_code_arr [ '6', '31', '32' ] + do: create array of keycodes from an array of keymapIndex + */ public get_KeyMap_Code_array__From__KeyMap_Action(data: any, search: string[]): string[] { const returnarray: string[] = [] for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { @@ -695,11 +694,11 @@ export class KeylayoutToKmnConverter { } return returnarray } - /* - in: Block 6 - b6_actionId_arr [ 'a9','1','â'] - out: Block 1 - b1_keycode_arr ['49','K_SPACE','a0','0','Â'] - do: create array of ['49','K_SPACE','a0','0','Â'] from create array of [ 'a9','1','â'] - */ + /* + in: Block 6 - b6_actionId_arr [ 'a9','1','â'] + out: Block 1 - b1_keycode_arr ['49','K_SPACE','a0','0','Â'] + do: create array of ['49','K_SPACE','a0','0','Â'] from create array of [ 'a9','1','â'] + */ public get_KeyMap_Code_array__From__KeyMap_Action_array2D(data: any, search: string[][]): string[][] { const returnarray2D: string[][] = [] for (let k = 0; k < search.length; k++) { @@ -722,11 +721,11 @@ export class KeylayoutToKmnConverter { } return returnarray2D } - /* - in: action_id a19 - out: b1_actionIndex behav. 1 - do: get the actionIdIndex from action id a18 - */ + /* + in: action_id a19 + out: b1_actionIndex behav. 1 + do: get the actionIdIndex from action id a18 + */ public get_ActionID_Index__From__ActionID_Id(data: any, search: string): number { for (let i = 0; i < data.keyboard.actions.action.length; i++) { if (data.keyboard.actions.action[i]['@_id'] === search) @@ -735,11 +734,11 @@ export class KeylayoutToKmnConverter { return 0 } - /* - in: Block 5 - b5_value_state state = 3 - out: Block 3 - b3_actionId a19 - do: get the actionIdI from state / next - */ + /* + in: Block 5 - b5_value_state state = 3 + out: Block 3 - b3_actionId a19 + do: get the actionIdI from state / next +*/ public get_ActionID_Id__From__ActionID_next(data: any, search: string): string { if (search !== "none") { for (let i = 0; i < data.keyboard.actions.action.length; i++) { @@ -752,11 +751,11 @@ export class KeylayoutToKmnConverter { } return "" } - /* - in: Block 5 - b5_value_next next = 1 - out: Block 6 - b6_actionId_arr 'a9','1','â'] - do: create array of [ 'a9','1','â'] from state / next - */ + /* + in: Block 5 - b5_value_next next = 1 + out: Block 6 - b6_actionId_arr 'a9','1','â'] + do: create array of [ 'a9','1','â'] from state / next +*/ public get_ActionID_Output_array__From__ActionID_State(data: any, search: string) { const returnarray2D: string[][] = [] for (let i = 0; i < data.keyboard.actions.action.length; i++) { @@ -773,29 +772,54 @@ export class KeylayoutToKmnConverter { } return returnarray2D } - /* - in: Block 1 - action_id a18 - out: Block 6 - outputchar 'A' - do: create output Array from action_id - */ + /* + in: Block 1 - action_id a18 + out: Block 6 - outputchar 'A' + do: create output Array from action_id +*/ public get_Action2ID_NoneOutput__From__ActionID_Id(data: any, search: string): string { let OutputValue: string = "" + + if (search === "a0") + console.log("search ", search) + for (let i = 0; i < data.keyboard.actions.action.length; i++) { if (data.keyboard.actions.action[i]['@_id'] === search) { + + + for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { + + /* console.log("data.keyboard.actions.action.length ", + i, j, + data.keyboard.actions.action.length, + data.keyboard.actions.action[i]['@_id'], + search, + data.keyboard.actions.action[i].when.length, + data.keyboard.actions.action[i].when[j]['@_output'], + OutputValue + )*/ if (data.keyboard.actions.action[i].when[j]['@_state'] === "none") { OutputValue = data.keyboard.actions.action[i].when[j]['@_output'] + // console.log("OutputValue ", OutputValue) + } } } } + if (search === "a19") + console.log(" OutputValue a19", OutputValue, "..") + if (search === "a0") + console.log(" OutputValue a0", OutputValue, "..") + + return OutputValue } - /* - in: Block 1 - b1_keycode_arr ['49','K_SPACE','a0','0','Â'] - out: Block 1 - b1_KeyMapModiKey_arr ['K_SPACE','a0','0','NCAPS','Â'] - do: create array of key+modi+out from array of b1_keycode_arr - */ + /* + in: Block 1 - b1_keycode_arr ['49','K_SPACE','a0','0','Â'] + out: Block 1 - b1_modifierKey_arr ['K_SPACE','a0','0','NCAPS','Â'] + do: create array of key+modi+out from array of b1_keycode_arr +*/ public get_KeyMapModiKeyArray__from__array(data: any, search: string[][], isCAPSused: boolean): string[][] { const returnarray: string[][] = [] @@ -826,18 +850,18 @@ export class KeylayoutToKmnConverter { ); return unique_returnarray } - /* ?? - in: Block C1 - action_id a19 - in: Block C1 - out 'A' - out: Block C1 - b1_KeyMapModiKey_arr - do: create array of key+mod+out from array of b1_KeyMapModiKey_arr - */ + /* ?? + in: Block C1 - action_id a19 + in: Block C1 - out 'A' + out: Block C1 - b1_modifierKey_arr + do: create array of key+mod+out from array of b1_modifierKey_arr +*/ public get_Datat_array2D__From__ActionID_stateOutput(data: any, modi: any, search: string, outchar: string, isCapsused: boolean): string[][] { const returnarray2D: string[][] = [] // loop behaviors ( in ukelele it is possible to define multiple modifier combinations that behave in the same) for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { - for (let j = 0; j <= KeylayoutToKmnConverter.USED_KEYS_COUNT; j++) { + for (let j = 0; j < KeylayoutToKmnConverter.USED_KEYS_COUNT; j++) { if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { for (let k = 0; k < modi[data.keyboard.keyMapSet[0].keyMap[i]['@_index']].length; k++) { const returnarray: string[] = [] @@ -872,15 +896,16 @@ export class KeylayoutToKmnConverter { return unique_returnarray } - /* - in: Block - action_id a19 - out: Block 4 - b4_keyBehaviour_arr [['24', 0], ['24', 3]] - do: create array of [['24', 0], ['24', 3]] from behaviour id - */ + /* + in: Block - action_id a19 + out: Block 4 - b4_deadkey_arr [['24', 0], ['24', 3]] + do: create array of [['24', 0], ['24', 3]] from behaviour id +*/ public get_KeyMap_Code_array__From__ActionID_Action(data: any, search: string): number[][] { const mapIndexArray_max: number[][] = [] for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { - for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { + for (let j = 0; j < KeylayoutToKmnConverter.USED_KEYS_COUNT; j++) { + const mapIndexArrayperKey: number[] = [] if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { @@ -893,11 +918,11 @@ export class KeylayoutToKmnConverter { } return mapIndexArray_max } - /* - in: Block 4 - b4_keyBehaviour_arr [['24', 0], ['24', 3]] - out: Block 4 - b4_modifier2D_arr [['','caps?'], ['Caps']] - do: create array of from array of b4_keyBehaviour_arr - */ + /* + in: Block 4 - b4_deadkey_arr [['24', 0], ['24', 3]] + out: Block 4 - b4_deadkeyModifier_arr [['','caps?'], ['Caps']] + do: create array of from array of b4_deadkey_arr +*/ public get_KeyMap_Modifier_array__From__behaviour_arr(data: any, search: number[][]): string[] { const mapIndexArray_max: string[] = [] for (let i = 0; i < search.length; i++) { @@ -1086,7 +1111,7 @@ export class KeylayoutToKmnConverter { curr.rule_type === "C2" && curr.modifier_deadkey === rule[index].modifier_deadkey && curr.deadkey === rule[index].deadkey - && curr.dk_C2 !== rule[index].dk_C2 || curr.dk !== rule[index].dk + && curr.id_deadkey !== rule[index].id_deadkey && idx < index ); @@ -1095,27 +1120,26 @@ export class KeylayoutToKmnConverter { curr.rule_type === "C2" && curr.modifier_deadkey === rule[index].modifier_deadkey && curr.deadkey === rule[index].deadkey - && curr.dk_C2 === rule[index].dk_C2 - && curr.dk === rule[index].dk + && curr.id_deadkey === rule[index].id_deadkey && idx < index ); //3-3 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'B' const amb_3_3 = rule.filter((curr, idx) => (curr.rule_type === "C2") - && curr.dk_C2 === rule[index].dk_C2 + && curr.id_deadkey === rule[index].id_deadkey && curr.modifier_key === rule[index].modifier_key && curr.key === rule[index].key && new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output) && idx < index - // && rule[index].uniqueB !== 0 + // && rule[index].unique_deadkey !== 0 ); //3-3 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'Ã' const dup_3_3 = rule.filter((curr, idx) => (curr.rule_type === "C2") - && curr.dk_C2 === rule[index].dk_C2 - && rule[index].uniqueB === 0 + && curr.id_deadkey === rule[index].id_deadkey + && rule[index].unique_deadkey === 0 && curr.modifier_key === rule[index].modifier_key && curr.key === rule[index].key && new TextDecoder().decode(curr.output) === new TextDecoder().decode(rule[index].output) @@ -1127,21 +1151,21 @@ export class KeylayoutToKmnConverter { ((curr.rule_type === "C0") || (curr.rule_type === "C1")) && curr.modifier_key === rule[index].modifier_deadkey && curr.key === rule[index].deadkey - //&& rule[index].uniqueB === 0 // include and the first occurance will be printed + //&& rule[index].unique_deadkey === 0 // include and the first occurance will be printed //&& (idx < index) // include and the first occurance will be printed ); if (amb_2_2.length > 0) { - warningTextArray[1] = warningTextArray[1] + ("C2 SECONDTEXT " + "ambiguous 2-2 rule: earlier: [" + amb_2_2[0].modifier_deadkey + " " + amb_2_2[0].deadkey + "] > dk(C" + amb_2_2[0].dk_C2 + ") here: ") + warningTextArray[1] = warningTextArray[1] + ("C2 SECONDTEXT " + "ambiguous 2-2 rule: earlier: [" + amb_2_2[0].modifier_deadkey + " " + amb_2_2[0].deadkey + "] > dk(C" + amb_2_2[0].id_deadkey + ") here: ") } if (dup_2_2.length > 0) { - warningTextArray[1] = warningTextArray[1] + ("C2 SECONDTEXT " + "duplicate 2-2 rule: earlier: [" + dup_2_2[0].modifier_deadkey + " " + dup_2_2[0].deadkey + "] > dk(C" + dup_2_2[0].dk_C2 + ") here: ") + warningTextArray[1] = warningTextArray[1] + ("C2 SECONDTEXT " + "duplicate 2-2 rule: earlier: [" + dup_2_2[0].modifier_deadkey + " " + dup_2_2[0].deadkey + "] > dk(C" + dup_2_2[0].id_deadkey + ") here: ") } if (amb_3_3.length > 0) { - warningTextArray[2] = warningTextArray[2] + ("C2 THIRDTEXT " + "ambiguous y 3-3 rule: earlier: dk(C" + amb_3_3[0].dk_C2 + ") + [" + amb_3_3[0].modifier_key + " " + amb_3_3[0].key + "] > \'" + new TextDecoder().decode(amb_3_3[0].output) + "\' here: ") + warningTextArray[2] = warningTextArray[2] + ("C2 THIRDTEXT " + "ambiguous y 3-3 rule: earlier: dk(C" + amb_3_3[0].id_deadkey + ") + [" + amb_3_3[0].modifier_key + " " + amb_3_3[0].key + "] > \'" + new TextDecoder().decode(amb_3_3[0].output) + "\' here: ") } if (dup_3_3.length > 0) { - warningTextArray[2] = warningTextArray[2] + ("C2 THIRDTEXT " + "duplicate y 3-3 rule: earlier: dk(C" + dup_3_3[0].dk_C2 + ") + [" + dup_3_3[0].modifier_key + " " + dup_3_3[0].key + "] > \'" + new TextDecoder().decode(dup_3_3[0].output) + "\' here: ") + warningTextArray[2] = warningTextArray[2] + ("C2 THIRDTEXT " + "duplicate y 3-3 rule: earlier: dk(C" + dup_3_3[0].id_deadkey + ") + [" + dup_3_3[0].modifier_key + " " + dup_3_3[0].key + "] > \'" + new TextDecoder().decode(dup_3_3[0].output) + "\' here: ") } if (amb_1_2.length > 0) { warningTextArray[1] = warningTextArray[1] + ("C2 SECONDTEXT " + "ambiguous 1-2 rule: earlier: [" + amb_1_2[0].modifier_key + " " + amb_1_2[0].key + "] > \'" + new TextDecoder().decode(amb_1_2[0].output) + "\' here: ") @@ -1155,7 +1179,7 @@ export class KeylayoutToKmnConverter { ((curr.rule_type === "C0") || (curr.rule_type === "C1")) && curr.modifier_key === rule[index].modifier_prev_deadkey && curr.key === rule[index].prev_deadkey - //&& rule[index].uniqueA === 0 // include and the first occurance will be printed + //&& rule[index].unique_prev_deadkey === 0 // include and the first occurance will be printed //&& (idx < index) ); @@ -1164,30 +1188,30 @@ export class KeylayoutToKmnConverter { ((curr.rule_type === "C2")) && curr.modifier_deadkey === rule[index].modifier_prev_deadkey && curr.deadkey === rule[index].prev_deadkey - && curr.dk_C2 === rule[index].dk_prev - // && rule[index].uniqueA === 0 // include and the first occurance will be printed + && curr.id_deadkey === rule[index].id_prev_deadkey + // && rule[index].unique_prev_deadkey === 0 // include and the first occurance will be printed // && (idx < index) ); // 6-3 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'B' const amb_6_3 = rule.filter((curr, idx) => (curr.rule_type === "C2") - && curr.dk_prev === rule[index].dk_prev + && curr.id_prev_deadkey === rule[index].id_prev_deadkey && curr.modifier_key === rule[index].modifier_key && curr.key === rule[index].key && (new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output)) - // && rule[index].uniqueB !== 0 + // && rule[index].unique_deadkey !== 0 // && idx < index ); // 6-3 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'Ã' const dup_6_3 = rule.filter((curr, idx) => (curr.rule_type === "C2") - && curr.dk_prev === rule[index].dk_prev + && curr.id_prev_deadkey === rule[index].id_prev_deadkey && curr.modifier_key === rule[index].modifier_key && curr.key === rule[index].key && new TextDecoder().decode(curr.output) === new TextDecoder().decode(rule[index].output) - // && rule[index].uniqueB === 0 + // && rule[index].unique_deadkey === 0 // && idx < index ); @@ -1195,9 +1219,9 @@ export class KeylayoutToKmnConverter { const amb_4_4_mid = rule.filter((curr, idx) => curr.rule_type === "C3" && curr.modifier_prev_deadkey === rule[index].modifier_prev_deadkey - && curr.dk_prev !== rule[index].dk_prev + && curr.id_prev_deadkey !== rule[index].id_prev_deadkey && curr.prev_deadkey === rule[index].prev_deadkey - && rule[index].uniqueA !== 0 + && rule[index].unique_prev_deadkey !== 0 && idx < index ); @@ -1206,17 +1230,16 @@ export class KeylayoutToKmnConverter { curr.rule_type === "C3" && curr.modifier_prev_deadkey === rule[index].modifier_prev_deadkey && curr.prev_deadkey === rule[index].prev_deadkey - && curr.dk_prev === rule[index].dk_prev + && curr.id_prev_deadkey === rule[index].id_prev_deadkey && idx < index - // && rule[index].uniqueA !== 0 + // && rule[index].unique_prev_deadkey !== 0 ); // 6-6 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'B' const amb_6_6 = rule.filter((curr, idx) => (curr.rule_type === "C3") - && curr.dk_C2 === rule[index].dk_C2 - && rule[index].uniqueA !== 0 - && curr.dk === rule[index].dk + && curr.id_deadkey === rule[index].id_deadkey + && rule[index].unique_prev_deadkey !== 0 && curr.modifier_key === rule[index].modifier_key && curr.key === rule[index].key && (new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output)) @@ -1227,7 +1250,7 @@ export class KeylayoutToKmnConverter { // 6-6 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'Ã' const dup_6_6 = rule.filter((curr, idx) => (curr.rule_type === "C3") - && curr.dk_C2 === rule[index].dk_C2 + && curr.id_deadkey === rule[index].id_deadkey && curr.modifier_key === rule[index].modifier_key && curr.key === rule[index].key && (new TextDecoder().decode(curr.output) === new TextDecoder().decode(rule[index].output)) @@ -1239,11 +1262,10 @@ export class KeylayoutToKmnConverter { (curr.rule_type === "C3") && curr.modifier_key === rule[index].modifier_key && curr.key === rule[index].key - && curr.dk_C2 === rule[index].dk_C2 + && curr.id_deadkey === rule[index].id_deadkey && (new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output)) && idx < index - //&& rule[index].uniqueA !== 0 - //&& String(curr.dk) === String(rule[index].dk) + //&& rule[index].unique_prev_deadkey !== 0 ); // 5-5 @@ -1251,10 +1273,9 @@ export class KeylayoutToKmnConverter { (curr.rule_type === "C3") && curr.modifier_deadkey === rule[index].modifier_deadkey && curr.deadkey === rule[index].deadkey - && curr.dk_prev === rule[index].dk_prev - && curr.dk_C2 === rule[index].dk_C2 - && curr.dk === rule[index].dk - && rule[index].uniqueB === 0 + && curr.id_prev_deadkey === rule[index].id_prev_deadkey + && curr.id_deadkey === rule[index].id_deadkey + && rule[index].unique_deadkey === 0 //&& idx < index ); @@ -1263,39 +1284,39 @@ export class KeylayoutToKmnConverter { } if (amb_2_4.length > 0) { - warningTextArray[0] = warningTextArray[0] + ("C3 FIRSTTEXT " + "ambiguous 2-4 rule: earlier(Todo check if print out or not): [" + amb_2_4[0].modifier_deadkey + " " + amb_2_4[0].deadkey + "] > dk(C" + amb_2_4[0].dk_C2 + ") here: ") + warningTextArray[0] = warningTextArray[0] + ("C3 FIRSTTEXT " + "ambiguous 2-4 rule: earlier(Todo check if print out or not): [" + amb_2_4[0].modifier_deadkey + " " + amb_2_4[0].deadkey + "] > dk(C" + amb_2_4[0].id_deadkey + ") here: ") } if (amb_6_3.length > 0) { - warningTextArray[1] = warningTextArray[1] + ("C3 SECONDTEXT " + "ambiguous y 6-3 rule: earlier: dk(C" + amb_6_3[0].dk_C2 + ") + [" + amb_6_3[0].modifier_key + " " + amb_6_3[0].key + "] > \'" + new TextDecoder().decode(amb_6_3[0].output) + "\' here: ") + warningTextArray[1] = warningTextArray[1] + ("C3 SECONDTEXT " + "ambiguous y 6-3 rule: earlier: dk(C" + amb_6_3[0].id_deadkey + ") + [" + amb_6_3[0].modifier_key + " " + amb_6_3[0].key + "] > \'" + new TextDecoder().decode(amb_6_3[0].output) + "\' here: ") } if (dup_6_3.length > 0) { - warningTextArray[1] = warningTextArray[1] + ("C3 SECONDTEXT " + "duplicate y 6-3 rule: earlier: dk(C" + dup_6_3[0].dk_C2 + ") + [" + dup_6_3[0].modifier_key + " " + dup_6_3[0].key + "] > \'" + new TextDecoder().decode(dup_6_3[0].output) + "\' here: ") + warningTextArray[1] = warningTextArray[1] + ("C3 SECONDTEXT " + "duplicate y 6-3 rule: earlier: dk(C" + dup_6_3[0].id_deadkey + ") + [" + dup_6_3[0].modifier_key + " " + dup_6_3[0].key + "] > \'" + new TextDecoder().decode(dup_6_3[0].output) + "\' here: ") } if (amb_4_4_mid.length > 0) { - warningTextArray[0] = warningTextArray[0] + ("C3 FIRSTTEXT " + "ambiguous 4-4 rule: earlier: [" + amb_4_4_mid[0].modifier_prev_deadkey + " " + amb_4_4_mid[0].prev_deadkey + "] > dk(C" + amb_4_4_mid[0].dk_prev + ") here: ") + warningTextArray[0] = warningTextArray[0] + ("C3 FIRSTTEXT " + "ambiguous 4-4 rule: earlier: [" + amb_4_4_mid[0].modifier_prev_deadkey + " " + amb_4_4_mid[0].prev_deadkey + "] > dk(C" + amb_4_4_mid[0].id_prev_deadkey + ") here: ") } if (dup_4_4.length > 0) { - warningTextArray[0] = warningTextArray[0] + ("C3 FIRSTTEXT " + "duplicate 4-4 rule: earlier: [" + dup_4_4[0].modifier_prev_deadkey + " " + dup_4_4[0].prev_deadkey + "] > dk(C" + dup_4_4[0].dk_prev + ") here: ") + warningTextArray[0] = warningTextArray[0] + ("C3 FIRSTTEXT " + "duplicate 4-4 rule: earlier: [" + dup_4_4[0].modifier_prev_deadkey + " " + dup_4_4[0].prev_deadkey + "] > dk(C" + dup_4_4[0].id_prev_deadkey + ") here: ") } if (amb_5_5.length > 0) { - warningTextArray[1] = warningTextArray[1] + ("C3 SECONDTEXT " + "ambiguous y 5-5 rule: earlier: dk(B" + amb_5_5[0].dk_prev + ") + [" + amb_5_5[0].modifier_deadkey + " " + amb_5_5[0].deadkey + "] > dk(B" + amb_5_5[0].dk_C2 + ") here: ") + warningTextArray[1] = warningTextArray[1] + ("C3 SECONDTEXT " + "ambiguous y 5-5 rule: earlier: dk(B" + amb_5_5[0].id_prev_deadkey + ") + [" + amb_5_5[0].modifier_deadkey + " " + amb_5_5[0].deadkey + "] > dk(B" + amb_5_5[0].id_deadkey + ") here: ") } if (dup_5_5.length > 0) { - warningTextArray[1] = warningTextArray[1] + ("C3 SECONDTEXT " + "duplicate y 5-5 rule: earlier: dk(B" + dup_5_5[0].dk_prev + ") + [" + dup_5_5[0].modifier_deadkey + " " + dup_5_5[0].deadkey + "] > dk(B" + dup_5_5[0].dk_C2 + ") here: ") + warningTextArray[1] = warningTextArray[1] + ("C3 SECONDTEXT " + "duplicate y 5-5 rule: earlier: dk(B" + dup_5_5[0].id_prev_deadkey + ") + [" + dup_5_5[0].modifier_deadkey + " " + dup_5_5[0].deadkey + "] > dk(B" + dup_5_5[0].id_deadkey + ") here: ") } if (amb_6_6.length > 0) { - warningTextArray[2] = warningTextArray[2] + ("C3 THIRDTEXT " + "ambiguous y 6-6 rule: earlier: dk(B" + amb_6_6[0].dk_C2 + ") + [" + amb_6_6[0].modifier_key + " " + amb_6_6[0].key + "] > \'" + new TextDecoder().decode(amb_6_6[0].output) + "\' here: ") + warningTextArray[2] = warningTextArray[2] + ("C3 THIRDTEXT " + "ambiguous y 6-6 rule: earlier: dk(B" + amb_6_6[0].id_deadkey + ") + [" + amb_6_6[0].modifier_key + " " + amb_6_6[0].key + "] > \'" + new TextDecoder().decode(amb_6_6[0].output) + "\' here: ") } if (dup_6_6.length > 0) { - warningTextArray[2] = warningTextArray[2] + ("C3 THIRDTEXT " + "duplicate y 6-6x rule: earlier: dk(B" + dup_6_6[0].dk_C2 + ") + [" + dup_6_6[0].modifier_key + " " + dup_6_6[0].key + "] > \'" + new TextDecoder().decode(dup_6_6[0].output) + "\' here: ") + warningTextArray[2] = warningTextArray[2] + ("C3 THIRDTEXT " + "duplicate y 6-6x rule: earlier: dk(B" + dup_6_6[0].id_deadkey + ") + [" + dup_6_6[0].modifier_key + " " + dup_6_6[0].key + "] > \'" + new TextDecoder().decode(dup_6_6[0].output) + "\' here: ") } } @@ -1307,11 +1328,10 @@ export class KeylayoutToKmnConverter { } /** - * @brief member function to map Ukelele keycodes to a Windows Keycodes + * @brief member function to map Ukelele keycodes to Windows Keycodes * @param pos Ukelele (=mac) keycodes - * @return keycode on Win Keyboard + * @return keycode on a Windows Keyboard */ - // TODO finish all entries public map_UkeleleKC_To_VK(pos: number): string { // ukelele KC --> // VK_US @@ -1383,31 +1403,31 @@ export class KeylayoutToKmnConverter { let keymarker: string = "" // create array of all rules and remove duplicates - /* const data_rules: rule_object[] = data_ukelele.arrayOf_Rules.filter((curr) => { - if ((curr.output !== new TextEncoder().encode("") || curr.output !== undefined) - && (curr.rule_type === "C0") || (curr.rule_type === "C1") || (curr.rule_type === "C2") || (curr.rule_type === "C3")) { - return curr; - } - else return "" - }); - const unique_data_Rules: rule_object[] = data_rules.reduce((unique, o) => { - if (!unique.some((obj: { output: Uint8Array; rule_type: string; modifier_key: string; modifier_deadkey: string; prev_deadkey: string; modifier_prev_deadkey: string; deadkey: string; key: string }) => - new TextDecoder().decode(obj.output) === new TextDecoder().decode(o.output) - - && obj.rule_type === o.rule_type - && obj.modifier_key === o.modifier_key - && obj.key === o.key - - && obj.modifier_deadkey === o.modifier_deadkey - && obj.deadkey === o.deadkey - - && obj.modifier_prev_deadkey === o.modifier_prev_deadkey - && obj.prev_deadkey === o.prev_deadkey) - ) { - unique.push(o); - } - return unique; - }, []);*/ + /*const data_rules: rule_object[] = data_ukelele.arrayOf_Rules.filter((curr) => { + if ((curr.output !== new TextEncoder().encode("") || curr.output !== undefined) + && (curr.rule_type === "C0") || (curr.rule_type === "C1") || (curr.rule_type === "C2") || (curr.rule_type === "C3")) { + return curr; + } + else return "" + }); + const unique_data_Rules: rule_object[] = data_rules.reduce((unique, o) => { + if (!unique.some((obj: { output: Uint8Array; rule_type: string; modifier_key: string; modifier_deadkey: string; prev_deadkey: string; modifier_prev_deadkey: string; deadkey: string; key: string }) => + new TextDecoder().decode(obj.output) === new TextDecoder().decode(o.output) + + && obj.rule_type === o.rule_type + && obj.modifier_key === o.modifier_key + && obj.key === o.key + + && obj.modifier_deadkey === o.modifier_deadkey + && obj.deadkey === o.deadkey + + && obj.modifier_prev_deadkey === o.modifier_prev_deadkey + && obj.prev_deadkey === o.prev_deadkey) + ) { + unique.push(o); + } + return unique; + }, []);*/ // ToDo remove const unique_data_Rules: rule_object[] = data_ukelele.arrayOf_Rules @@ -1428,13 +1448,15 @@ export class KeylayoutToKmnConverter { for (let j = 0; j < KeylayoutToKmnConverter.USED_KEYS_COUNT; j++) { if (this.map_UkeleleKC_To_VK(j) === unique_data_Rules[k].key) { keyNr = j - break + //break } } // skip keyNr 48 ( TAB ) if (keyNr === 48) - continue + console.log(" keyNr", keyNr) + + //continue // add a line after rules of each key if (unique_data_Rules[k].key !== keymarker) @@ -1468,13 +1490,13 @@ export class KeylayoutToKmnConverter { //SECONDTEXT print // ToDo include condition again // if ((warn_text[1].indexOf("duplicate") < 0)) { - data += warn_text[1] + "+ [" + unique_data_Rules[k].modifier_deadkey + " " + unique_data_Rules[k].deadkey + "] > dk(C" + String(unique_data_Rules[k].dk_C2) + ")\n" + data += warn_text[1] + "+ [" + unique_data_Rules[k].modifier_deadkey + " " + unique_data_Rules[k].deadkey + "] > dk(C" + String(unique_data_Rules[k].id_deadkey) + ")\n" // } // THIRDTEXT print OK // ToDo include condition again // if ((warn_text[2].indexOf("duplicate") < 0)) { - data += warn_text[2] + "dk(C" + String(unique_data_Rules[k].dk_C2) + ") + [" + unique_data_Rules[k].modifier_key + " " + unique_data_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_data_Rules[k].output) + "\'\n" + data += warn_text[2] + "dk(C" + String(unique_data_Rules[k].id_deadkey) + ") + [" + unique_data_Rules[k].modifier_key + " " + unique_data_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_data_Rules[k].output) + "\'\n" data += "\n" // } } @@ -1494,22 +1516,25 @@ export class KeylayoutToKmnConverter { // ToDo include condition again // FIRSTTEXT print // if ((warn_text[0].indexOf("duplicate") < 0)) { - data += warn_text[0] + " [" + unique_data_Rules[k].modifier_prev_deadkey + " " + unique_data_Rules[k].prev_deadkey + "] > dk(A" + String(unique_data_Rules[k].dk_prev) + ")\n" + data += warn_text[0] + " [" + unique_data_Rules[k].modifier_prev_deadkey + " " + unique_data_Rules[k].prev_deadkey + "] > dk(A" + String(unique_data_Rules[k].id_prev_deadkey) + ")\n" // } // ToDo include condition again //SECONDTEXT print // if ((warn_text[1].indexOf("duplicate") < 0)) { - data += warn_text[1] + "dk(A" + String(unique_data_Rules[k].dk_prev) + ") + [" + unique_data_Rules[k].modifier_deadkey + " " + unique_data_Rules[k].deadkey + "] > dk(B" + String(unique_data_Rules[k].dk_C2) + ")\n" + data += warn_text[1] + "dk(A" + String(unique_data_Rules[k].id_prev_deadkey) + ") + [" + unique_data_Rules[k].modifier_deadkey + " " + unique_data_Rules[k].deadkey + "] > dk(B" + String(unique_data_Rules[k].id_deadkey) + ")\n" // } // ToDo include condition again // THIRDTEXT print OK // if ((warn_text[2].indexOf("duplicate") < 0)) { - data += warn_text[2] + "dk(B" + String(unique_data_Rules[k].dk_C2) + ") + [" + unique_data_Rules[k].modifier_key + " " + unique_data_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_data_Rules[k].output) + "\'\n" + data += warn_text[2] + "dk(B" + String(unique_data_Rules[k].id_deadkey) + ") + [" + unique_data_Rules[k].modifier_key + " " + unique_data_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_data_Rules[k].output) + "\'\n" // } + // if ((warn_text[0].indexOf("duplicate") < 0) || (warn_text[1].indexOf("duplicate") < 0) || (warn_text[2].indexOf("duplicate") < 0)) { data += "\n" + // } + } } @@ -1548,28 +1573,19 @@ export class KeylayoutToKmnConverter { console.log("dataRules ", i, dataRules[i].rule_type !== "" ? dataRules[i].rule_type : "--".padEnd(4, " ") + , /*dataRules.length, i,*/ "| ", (dataRules[i].modifier_prev_deadkey !== "" ? dataRules[i].modifier_prev_deadkey.padEnd(33, " ") : "--".padEnd(33, " ")), (dataRules[i].prev_deadkey !== "" ? dataRules[i].prev_deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), - (dataRules[i].dk_prev !== 0 ? ("dk(A" + String(dataRules[i].dk_prev) + ")").padEnd(11, " ") : "--".padEnd(11, " ")), - (dataRules[i].uniqueA !== 0 ? ("unique(A" + String(dataRules[i].uniqueA) + ")").padEnd(11, " ") : "--".padEnd(11, " ")), - - /* (("dk(A-B-C " + String(dataRules[i].dk_prev) + "-" + String(dataRules[i].dk)).padEnd(9, "-") + (String(dataRules[i].dk_C2) + ")").padEnd(9, " ")), - ("unique(AB " + String(dataRules[i].uniqueA) + "-" + String(dataRules[i].uniqueB) + ")"),*/ - + (dataRules[i].id_prev_deadkey !== 0 ? ("dk(A" + String(dataRules[i].id_prev_deadkey) + ")").padEnd(11, " ") : "--".padEnd(11, " ")), + (dataRules[i].unique_prev_deadkey !== 0 ? ("unique(A" + String(dataRules[i].unique_prev_deadkey) + ")").padEnd(11, " ") : "--".padEnd(11, " ")), (dataRules[i].modifier_deadkey !== "" ? dataRules[i].modifier_deadkey.padEnd(30, " ") : "--".padEnd(30, " ")), (dataRules[i].deadkey !== "" ? dataRules[i].deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), - dataRules[i].rule_type === "C2" ? (dataRules[i].dk !== 0 ? ("dk(C" + String(dataRules[i].dk) + ")").padEnd(9, " ") : "--".padEnd(9, " ")) : ((dataRules[i].dk !== 0 ? ("dk(B" + String(dataRules[i].dk) + ")").padEnd(9, " ") : "--".padEnd(9, " "))), - dataRules[i].rule_type === "C2" ? (dataRules[i].uniqueB !== 0 ? ("unique(C" + String(dataRules[i].uniqueB) + ")").padEnd(9, " ") : "--".padEnd(9, " ")) : ((dataRules[i].uniqueA !== 0 ? ("unique(B" + String(dataRules[i].dk) + ")").padEnd(9, " ") : "--".padEnd(9, " "))), - dataRules[i].dk, - dataRules[i].dk_C2, - dataRules[i].dk_prev, - - // dataRules[i].rule_type === "C2" ? (dataRules[i].dk !== 0 ? ("dk(C" + String(dataRules[i].dk) + ")").padEnd(9, " ") : "--".padEnd(9, " ")) : ((dataRules[i].dk !== 0 ? ("dk(B" + String(dataRules[i].dk) + ")").padEnd(9, " ") : "--".padEnd(9, " "))), - // dataRules[i].rule_type === "C2" ? (dataRules[i].uniqueB !== 0 ? ("unique(C" + String(dataRules[i].uniqueB) + ")").padEnd(9, " ") : "--".padEnd(9, " ")) : ((dataRules[i].uniqueA !== 0 ? ("unique(B" + String(dataRules[i].dk) + ")").padEnd(9, " ") : "--".padEnd(9, " "))), - + dataRules[i].rule_type === "C2" ? (dataRules[i].unique_deadkey !== 0 ? ("unique(C" + String(dataRules[i].unique_deadkey) + ")").padEnd(9, " ") : "--".padEnd(9, " ")) : ((dataRules[i].unique_prev_deadkey !== 0 ? ("unique(B" + ")").padEnd(9, " ") : "--".padEnd(9, " "))), + dataRules[i].id_deadkey, + dataRules[i].id_prev_deadkey, "| ", (dataRules[i].modifier_key !== "" ? dataRules[i].modifier_key.padEnd(40, " ") : "--".padEnd(40, " ")), (dataRules[i].key !== "" ? dataRules[i].key.padEnd(8, " ") : "--".padEnd(8, " ")), @@ -1588,17 +1604,16 @@ export class KeylayoutToKmnConverter { "| ", (dataRules.modifier_prev_deadkey !== "" ? dataRules.modifier_prev_deadkey.padEnd(33, " ") : "--".padEnd(33, " ")), (dataRules.prev_deadkey !== "" ? dataRules.prev_deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), - (dataRules.dk_prev !== 0 ? ("dk(A" + String(dataRules.dk_prev) + ")").padEnd(11, " ") : "--".padEnd(11, " ")), - (dataRules.uniqueA !== 0 ? ("unique(A" + String(dataRules.uniqueA) + ")").padEnd(11, " ") : "--".padEnd(11, " ")), + (dataRules.id_prev_deadkey !== 0 ? ("dk(A" + String(dataRules.id_prev_deadkey) + ")").padEnd(11, " ") : "--".padEnd(11, " ")), + (dataRules.unique_prev_deadkey !== 0 ? ("unique(A" + String(dataRules.unique_prev_deadkey) + ")").padEnd(11, " ") : "--".padEnd(11, " ")), (dataRules.modifier_deadkey !== "" ? dataRules.modifier_deadkey.padEnd(30, " ") : "--".padEnd(30, " ")), (dataRules.deadkey !== "" ? dataRules.deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), - dataRules.rule_type === "C2" ? (dataRules.dk !== 0 ? ("dk(C" + String(dataRules.dk) + ")").padEnd(9, " ") : "--".padEnd(9, " ")) : ((dataRules.dk !== 0 ? ("dk(B" + String(dataRules.dk) + ")").padEnd(9, " ") : "--".padEnd(9, " "))), - dataRules.rule_type === "C2" ? (dataRules.uniqueB !== 0 ? ("unique(C" + String(dataRules.uniqueB) + ")").padEnd(9, " ") : "--".padEnd(9, " ")) : ((dataRules.uniqueA !== 0 ? ("unique(B" + String(dataRules.dk) + ")").padEnd(9, " ") : "--".padEnd(9, " "))), - dataRules.dk, - dataRules.dk_C2, - dataRules.dk_prev, + dataRules.rule_type === "C2" ? (dataRules.unique_deadkey !== 0 ? ("unique(C" + String(dataRules.unique_deadkey) + ")").padEnd(9, " ") : "--".padEnd(9, " ")) : ((dataRules.unique_prev_deadkey !== 0 ? ("unique(B" + ")").padEnd(9, " ") : "--".padEnd(9, " "))), + + dataRules.id_deadkey, + dataRules.id_prev_deadkey, "| ", (dataRules.modifier_key !== "" ? dataRules.modifier_key.padEnd(40, " ") : "--".padEnd(40, " ")), (dataRules.key !== "" ? dataRules.key.padEnd(8, " ") : "--".padEnd(8, " ")), @@ -1615,14 +1630,13 @@ class Rules { public modifier_prev_deadkey: string, /* first key used by C3 rules*/ public prev_deadkey: string, - public dk_prev: number, - public uniqueA: number, + public id_prev_deadkey: number, + public unique_prev_deadkey: number, public modifier_deadkey: string, /* second key used by C2,C3 rules*/ public deadkey: string, - public dk: number, - public dk_C2: number, - public uniqueB: number, + public id_deadkey: number, + public unique_deadkey: number, public modifier_key: string, /* third key used by C0,C1,C2,C3,C4 rules*/ public key: string, From f7a0ac84f90ef2a1d83953a05695a0e902b2e2bf Mon Sep 17 00:00:00 2001 From: Sabine Date: Fri, 21 Feb 2025 16:28:38 +0100 Subject: [PATCH 056/251] feat(developer): change trimValues to false to allow space to be output --- .../keylayout-to-kmn-converter.ts | 327 +++++++----------- 1 file changed, 132 insertions(+), 195 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index c19fe720929..dcc6582b5ea 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -77,6 +77,7 @@ import { ConverterToKmnArtifacts } from "../converter-artifacts.js"; // read TODO which stores? // does order of modifier matter ? // NO OUTPUT FOR SPACE in C0C1 !!! +// remove all markers c0, 1-1, #### C2 ###, ... import { XMLParser } from 'fast-xml-parser'; // for reading an xml file @@ -189,6 +190,7 @@ export class KeylayoutToKmnConverter { const options = { ignoreAttributes: false, + trimValues: false, // preserve spaces attributeNamePrefix: '@_' // to access the attribute }; @@ -202,12 +204,6 @@ export class KeylayoutToKmnConverter { // Todo how to break correctly; return what?? console.log(" FILE NOT FOUND") } - console.log("jsonobj ",jsonObj.keyboard.actions.action[0] ) - console.log("tttttt ", ) - - - - return jsonObj } @@ -298,15 +294,14 @@ export class KeylayoutToKmnConverter { // ...............e. g. ............................................................................... // ............................................................................................................................... - if ((jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] !== undefined)) { + if ((jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] !== undefined) + && (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] !== "")) { - if (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] !== "") { - - // loop behaviours - for (let l = 0; l < data_ukelele.arrayOf_Modifiers[i].length; l++) { - if (this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']))) { + // loop behaviours + for (let l = 0; l < data_ukelele.arrayOf_Modifiers[i].length; l++) { + if (this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']))) { - rule_obj = new Rules( + rule_obj = new Rules( /* rule_type */ "C0", /* modifier_prev_deadkey*/ "", @@ -322,19 +317,16 @@ export class KeylayoutToKmnConverter { /* modifier_key*/ this.create_kmn_modifier(data_ukelele.arrayOf_Modifiers[i][l], isCapsused), /* key */ this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), /* output */ new TextEncoder().encode(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output']), - ) - if (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] !== "") - object_array.push(rule_obj) - } + ) + if (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] !== "") + object_array.push(rule_obj) } } + } else if (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] !== undefined) { - action_id = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] - console.log("i j ", i, j) - console.log("action_id ", action_id) // ............................................................................................................................... // case C1: action + state none + output ......................................................................................... // C1 see: https://docs.google.com/document/d/12J3NGO6RxIthCpZDTR8FYSRjiMgXJDLwPY2z9xqKzJ0/edit?tab=t.0#heading=h.g7jwx3lx0ydd ... @@ -342,31 +334,15 @@ export class KeylayoutToKmnConverter { // KeyMap:code->KeyMap:action->action:action_state(none)->action_output .......................................................... // ...............e. g. 0) returnarray2D.push(returnarray) @@ -780,39 +753,15 @@ export class KeylayoutToKmnConverter { public get_Action2ID_NoneOutput__From__ActionID_Id(data: any, search: string): string { let OutputValue: string = "" - if (search === "a0") - console.log("search ", search) - for (let i = 0; i < data.keyboard.actions.action.length; i++) { if (data.keyboard.actions.action[i]['@_id'] === search) { - - - for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { - - /* console.log("data.keyboard.actions.action.length ", - i, j, - data.keyboard.actions.action.length, - data.keyboard.actions.action[i]['@_id'], - search, - data.keyboard.actions.action[i].when.length, - data.keyboard.actions.action[i].when[j]['@_output'], - OutputValue - )*/ if (data.keyboard.actions.action[i].when[j]['@_state'] === "none") { OutputValue = data.keyboard.actions.action[i].when[j]['@_output'] - // console.log("OutputValue ", OutputValue) - } } } } - if (search === "a19") - console.log(" OutputValue a19", OutputValue, "..") - if (search === "a0") - console.log(" OutputValue a0", OutputValue, "..") - - return OutputValue } /* @@ -1022,7 +971,7 @@ export class KeylayoutToKmnConverter { return iskKeymanModifier } - // definition of comparisons 1-1, 2-4, 6-6, ... see https://docs.google.com/document/d/12J3NGO6RxIthCpZDTR8FYSRjiMgXJDLwPY2z9xqKzJ0/edit?tab=t.0 + // definition of comparisons 1-1, 2-4, 6-6,... see https://docs.google.com/document/d/12J3NGO6RxIthCpZDTR8FYSRjiMgXJDLwPY2z9xqKzJ0/edit?tab=t.0#heading=h.pcz8rjyrl5ug // todo remove comments n filters after check of several keylayout files public reviewRules(rule: rule_object[], index: number): string[] { @@ -1032,33 +981,27 @@ export class KeylayoutToKmnConverter { // Todo remoce C1-C3's and other markers if ((rule[index].rule_type === "C0") || (rule[index].rule_type === "C1")) { - if (!this.isAcceptableKeymanModifier(rule[index].modifier_key)) { warningTextArray[2] = "C1 unavailable modifier in: " } } - if (rule[index].rule_type === "C2") { - if - (!this.isAcceptableKeymanModifier(rule[index].modifier_deadkey)) { + else if (rule[index].rule_type === "C2") { + if (!this.isAcceptableKeymanModifier(rule[index].modifier_deadkey)) { warningTextArray[1] = "C2 unavailable modifier in: " } - if (!this.isAcceptableKeymanModifier(rule[index].modifier_key)) { warningTextArray[2] = "C2 unavailable modifier in: " } } - if (rule[index].rule_type === "C3") { - + else if (rule[index].rule_type === "C3") { if (!this.isAcceptableKeymanModifier(rule[index].modifier_prev_deadkey)) { warningTextArray[2] = "C3 unavailable modifier in: " } - if (!this.isAcceptableKeymanModifier(rule[index].modifier_deadkey)) { warningTextArray[1] = "C3 unavailable modifier in: " } - if (!this.isAcceptableKeymanModifier(rule[index].modifier_key)) { warningTextArray[0] = "C3 unavailable modifier in: " } @@ -1162,10 +1105,10 @@ export class KeylayoutToKmnConverter { warningTextArray[1] = warningTextArray[1] + ("C2 SECONDTEXT " + "duplicate 2-2 rule: earlier: [" + dup_2_2[0].modifier_deadkey + " " + dup_2_2[0].deadkey + "] > dk(C" + dup_2_2[0].id_deadkey + ") here: ") } if (amb_3_3.length > 0) { - warningTextArray[2] = warningTextArray[2] + ("C2 THIRDTEXT " + "ambiguous y 3-3 rule: earlier: dk(C" + amb_3_3[0].id_deadkey + ") + [" + amb_3_3[0].modifier_key + " " + amb_3_3[0].key + "] > \'" + new TextDecoder().decode(amb_3_3[0].output) + "\' here: ") + warningTextArray[2] = warningTextArray[2] + ("C2 THIRDTEXT " + "ambiguous 3-3 rule: earlier: dk(C" + amb_3_3[0].id_deadkey + ") + [" + amb_3_3[0].modifier_key + " " + amb_3_3[0].key + "] > \'" + new TextDecoder().decode(amb_3_3[0].output) + "\' here: ") } if (dup_3_3.length > 0) { - warningTextArray[2] = warningTextArray[2] + ("C2 THIRDTEXT " + "duplicate y 3-3 rule: earlier: dk(C" + dup_3_3[0].id_deadkey + ") + [" + dup_3_3[0].modifier_key + " " + dup_3_3[0].key + "] > \'" + new TextDecoder().decode(dup_3_3[0].output) + "\' here: ") + warningTextArray[2] = warningTextArray[2] + ("C2 THIRDTEXT " + "duplicate 3-3 rule: earlier: dk(C" + dup_3_3[0].id_deadkey + ") + [" + dup_3_3[0].modifier_key + " " + dup_3_3[0].key + "] > \'" + new TextDecoder().decode(dup_3_3[0].output) + "\' here: ") } if (amb_1_2.length > 0) { warningTextArray[1] = warningTextArray[1] + ("C2 SECONDTEXT " + "ambiguous 1-2 rule: earlier: [" + amb_1_2[0].modifier_key + " " + amb_1_2[0].key + "] > \'" + new TextDecoder().decode(amb_1_2[0].output) + "\' here: ") @@ -1288,11 +1231,11 @@ export class KeylayoutToKmnConverter { } if (amb_6_3.length > 0) { - warningTextArray[1] = warningTextArray[1] + ("C3 SECONDTEXT " + "ambiguous y 6-3 rule: earlier: dk(C" + amb_6_3[0].id_deadkey + ") + [" + amb_6_3[0].modifier_key + " " + amb_6_3[0].key + "] > \'" + new TextDecoder().decode(amb_6_3[0].output) + "\' here: ") + warningTextArray[1] = warningTextArray[1] + ("C3 SECONDTEXT " + "ambiguous 6-3 rule: earlier: dk(C" + amb_6_3[0].id_deadkey + ") + [" + amb_6_3[0].modifier_key + " " + amb_6_3[0].key + "] > \'" + new TextDecoder().decode(amb_6_3[0].output) + "\' here: ") } if (dup_6_3.length > 0) { - warningTextArray[1] = warningTextArray[1] + ("C3 SECONDTEXT " + "duplicate y 6-3 rule: earlier: dk(C" + dup_6_3[0].id_deadkey + ") + [" + dup_6_3[0].modifier_key + " " + dup_6_3[0].key + "] > \'" + new TextDecoder().decode(dup_6_3[0].output) + "\' here: ") + warningTextArray[1] = warningTextArray[1] + ("C3 SECONDTEXT " + "duplicate 6-3 rule: earlier: dk(C" + dup_6_3[0].id_deadkey + ") + [" + dup_6_3[0].modifier_key + " " + dup_6_3[0].key + "] > \'" + new TextDecoder().decode(dup_6_3[0].output) + "\' here: ") } if (amb_4_4_mid.length > 0) { @@ -1304,19 +1247,19 @@ export class KeylayoutToKmnConverter { } if (amb_5_5.length > 0) { - warningTextArray[1] = warningTextArray[1] + ("C3 SECONDTEXT " + "ambiguous y 5-5 rule: earlier: dk(B" + amb_5_5[0].id_prev_deadkey + ") + [" + amb_5_5[0].modifier_deadkey + " " + amb_5_5[0].deadkey + "] > dk(B" + amb_5_5[0].id_deadkey + ") here: ") + warningTextArray[1] = warningTextArray[1] + ("C3 SECONDTEXT " + "ambiguous 5-5 rule: earlier: dk(B" + amb_5_5[0].id_prev_deadkey + ") + [" + amb_5_5[0].modifier_deadkey + " " + amb_5_5[0].deadkey + "] > dk(B" + amb_5_5[0].id_deadkey + ") here: ") } if (dup_5_5.length > 0) { - warningTextArray[1] = warningTextArray[1] + ("C3 SECONDTEXT " + "duplicate y 5-5 rule: earlier: dk(B" + dup_5_5[0].id_prev_deadkey + ") + [" + dup_5_5[0].modifier_deadkey + " " + dup_5_5[0].deadkey + "] > dk(B" + dup_5_5[0].id_deadkey + ") here: ") + warningTextArray[1] = warningTextArray[1] + ("C3 SECONDTEXT " + "duplicate 5-5 rule: earlier: dk(B" + dup_5_5[0].id_prev_deadkey + ") + [" + dup_5_5[0].modifier_deadkey + " " + dup_5_5[0].deadkey + "] > dk(B" + dup_5_5[0].id_deadkey + ") here: ") } if (amb_6_6.length > 0) { - warningTextArray[2] = warningTextArray[2] + ("C3 THIRDTEXT " + "ambiguous y 6-6 rule: earlier: dk(B" + amb_6_6[0].id_deadkey + ") + [" + amb_6_6[0].modifier_key + " " + amb_6_6[0].key + "] > \'" + new TextDecoder().decode(amb_6_6[0].output) + "\' here: ") + warningTextArray[2] = warningTextArray[2] + ("C3 THIRDTEXT " + "ambiguous 6-6 rule: earlier: dk(B" + amb_6_6[0].id_deadkey + ") + [" + amb_6_6[0].modifier_key + " " + amb_6_6[0].key + "] > \'" + new TextDecoder().decode(amb_6_6[0].output) + "\' here: ") } if (dup_6_6.length > 0) { - warningTextArray[2] = warningTextArray[2] + ("C3 THIRDTEXT " + "duplicate y 6-6x rule: earlier: dk(B" + dup_6_6[0].id_deadkey + ") + [" + dup_6_6[0].modifier_key + " " + dup_6_6[0].key + "] > \'" + new TextDecoder().decode(dup_6_6[0].output) + "\' here: ") + warningTextArray[2] = warningTextArray[2] + ("C3 THIRDTEXT " + "duplicate 6-6x rule: earlier: dk(B" + dup_6_6[0].id_deadkey + ") + [" + dup_6_6[0].modifier_key + " " + dup_6_6[0].key + "] > \'" + new TextDecoder().decode(dup_6_6[0].output) + "\' here: ") } } @@ -1336,61 +1279,60 @@ export class KeylayoutToKmnConverter { // ukelele KC --> // VK_US if (pos === 0x0A) return "K_BKQUOTE" /* ^ */ - if (pos === 0x12) return "K_1" /* 1 */ - if (pos === 0x13) return "K_2" /* 2 */ - if (pos === 0x14) return "K_3" /* 3 */ - if (pos === 0x15) return "K_4" /* 4 */ - if (pos === 0x17) return "K_5" /* 5 */ - if (pos === 0x16) return "K_6" /* 6 */ - if (pos === 0x1A) return "K_7" /* 7 */ - if (pos === 0x1C) return "K_8" /* 8 */ - if (pos === 0x19) return "K_9" /* 9 */ - if (pos === 0x1D) return "K_0" /* 0 */ - if (pos === 0x1B) return "K_HYPHEN" /* ß */ - if (pos === 0x18) return "K_EQUAL" /* ´ */ - - if (pos === 0x0C) return "K_Q" /* Q */ - if (pos === 0x0D) return "K_W" /* W */ - if (pos === 0x0E) return "K_E" /* E */ - if (pos === 0x0F) return "K_R" /* R */ - if (pos === 0x11) return "K_T" /* T */ - if (pos === 0x10) return "K_Y" /* Y */ - if (pos === 0x20) return "K_U" /* U */ - if (pos === 0x22) return "K_I" /* I */ - if (pos === 0x1F) return "K_O" /* O */ - if (pos === 0x23) return "K_P" /* P */ - if (pos === 0x21) return "K_LBRKT" /* [ */ - if (pos === 0x1E) return "K_RBRKT" /* ] */ - if (pos === 0x31) return "K_SPACE" /* \ */ - if (pos === 0x2A) return "K_BKSLASH" /* \ */ // 42 for ISO correct?? - // if (pos === 0x30) return "K_?C1" /* \ */ // 48 for ANSI correct?? - // TODO numbers OK?? - - if (pos === 0x00) return "K_A" /* A */ - if (pos === 0x01) return "K_S" /* S */ - if (pos === 0x02) return "K_D" /* D */ - if (pos === 0x03) return "K_F" /* F */ - if (pos === 0x05) return "K_G" /* G */ - if (pos === 0x04) return "K_H" /* H */ - if (pos === 0x26) return "K_J" /* J */ - if (pos === 0x28) return "K_K" /* K */ - if (pos === 0x25) return "K_L" /* L */ - if (pos === 0x29) return "K_COLON" /* : */ - if (pos === 0x27) return "K_QUOTE" /* " */ - - if (pos === 0x23) return "K_oE2" /* | */ - if (pos === 0x06) return "K_Z" /* Z */ - if (pos === 0x07) return "K_X" /* X */ - if (pos === 0x08) return "K_C" /* C */ - if (pos === 0x09) return "K_V" /* V */ - if (pos === 0x0B) return "K_B" /* B */ - if (pos === 0x2D) return "K_N" /* N */ - if (pos === 0x2E) return "K_M" /* M */ - if (pos === 0x2B) return "K_COMMA" /* , */ - if (pos === 0x2F) return "K_PERIOD" /* . */ - if (pos === 0x2C) return "K_SLASH" /* / */ - - if (pos === 0x24) return "K_ENTER" + else if (pos === 0x12) return "K_1" /* 1 */ + else if (pos === 0x13) return "K_2" /* 2 */ + else if (pos === 0x14) return "K_3" /* 3 */ + else if (pos === 0x15) return "K_4" /* 4 */ + else if (pos === 0x17) return "K_5" /* 5 */ + else if (pos === 0x16) return "K_6" /* 6 */ + else if (pos === 0x1A) return "K_7" /* 7 */ + else if (pos === 0x1C) return "K_8" /* 8 */ + else if (pos === 0x19) return "K_9" /* 9 */ + else if (pos === 0x1D) return "K_0" /* 0 */ + else if (pos === 0x1B) return "K_HYPHEN" /* ß */ + else if (pos === 0x18) return "K_EQUAL" /* ´ */ + + else if (pos === 0x0C) return "K_Q" /* Q */ + else if (pos === 0x0D) return "K_W" /* W */ + else if (pos === 0x0E) return "K_E" /* E */ + else if (pos === 0x0F) return "K_R" /* R */ + else if (pos === 0x11) return "K_T" /* T */ + else if (pos === 0x10) return "K_Y" /* Y */ + else if (pos === 0x20) return "K_U" /* U */ + else if (pos === 0x22) return "K_I" /* I */ + else if (pos === 0x1F) return "K_O" /* O */ + else if (pos === 0x23) return "K_P" /* P */ + else if (pos === 0x21) return "K_LBRKT" /* [ */ + else if (pos === 0x1E) return "K_RBRKT" /* ] */ + else if (pos === 0x31) return "K_SPACE" /* \ */ + else if (pos === 0x2A) return "K_BKSLASH" /* \ */ // 42 for ISO correct?? + // else if (pos === 0x30) return "K_?C1" /* \ */ // 48 for ANSI correct?? + + else if (pos === 0x00) return "K_A" /* A */ + else if (pos === 0x01) return "K_S" /* S */ + else if (pos === 0x02) return "K_D" /* D */ + else if (pos === 0x03) return "K_F" /* F */ + else if (pos === 0x05) return "K_G" /* G */ + else if (pos === 0x04) return "K_H" /* H */ + else if (pos === 0x26) return "K_J" /* J */ + else if (pos === 0x28) return "K_K" /* K */ + else if (pos === 0x25) return "K_L" /* L */ + else if (pos === 0x29) return "K_COLON" /* : */ + else if (pos === 0x27) return "K_QUOTE" /* " */ + + else if (pos === 0x23) return "K_oE2" /* | */ + else if (pos === 0x06) return "K_Z" /* Z */ + else if (pos === 0x07) return "K_X" /* X */ + else if (pos === 0x08) return "K_C" /* C */ + else if (pos === 0x09) return "K_V" /* V */ + else if (pos === 0x0B) return "K_B" /* B */ + else if (pos === 0x2D) return "K_N" /* N */ + else if (pos === 0x2E) return "K_M" /* M */ + else if (pos === 0x2B) return "K_COMMA" /* , */ + else if (pos === 0x2F) return "K_PERIOD" /* . */ + else if (pos === 0x2C) return "K_SLASH" /* / */ + + else if (pos === 0x24) return "K_ENTER" else return "" } //---------------------------------------------------------------------------------------------------- @@ -1400,10 +1342,9 @@ export class KeylayoutToKmnConverter { public createData_Rules(data_ukelele: convert_object): string { let data: string = "" - let keymarker: string = "" // create array of all rules and remove duplicates - /*const data_rules: rule_object[] = data_ukelele.arrayOf_Rules.filter((curr) => { + const data_rules: rule_object[] = data_ukelele.arrayOf_Rules.filter((curr) => { if ((curr.output !== new TextEncoder().encode("") || curr.output !== undefined) && (curr.rule_type === "C0") || (curr.rule_type === "C1") || (curr.rule_type === "C2") || (curr.rule_type === "C3")) { return curr; @@ -1427,10 +1368,10 @@ export class KeylayoutToKmnConverter { unique.push(o); } return unique; - }, []);*/ + }, []); // ToDo remove - const unique_data_Rules: rule_object[] = data_ukelele.arrayOf_Rules + //const unique_data_Rules: rule_object[] = data_ukelele.arrayOf_Rules console.log("xx data_ukelele.arrayOf_Rules", data_ukelele.arrayOf_Rules.length) //console.log("xx data_ukelele.arrayOf_Rules", this.writeDataset(data_ukelele.arrayOf_Rules)) console.log("xx unique_data_Rules", unique_data_Rules.length) @@ -1442,39 +1383,39 @@ export class KeylayoutToKmnConverter { for (let k = 0; k < unique_data_Rules.length; k++) { - if ((unique_data_Rules[k].rule_type === "C0") || (unique_data_Rules[k].rule_type === "C1")) { - // lookup key nr of the key that is being processed - let keyNr: number = 0; - for (let j = 0; j < KeylayoutToKmnConverter.USED_KEYS_COUNT; j++) { - if (this.map_UkeleleKC_To_VK(j) === unique_data_Rules[k].key) { - keyNr = j - //break - } + if ((unique_data_Rules[k].rule_type === "C0")||(unique_data_Rules[k].rule_type === "C1")) { + + // lookup key nr of the key that is being processed + let keyNr: number = 0; + for (let j = 0; j < KeylayoutToKmnConverter.USED_KEYS_COUNT; j++) { + if (this.map_UkeleleKC_To_VK(j) === unique_data_Rules[k].key) { + keyNr = j + break } + } - // skip keyNr 48 ( TAB ) - if (keyNr === 48) - console.log(" keyNr", keyNr) + // skip keyNr 48 (K_TAB) and 36 (K_ENTER) + if ((keyNr === 48) || (keyNr === 36)) + continue - //continue + //--------------------------------------------------------------------------------------------- - // add a line after rules of each key - if (unique_data_Rules[k].key !== keymarker) - data += '\n' + // add a line after rules of each key + if ((k > 1) && (unique_data_Rules[k - 1].key !== unique_data_Rules[k].key) && (unique_data_Rules[k - 1].rule_type === unique_data_Rules[k].rule_type)) { + data += '\n' + } - //--------------------------------------------------------------------------------------------- + const warn_text = this.reviewRules(unique_data_Rules, k) - // add a warning in front of rules that use unavailable modifiers or ambiguous rules - const warn_text = this.reviewRules(unique_data_Rules, k) + // add a warning in front of rules that use unavailable modifiers or ambiguous rules + // if warning contains duplicate rules we do not write out this rule (even if there are other warnings for the same rule) since that rule had been written before - // ToDo include condition again - // if warning contains duplicate rules we do not write out this rule (even if there are other warnings for the same rule) since that rule had been written before - // if ((warn_text[2].indexOf("duplicate") < 0)) { + // ToDo include condition again + if ((warn_text[2].indexOf("duplicate") < 0)) { data += warn_text[2] + "+ [" + (unique_data_Rules[k].modifier_key + ' ' + unique_data_Rules[k].key).trim() + `] > \'` + new TextDecoder().decode(unique_data_Rules[k].output) + '\'\n' - // } - keymarker = unique_data_Rules[k].key } - } + }} + // Todo remove this marker data += "\n c ########## C2 #################################################################\n" @@ -1551,7 +1492,7 @@ export class KeylayoutToKmnConverter { data += "c from Ukelele file: " + data_ukelele.keylayout_filename + "\n" data += "c ......................................................................\n" data += "c ......................................................................\n" - data += "c \n" + data += "\n" data += "store(&VERSION) \'10.0\'\n" data += "store(&TARGETS) \'any\'\n" @@ -1572,9 +1513,7 @@ export class KeylayoutToKmnConverter { console.log("dataRules ", i, - dataRules[i].rule_type !== "" ? dataRules[i].rule_type : "--".padEnd(4, " ") - - , /*dataRules.length, i,*/ + dataRules[i].rule_type !== "" ? dataRules[i].rule_type : "--".padEnd(4, " "), "| ", (dataRules[i].modifier_prev_deadkey !== "" ? dataRules[i].modifier_prev_deadkey.padEnd(33, " ") : "--".padEnd(33, " ")), (dataRules[i].prev_deadkey !== "" ? dataRules[i].prev_deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), @@ -1599,15 +1538,13 @@ export class KeylayoutToKmnConverter { public writeDatasetSingle(dataRules: rule_object) { console.log("dataRules ", - dataRules.rule_type !== "" ? dataRules.rule_type : "--".padEnd(4, " ") - , + dataRules.rule_type !== "" ? dataRules.rule_type : "--".padEnd(4, " "), "| ", (dataRules.modifier_prev_deadkey !== "" ? dataRules.modifier_prev_deadkey.padEnd(33, " ") : "--".padEnd(33, " ")), (dataRules.prev_deadkey !== "" ? dataRules.prev_deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), (dataRules.id_prev_deadkey !== 0 ? ("dk(A" + String(dataRules.id_prev_deadkey) + ")").padEnd(11, " ") : "--".padEnd(11, " ")), (dataRules.unique_prev_deadkey !== 0 ? ("unique(A" + String(dataRules.unique_prev_deadkey) + ")").padEnd(11, " ") : "--".padEnd(11, " ")), - (dataRules.modifier_deadkey !== "" ? dataRules.modifier_deadkey.padEnd(30, " ") : "--".padEnd(30, " ")), (dataRules.deadkey !== "" ? dataRules.deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), dataRules.rule_type === "C2" ? (dataRules.unique_deadkey !== 0 ? ("unique(C" + String(dataRules.unique_deadkey) + ")").padEnd(9, " ") : "--".padEnd(9, " ")) : ((dataRules.unique_prev_deadkey !== 0 ? ("unique(B" + ")").padEnd(9, " ") : "--".padEnd(9, " "))), From 356dd35bf35e75537a4f224df0593bc1e2f31306 Mon Sep 17 00:00:00 2001 From: Sabine Date: Fri, 21 Feb 2025 16:53:10 +0100 Subject: [PATCH 057/251] feat(developer): check code according to stye guides --- .../keylayout-to-kmn-converter.ts | 193 +++++++++++------- 1 file changed, 117 insertions(+), 76 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index dcc6582b5ea..96fe42eaaac 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -60,6 +60,9 @@ import { ConverterToKmnArtifacts } from "../converter-artifacts.js"; // OK when I run german with uniqueCAll why will there be [ ] without key anf modifier // OK add links to HEADLINE of kmc-convert document // OK TODO more Data stores to add ?? +// OK check for keys < 50 whern working with keys +// OK NO OUTPUT FOR SPACE in C0C1 !!! +// OK check code for code styles keyman // tests for 3 functions read write convert // Return conditions // Tests throws @@ -72,12 +75,10 @@ import { ConverterToKmnArtifacts } from "../converter-artifacts.js"; // replace unique_prev_deadkey 0, >0 with true, false // TODO waht about using actions twice in a row??? -> error msg if chain >4 // what if keylayout file is not correct e.g missing > -// check for keys < 50 whern working with keys -// check code for code styles keyman // read TODO which stores? // does order of modifier matter ? -// NO OUTPUT FOR SPACE in C0C1 !!! // remove all markers c0, 1-1, #### C2 ###, ... +// better function names for get...... import { XMLParser } from 'fast-xml-parser'; // for reading an xml file @@ -260,10 +261,11 @@ export class KeylayoutToKmnConverter { this.callbacks.fs.writeFileSync("data/MyResult.kmn", new TextEncoder().encode(data)) // ToDo conditions? - if (data.length > 0) + if (data.length > 0) { return true; - else + } else { return false + } } // TODO move outside of class? @@ -318,8 +320,9 @@ export class KeylayoutToKmnConverter { /* key */ this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), /* output */ new TextEncoder().encode(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output']), ) - if (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] !== "") + if (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] !== "") { object_array.push(rule_obj) + } } } @@ -432,8 +435,9 @@ export class KeylayoutToKmnConverter { /* key */ b1_modifierKey_arr[n4][0], /* output */ new TextEncoder().encode(b1_modifierKey_arr[n4][4]), ) - if (b1_modifierKey_arr[n4][4] !== undefined) + if (b1_modifierKey_arr[n4][4] !== undefined) { object_array.push(rule_obj) + } } } } @@ -518,8 +522,9 @@ export class KeylayoutToKmnConverter { /* key */ b1_modifierKey_arr[n7][0], /* output */ new TextEncoder().encode(b1_modifierKey_arr[n7][4]), ) - if (b1_modifierKey_arr[n7][4] !== undefined) + if (b1_modifierKey_arr[n7][4] !== undefined) { object_array.push(rule_obj) + } } } } @@ -529,9 +534,9 @@ export class KeylayoutToKmnConverter { } } } - } - else + } else { console.log("ERROR : some entries are not available") + } } } @@ -598,8 +603,9 @@ export class KeylayoutToKmnConverter { unique_dkA_count++ // check if first part of C3 rule contains already defined rule for (let k = 0; k < unique_ruleArrayC2.length; k++) { - if ((unique_ruleArrayC2[k][0] === object_array[i].modifier_deadkey) && ((unique_ruleArrayC2[k][1] === object_array[i].deadkey))) + if ((unique_ruleArrayC2[k][0] === object_array[i].modifier_deadkey) && ((unique_ruleArrayC2[k][1] === object_array[i].deadkey))) { object_array[i].unique_deadkey = Number(unique_ruleArrayC2[k][2]) + } } } @@ -687,8 +693,9 @@ export class KeylayoutToKmnConverter { returnarray.push(data.keyboard.keyMapSet[0].keyMap[i]['@_index']) returnarray.push(search[k][2]) } - if (returnarray.length > 0) + if (returnarray.length > 0) { returnarray2D.push(returnarray) + } } } } @@ -701,8 +708,9 @@ export class KeylayoutToKmnConverter { */ public get_ActionID_Index__From__ActionID_Id(data: any, search: string): number { for (let i = 0; i < data.keyboard.actions.action.length; i++) { - if (data.keyboard.actions.action[i]['@_id'] === search) + if (data.keyboard.actions.action[i]['@_id'] === search) { return i + } } return 0 } @@ -739,8 +747,9 @@ export class KeylayoutToKmnConverter { returnarray.push(data.keyboard.actions.action[i].when[j]['@_state']) returnarray.push(data.keyboard.actions.action[i].when[j]['@_output']) } - if (returnarray.length > 0) + if (returnarray.length > 0) { returnarray2D.push(returnarray) + } } } return returnarray2D @@ -782,8 +791,9 @@ export class KeylayoutToKmnConverter { returnarray1D.push(search[i][3]) /* behaviour*/ returnarray1D.push(this.create_kmn_modifier(data.keyboard.modifierMap.keyMapSelect[behaviour].modifier[j]['@_keys'], isCAPSused)) /* modifier */ returnarray1D.push(search[i][4]) /* char*/ - if (returnarray1D.length > 0) + if (returnarray1D.length > 0) { returnarray.push(returnarray1D) + } } } // remove duplicates @@ -825,8 +835,9 @@ export class KeylayoutToKmnConverter { returnarray.push(keyName) returnarray.push(modifierkmn) - if (returnarray.length > 0) + if (returnarray.length > 0) { returnarray2D.push(returnarray) + } } } } @@ -861,8 +872,9 @@ export class KeylayoutToKmnConverter { mapIndexArrayperKey.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']) mapIndexArrayperKey.push(i) } - if (mapIndexArrayperKey.length > 0) + if (mapIndexArrayperKey.length > 0) { mapIndexArray_max.push(mapIndexArrayperKey) + } } } return mapIndexArray_max @@ -880,14 +892,6 @@ export class KeylayoutToKmnConverter { return mapIndexArray_max } - /** - * @brief member function to return the unicode value of a character - * @param character the value that will converted - * @return headecimal value of a character - */ - /* public getHexFromChar(character: string): string { - return character.charCodeAt(0).toString(16).slice(-4).toUpperCase().padStart(4, "0") - }*/ /** * @brief member function to create a string of modifiers in kmn-style from the modifierMap section of .keylayout-file * @param keylayout_modifier the modifier value used in the .keylayout-file @@ -904,31 +908,61 @@ export class KeylayoutToKmnConverter { for (let i = 0; i < modifier_state.length; i++) { - if (isCAPSused && (keylayout_modifier).toUpperCase().indexOf("CAPS") === -1) + if (isCAPSused && (keylayout_modifier).toUpperCase().indexOf("CAPS") === -1) { kmn_ncaps = " NCAPS " + } // if we find a modifier containing a '?' e.g. SHIFT?: => SHIFT is not neccessary. If it is not neccessary we don`t write this modifier - if (modifier_state[i].toUpperCase().includes('?') && (!modifier_state[i].toUpperCase().includes('CAPS?'))) add_modifier = ""; + if (modifier_state[i].toUpperCase().includes('?') && (!modifier_state[i].toUpperCase().includes('CAPS?'))) { + add_modifier = ""; + } // TODO is this correct: caps? => caps is not neccessary. If its not neccessary and isCAPSused we need to write out NCAPS. Correct? - else if (isCAPSused && (modifier_state[i].toUpperCase().includes('CAPS?'))) add_modifier = "NCAPS "; - else if (!isCAPSused && (modifier_state[i].toUpperCase().includes('CAPS?'))) add_modifier = ""; - else if (modifier_state[i].toUpperCase().includes('CAPS')) add_modifier = "CAPS "; - else if (isCAPSused && (modifier_state[i].toUpperCase().includes('NCAPS'))) add_modifier = "NCAPS "; + else if (isCAPSused && (modifier_state[i].toUpperCase().includes('CAPS?'))) { + add_modifier = "NCAPS "; + } + else if (!isCAPSused && (modifier_state[i].toUpperCase().includes('CAPS?'))) { + add_modifier = ""; + } + else if (modifier_state[i].toUpperCase().includes('CAPS')) { + add_modifier = "CAPS "; + } + else if (isCAPSused && (modifier_state[i].toUpperCase().includes('NCAPS'))) { + add_modifier = "NCAPS "; + } // Keyman does not use the right or left version of a modifier (e.g. rightshift, leftshift). If those are used in keylayout files // they will not be changed but written to the kmn as they are with a warning placed in front of them - else if ((modifier_state[i].toUpperCase() === 'ANYSHIFT') || (modifier_state[i].toUpperCase() === 'SHIFT')) add_modifier = "SHIFT "; - else if ((modifier_state[i].toUpperCase() === "LEFTSHIFT") || (modifier_state[i].toUpperCase() === "LSHIFT")) add_modifier = "SHIFT "; - else if ((modifier_state[i].toUpperCase() === "RIGHTSHIFT") || (modifier_state[i].toUpperCase() === "RSHIFT")) add_modifier = "SHIFT "; - else if ((modifier_state[i].toUpperCase() === 'ANYCONTROL') || (modifier_state[i].toUpperCase() === 'CONTROL')) add_modifier = "RCTRL "; - else if ((modifier_state[i].toUpperCase() === "LEFTCONTROL") || (modifier_state[i].toUpperCase() === "LCONTROL")) add_modifier = "CTRL "; - else if ((modifier_state[i].toUpperCase() === "RIGHTCONTROL") || (modifier_state[i].toUpperCase() === "LCONTROL")) add_modifier = "CTRL "; - else if ((modifier_state[i].toUpperCase() === "LEFTOPTION") || (modifier_state[i].toUpperCase() === "LOPTION")) add_modifier = "RALT "; - else if ((modifier_state[i].toUpperCase() === "RIGHTOPTION") || (modifier_state[i].toUpperCase() === "ROPTION")) add_modifier = "RALT "; - else if ((modifier_state[i].toUpperCase() === 'ANYOPTION') || (modifier_state[i].toUpperCase() === 'OPTION')) add_modifier = "RALT "; - - else add_modifier = String(modifier_state[i]) + " " + else if ((modifier_state[i].toUpperCase() === 'ANYSHIFT') || (modifier_state[i].toUpperCase() === 'SHIFT')) { + add_modifier = "SHIFT "; + } + else if ((modifier_state[i].toUpperCase() === "LEFTSHIFT") || (modifier_state[i].toUpperCase() === "LSHIFT")) { + add_modifier = "SHIFT "; + } + else if ((modifier_state[i].toUpperCase() === "RIGHTSHIFT") || (modifier_state[i].toUpperCase() === "RSHIFT")) { + add_modifier = "SHIFT "; + } + else if ((modifier_state[i].toUpperCase() === 'ANYCONTROL') || (modifier_state[i].toUpperCase() === 'CONTROL')) { + add_modifier = "RCTRL "; + } + else if ((modifier_state[i].toUpperCase() === "LEFTCONTROL") || (modifier_state[i].toUpperCase() === "LCONTROL")) { + add_modifier = "CTRL "; + } + else if ((modifier_state[i].toUpperCase() === "RIGHTCONTROL") || (modifier_state[i].toUpperCase() === "LCONTROL")) { + add_modifier = "CTRL "; + } + else if ((modifier_state[i].toUpperCase() === "LEFTOPTION") || (modifier_state[i].toUpperCase() === "LOPTION")) { + add_modifier = "RALT "; + } + else if ((modifier_state[i].toUpperCase() === "RIGHTOPTION") || (modifier_state[i].toUpperCase() === "ROPTION")) { + add_modifier = "RALT "; + } + else if ((modifier_state[i].toUpperCase() === 'ANYOPTION') || (modifier_state[i].toUpperCase() === 'OPTION')) { + add_modifier = "RALT "; + } + else { + add_modifier = String(modifier_state[i]) + " " + } kmn_modifier += kmn_ncaps + add_modifier } @@ -960,11 +994,9 @@ export class KeylayoutToKmnConverter { || (modifier_single[i].toUpperCase() === "LCTRL") || (modifier_single[i].toUpperCase() === "RCTRL") || (modifier_single[i].toUpperCase() === "") - ) { iskKeymanModifier &&= true - } - else { + } else { iskKeymanModifier &&= false } } @@ -986,7 +1018,7 @@ export class KeylayoutToKmnConverter { } } - else if (rule[index].rule_type === "C2") { + else if (rule[index].rule_type === "C2") { if (!this.isAcceptableKeymanModifier(rule[index].modifier_deadkey)) { warningTextArray[1] = "C2 unavailable modifier in: " } @@ -1159,7 +1191,7 @@ export class KeylayoutToKmnConverter { ); // 4-4 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > 'dk(C1)' - const amb_4_4_mid = rule.filter((curr, idx) => + const amb_4_4 = rule.filter((curr, idx) => curr.rule_type === "C3" && curr.modifier_prev_deadkey === rule[index].modifier_prev_deadkey && curr.id_prev_deadkey !== rule[index].id_prev_deadkey @@ -1238,8 +1270,8 @@ export class KeylayoutToKmnConverter { warningTextArray[1] = warningTextArray[1] + ("C3 SECONDTEXT " + "duplicate 6-3 rule: earlier: dk(C" + dup_6_3[0].id_deadkey + ") + [" + dup_6_3[0].modifier_key + " " + dup_6_3[0].key + "] > \'" + new TextDecoder().decode(dup_6_3[0].output) + "\' here: ") } - if (amb_4_4_mid.length > 0) { - warningTextArray[0] = warningTextArray[0] + ("C3 FIRSTTEXT " + "ambiguous 4-4 rule: earlier: [" + amb_4_4_mid[0].modifier_prev_deadkey + " " + amb_4_4_mid[0].prev_deadkey + "] > dk(C" + amb_4_4_mid[0].id_prev_deadkey + ") here: ") + if (amb_4_4.length > 0) { + warningTextArray[0] = warningTextArray[0] + ("C3 FIRSTTEXT " + "ambiguous 4-4 rule: earlier: [" + amb_4_4[0].modifier_prev_deadkey + " " + amb_4_4[0].prev_deadkey + "] > dk(C" + amb_4_4[0].id_prev_deadkey + ") here: ") } if (dup_4_4.length > 0) { @@ -1263,9 +1295,15 @@ export class KeylayoutToKmnConverter { } } - if (warningTextArray[0] !== "") warningTextArray[0] = "c WARNING: " + warningTextArray[0] - if (warningTextArray[1] !== "") warningTextArray[1] = "c WARNING: " + warningTextArray[1] - if (warningTextArray[2] !== "") warningTextArray[2] = "c WARNING: " + warningTextArray[2] + if (warningTextArray[0] !== "") { + warningTextArray[0] = "c WARNING: " + warningTextArray[0] + } + if (warningTextArray[1] !== "") { + warningTextArray[1] = "c WARNING: " + warningTextArray[1] + } + if (warningTextArray[2] !== "") { + warningTextArray[2] = "c WARNING: " + warningTextArray[2] + } return warningTextArray } @@ -1348,8 +1386,9 @@ export class KeylayoutToKmnConverter { if ((curr.output !== new TextEncoder().encode("") || curr.output !== undefined) && (curr.rule_type === "C0") || (curr.rule_type === "C1") || (curr.rule_type === "C2") || (curr.rule_type === "C3")) { return curr; + } else { + return "" } - else return "" }); const unique_data_Rules: rule_object[] = data_rules.reduce((unique, o) => { if (!unique.some((obj: { output: Uint8Array; rule_type: string; modifier_key: string; modifier_deadkey: string; prev_deadkey: string; modifier_prev_deadkey: string; deadkey: string; key: string }) => @@ -1383,38 +1422,40 @@ export class KeylayoutToKmnConverter { for (let k = 0; k < unique_data_Rules.length; k++) { - if ((unique_data_Rules[k].rule_type === "C0")||(unique_data_Rules[k].rule_type === "C1")) { + if ((unique_data_Rules[k].rule_type === "C0") || (unique_data_Rules[k].rule_type === "C1")) { - // lookup key nr of the key that is being processed - let keyNr: number = 0; - for (let j = 0; j < KeylayoutToKmnConverter.USED_KEYS_COUNT; j++) { - if (this.map_UkeleleKC_To_VK(j) === unique_data_Rules[k].key) { - keyNr = j - break + // lookup key nr of the key that is being processed + let keyNr: number = 0; + for (let j = 0; j < KeylayoutToKmnConverter.USED_KEYS_COUNT; j++) { + if (this.map_UkeleleKC_To_VK(j) === unique_data_Rules[k].key) { + keyNr = j + break + } } - } - // skip keyNr 48 (K_TAB) and 36 (K_ENTER) - if ((keyNr === 48) || (keyNr === 36)) - continue + // skip keyNr 48 (K_TAB) and 36 (K_ENTER) + if ((keyNr === 48) || (keyNr === 36)) { + continue + } - //--------------------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------------------- - // add a line after rules of each key - if ((k > 1) && (unique_data_Rules[k - 1].key !== unique_data_Rules[k].key) && (unique_data_Rules[k - 1].rule_type === unique_data_Rules[k].rule_type)) { - data += '\n' - } + // add a line after rules of each key + if ((k > 1) && (unique_data_Rules[k - 1].key !== unique_data_Rules[k].key) && (unique_data_Rules[k - 1].rule_type === unique_data_Rules[k].rule_type)) { + data += '\n' + } - const warn_text = this.reviewRules(unique_data_Rules, k) + const warn_text = this.reviewRules(unique_data_Rules, k) - // add a warning in front of rules that use unavailable modifiers or ambiguous rules - // if warning contains duplicate rules we do not write out this rule (even if there are other warnings for the same rule) since that rule had been written before + // add a warning in front of rules that use unavailable modifiers or ambiguous rules + // if warning contains duplicate rules we do not write out this rule (even if there are other warnings for the same rule) since that rule had been written before - // ToDo include condition again - if ((warn_text[2].indexOf("duplicate") < 0)) { - data += warn_text[2] + "+ [" + (unique_data_Rules[k].modifier_key + ' ' + unique_data_Rules[k].key).trim() + `] > \'` + new TextDecoder().decode(unique_data_Rules[k].output) + '\'\n' + // ToDo include condition again + if ((warn_text[2].indexOf("duplicate") < 0)) { + data += warn_text[2] + "+ [" + (unique_data_Rules[k].modifier_key + ' ' + unique_data_Rules[k].key).trim() + `] > \'` + new TextDecoder().decode(unique_data_Rules[k].output) + '\'\n' + } } - }} + } // Todo remove this marker data += "\n c ########## C2 #################################################################\n" From 7e2c5b4f20222175c913c068e9fae341cf3c0e04 Mon Sep 17 00:00:00 2001 From: Sabine Date: Mon, 24 Feb 2025 10:44:17 +0100 Subject: [PATCH 058/251] feat(developer): check more code according to style guides --- .../keylayout-to-kmn-converter.ts | 305 ++++++++++++++---- 1 file changed, 251 insertions(+), 54 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 96fe42eaaac..ac6b369b2fa 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -73,7 +73,7 @@ import { ConverterToKmnArtifacts } from "../converter-artifacts.js"; // Filter functions use the same type // TODO need to use export const USVirtualKeyCodes here // replace unique_prev_deadkey 0, >0 with true, false -// TODO waht about using actions twice in a row??? -> error msg if chain >4 +// TODO what about using actions twice in a row??? -> error msg if chain >4 // what if keylayout file is not correct e.g missing > // read TODO which stores? // does order of modifier matter ? @@ -344,7 +344,8 @@ export class KeylayoutToKmnConverter { && (this.get_Action2ID_NoneOutput__From__ActionID_Id(jsonObj, action_id) !== "")) { const outputchar: string = this.get_Action2ID_NoneOutput__From__ActionID_Id(jsonObj, action_id) - const b1_modifierKey_arr: string[][] = this.get_Datat_array2D__From__ActionID_stateOutput(jsonObj, data_ukelele.arrayOf_Modifiers, action_id, outputchar, isCapsused) + const b1_modifierKey_arr: string[][] = + this.get_Datat_array2D__From__ActionID_stateOutput(jsonObj, data_ukelele.arrayOf_Modifiers, action_id, outputchar, isCapsused) for (let m = 0; m < b1_modifierKey_arr.length; m++) { @@ -540,16 +541,16 @@ export class KeylayoutToKmnConverter { } } - // --------------------------------------------------------------------------------------------------------------------- - // --------------------------------------------------------------------------------------------------------------------- - // now prepare for printing i.e. check for duplicate C2 and C3 rules and mark first occurance of rule - // add nr to unique_prev_deadkey, unique_deadkey if it is the first occurence of declaration of dk e.g. [NCAPS RALT K_8] > dk(C12) - // --------------------------------------------------------------------------------------------------------------------- - // --------------------------------------------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------------------------------------------------------------------------- + // check for duplicate C2 and C3 rules in object_array (e.g. [NCAPS RALT K_8] > dk(C12) ): create a separate array of unique rules, + // then compare to object_array and mark first occurance of a rule in object_array + // -------------------------------------------------------------------------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------------------------------------------------------------------------- let unique_dkB_count = 0 - const unique_ruleArrayC2: string[][] = [] + const list_of_unique_rules: string[][] = [] - //----------------------------------- -dk---------------------------------- + //------------------------------------ C2: dk ---------------------------------- // first rule is always unique object_array[0].unique_deadkey = unique_dkB_count object_array[0].id_deadkey = unique_dkB_count @@ -574,12 +575,12 @@ export class KeylayoutToKmnConverter { ruleArray.push(object_array[i].deadkey) ruleArray.push(String(unique_dkB_count)) unique_dkB_count++ - unique_ruleArrayC2.push(ruleArray) + list_of_unique_rules.push(ruleArray) } } } - //-----------------------------------prev-dk---------------------------------- + //----------------------------------- C3: prev-dk ---------------------------------- let unique_dkA_count = 0 // first rule is always unique @@ -598,13 +599,13 @@ export class KeylayoutToKmnConverter { } } + // check if first part of C3 rule contains already defined rule of C2 if (isFirstUsedHere_prev_dk) { object_array[i].unique_prev_deadkey = unique_dkA_count unique_dkA_count++ - // check if first part of C3 rule contains already defined rule - for (let k = 0; k < unique_ruleArrayC2.length; k++) { - if ((unique_ruleArrayC2[k][0] === object_array[i].modifier_deadkey) && ((unique_ruleArrayC2[k][1] === object_array[i].deadkey))) { - object_array[i].unique_deadkey = Number(unique_ruleArrayC2[k][2]) + for (let k = 0; k < list_of_unique_rules.length; k++) { + if ((list_of_unique_rules[k][0] === object_array[i].modifier_deadkey) && ((list_of_unique_rules[k][1] === object_array[i].deadkey))) { + object_array[i].unique_deadkey = Number(list_of_unique_rules[k][2]) } } } @@ -616,18 +617,19 @@ export class KeylayoutToKmnConverter { ruleArray.push(object_array[i].prev_deadkey) ruleArray.push(String(unique_dkB_count)) unique_dkB_count++ - unique_ruleArrayC2.push(ruleArray) + list_of_unique_rules.push(ruleArray) } } } + // loop through object_array and mark first occurence each rule of list_of_unique_rules for (let i = 0; i < object_array.length; i++) { - for (let j = 0; j < unique_ruleArrayC2.length; j++) { - if ((object_array[i].modifier_prev_deadkey === unique_ruleArrayC2[j][0]) && (object_array[i].prev_deadkey === unique_ruleArrayC2[j][1])) { - object_array[i].id_prev_deadkey = Number(unique_ruleArrayC2[j][2]) + for (let j = 0; j < list_of_unique_rules.length; j++) { + if ((object_array[i].modifier_prev_deadkey === list_of_unique_rules[j][0]) && (object_array[i].prev_deadkey === list_of_unique_rules[j][1])) { + object_array[i].id_prev_deadkey = Number(list_of_unique_rules[j][2]) } - if ((object_array[i].modifier_deadkey === unique_ruleArrayC2[j][0]) && (object_array[i].deadkey === unique_ruleArrayC2[j][1])) { - object_array[i].id_deadkey = Number(unique_ruleArrayC2[j][2]) + if ((object_array[i].modifier_deadkey === list_of_unique_rules[j][0]) && (object_array[i].deadkey === list_of_unique_rules[j][1])) { + object_array[i].id_deadkey = Number(list_of_unique_rules[j][2]) } } } @@ -1014,28 +1016,28 @@ export class KeylayoutToKmnConverter { // Todo remoce C1-C3's and other markers if ((rule[index].rule_type === "C0") || (rule[index].rule_type === "C1")) { if (!this.isAcceptableKeymanModifier(rule[index].modifier_key)) { - warningTextArray[2] = "C1 unavailable modifier in: " + warningTextArray[2] = "C1 unavailable modifier : " } } else if (rule[index].rule_type === "C2") { if (!this.isAcceptableKeymanModifier(rule[index].modifier_deadkey)) { - warningTextArray[1] = "C2 unavailable modifier in: " + warningTextArray[1] = "C2 unavailable modifier : " } if (!this.isAcceptableKeymanModifier(rule[index].modifier_key)) { - warningTextArray[2] = "C2 unavailable modifier in: " + warningTextArray[2] = "C2 unavailable modifier : " } } else if (rule[index].rule_type === "C3") { if (!this.isAcceptableKeymanModifier(rule[index].modifier_prev_deadkey)) { - warningTextArray[2] = "C3 unavailable modifier in: " + warningTextArray[2] = "C3 unavailable modifier : " } if (!this.isAcceptableKeymanModifier(rule[index].modifier_deadkey)) { - warningTextArray[1] = "C3 unavailable modifier in: " + warningTextArray[1] = "C3 unavailable modifier : " } if (!this.isAcceptableKeymanModifier(rule[index].modifier_key)) { - warningTextArray[0] = "C3 unavailable modifier in: " + warningTextArray[0] = "C3 unavailable modifier : " } } @@ -1045,8 +1047,8 @@ export class KeylayoutToKmnConverter { if ((rule[index].rule_type === "C0") || (rule[index].rule_type === "C1")) { // 1-1 + [CAPS K_N] > 'N' <-> + [CAPS K_N] > 'A' - const amb_1_1 = rule.filter((curr, idx) => ( - curr.rule_type === "C0" || curr.rule_type === "C1") + const amb_1_1 = rule.filter((curr, idx) => + (curr.rule_type === "C0" || curr.rule_type === "C1") && curr.modifier_prev_deadkey === "" && curr.prev_deadkey === "" && curr.modifier_deadkey === "" @@ -1071,11 +1073,25 @@ export class KeylayoutToKmnConverter { ); if (amb_1_1.length > 0) { - warningTextArray[2] = warningTextArray[2] + ("C1 ambiguous 1-1 rule: earlier: [" + amb_1_1[0].modifier_key + " " + amb_1_1[0].key + "] > \'" + new TextDecoder().decode(amb_1_1[0].output) + "\' here: [") + warningTextArray[2] = warningTextArray[2] + + ("C1 ambiguous 1-1 rule: earlier: [" + + amb_1_1[0].modifier_key + + " " + + amb_1_1[0].key + + "] > \'" + + new TextDecoder().decode(amb_1_1[0].output) + + "\' here: [") } if (dup_1_1.length > 0) { - warningTextArray[2] = warningTextArray[2] + ("C1 duplicate 1-1 rule: earlier: [" + dup_1_1[0].modifier_key + " " + dup_1_1[0].key + "] > \'" + new TextDecoder().decode(dup_1_1[0].output) + "\' here: [") + warningTextArray[2] = warningTextArray[2] + + ("C1 duplicate 1-1 rule: earlier: [" + + dup_1_1[0].modifier_key + + " " + + dup_1_1[0].key + + "] > \'" + + new TextDecoder().decode(dup_1_1[0].output) + + "\' here: [") } } @@ -1131,19 +1147,63 @@ export class KeylayoutToKmnConverter { ); if (amb_2_2.length > 0) { - warningTextArray[1] = warningTextArray[1] + ("C2 SECONDTEXT " + "ambiguous 2-2 rule: earlier: [" + amb_2_2[0].modifier_deadkey + " " + amb_2_2[0].deadkey + "] > dk(C" + amb_2_2[0].id_deadkey + ") here: ") + warningTextArray[1] = warningTextArray[1] + + ("C2 SECONDTEXT " + + "ambiguous 2-2 rule: earlier: [" + + amb_2_2[0].modifier_deadkey + + " " + + amb_2_2[0].deadkey + + "] > dk(C" + + amb_2_2[0].id_deadkey + + ") here: ") } if (dup_2_2.length > 0) { - warningTextArray[1] = warningTextArray[1] + ("C2 SECONDTEXT " + "duplicate 2-2 rule: earlier: [" + dup_2_2[0].modifier_deadkey + " " + dup_2_2[0].deadkey + "] > dk(C" + dup_2_2[0].id_deadkey + ") here: ") + warningTextArray[1] = warningTextArray[1] + + ("C2 SECONDTEXT " + + "duplicate 2-2 rule: earlier: [" + + dup_2_2[0].modifier_deadkey + + " " + + dup_2_2[0].deadkey + + "] > dk(C" + + dup_2_2[0].id_deadkey + + ") here: ") } if (amb_3_3.length > 0) { - warningTextArray[2] = warningTextArray[2] + ("C2 THIRDTEXT " + "ambiguous 3-3 rule: earlier: dk(C" + amb_3_3[0].id_deadkey + ") + [" + amb_3_3[0].modifier_key + " " + amb_3_3[0].key + "] > \'" + new TextDecoder().decode(amb_3_3[0].output) + "\' here: ") + warningTextArray[2] = warningTextArray[2] + + ("C2 THIRDTEXT " + + "ambiguous 3-3 rule: earlier: dk(C" + + amb_3_3[0].id_deadkey + + ") + [" + + amb_3_3[0].modifier_key + + " " + + amb_3_3[0].key + + "] > \'" + + new TextDecoder().decode(amb_3_3[0].output) + + "\' here: ") } if (dup_3_3.length > 0) { - warningTextArray[2] = warningTextArray[2] + ("C2 THIRDTEXT " + "duplicate 3-3 rule: earlier: dk(C" + dup_3_3[0].id_deadkey + ") + [" + dup_3_3[0].modifier_key + " " + dup_3_3[0].key + "] > \'" + new TextDecoder().decode(dup_3_3[0].output) + "\' here: ") + warningTextArray[2] = warningTextArray[2] + + ("C2 THIRDTEXT " + + "duplicate 3-3 rule: earlier: dk(C" + + dup_3_3[0].id_deadkey + + ") + [" + + dup_3_3[0].modifier_key + + " " + + dup_3_3[0].key + + "] > \'" + + new TextDecoder().decode(dup_3_3[0].output) + + "\' here: ") } if (amb_1_2.length > 0) { - warningTextArray[1] = warningTextArray[1] + ("C2 SECONDTEXT " + "ambiguous 1-2 rule: earlier: [" + amb_1_2[0].modifier_key + " " + amb_1_2[0].key + "] > \'" + new TextDecoder().decode(amb_1_2[0].output) + "\' here: ") + warningTextArray[1] = warningTextArray[1] + + ("C2 SECONDTEXT " + + "ambiguous 1-2 rule: earlier: [" + + amb_1_2[0].modifier_key + + " " + + amb_1_2[0].key + + "] > \'" + + new TextDecoder().decode(amb_1_2[0].output) + + "\' here: ") } } @@ -1255,43 +1315,136 @@ export class KeylayoutToKmnConverter { ); if (amb_1_4.length > 0) { - warningTextArray[0] = warningTextArray[0] + ("C3 FIRSTTEXT " + "ambiguous 1-4 rule: earlier(Todo check if print out or not): [" + amb_1_4[0].modifier_key + " " + amb_1_4[0].key + "] > \'" + new TextDecoder().decode(amb_1_4[0].output) + "\' here: ") + warningTextArray[0] = warningTextArray[0] + + ("C3 FIRSTTEXT " + + "ambiguous 1-4 rule: earlier(Todo check if print out or not): [" + + amb_1_4[0].modifier_key + + " " + + amb_1_4[0].key + + "] > \'" + + new TextDecoder().decode(amb_1_4[0].output) + + "\' here: ") } if (amb_2_4.length > 0) { - warningTextArray[0] = warningTextArray[0] + ("C3 FIRSTTEXT " + "ambiguous 2-4 rule: earlier(Todo check if print out or not): [" + amb_2_4[0].modifier_deadkey + " " + amb_2_4[0].deadkey + "] > dk(C" + amb_2_4[0].id_deadkey + ") here: ") + warningTextArray[0] = warningTextArray[0] + + ("C3 FIRSTTEXT " + + "ambiguous 2-4 rule: earlier(Todo check if print out or not): [" + + amb_2_4[0].modifier_deadkey + + " " + + amb_2_4[0].deadkey + + "] > dk(C" + + amb_2_4[0].id_deadkey + + ") here: ") } if (amb_6_3.length > 0) { - warningTextArray[1] = warningTextArray[1] + ("C3 SECONDTEXT " + "ambiguous 6-3 rule: earlier: dk(C" + amb_6_3[0].id_deadkey + ") + [" + amb_6_3[0].modifier_key + " " + amb_6_3[0].key + "] > \'" + new TextDecoder().decode(amb_6_3[0].output) + "\' here: ") + warningTextArray[1] = warningTextArray[1] + + ("C3 SECONDTEXT " + + "ambiguous 6-3 rule: earlier: dk(C" + + amb_6_3[0].id_deadkey + + ") + [" + + amb_6_3[0].modifier_key + + " " + + amb_6_3[0].key + + "] > \'" + + new TextDecoder().decode(amb_6_3[0].output) + + "\' here: ") } if (dup_6_3.length > 0) { - warningTextArray[1] = warningTextArray[1] + ("C3 SECONDTEXT " + "duplicate 6-3 rule: earlier: dk(C" + dup_6_3[0].id_deadkey + ") + [" + dup_6_3[0].modifier_key + " " + dup_6_3[0].key + "] > \'" + new TextDecoder().decode(dup_6_3[0].output) + "\' here: ") + warningTextArray[1] = warningTextArray[1] + + ("C3 SECONDTEXT " + + "duplicate 6-3 rule: earlier: dk(C" + + dup_6_3[0].id_deadkey + + ") + [" + + dup_6_3[0].modifier_key + + " " + + dup_6_3[0].key + + "] > \'" + + new TextDecoder().decode(dup_6_3[0].output) + + "\' here: ") } if (amb_4_4.length > 0) { - warningTextArray[0] = warningTextArray[0] + ("C3 FIRSTTEXT " + "ambiguous 4-4 rule: earlier: [" + amb_4_4[0].modifier_prev_deadkey + " " + amb_4_4[0].prev_deadkey + "] > dk(C" + amb_4_4[0].id_prev_deadkey + ") here: ") + warningTextArray[0] = warningTextArray[0] + + ("C3 FIRSTTEXT " + + "ambiguous 4-4 rule: earlier: [" + + amb_4_4[0].modifier_prev_deadkey + + " " + + amb_4_4[0].prev_deadkey + + "] > dk(C" + + amb_4_4[0].id_prev_deadkey + + ") here: ") } if (dup_4_4.length > 0) { - warningTextArray[0] = warningTextArray[0] + ("C3 FIRSTTEXT " + "duplicate 4-4 rule: earlier: [" + dup_4_4[0].modifier_prev_deadkey + " " + dup_4_4[0].prev_deadkey + "] > dk(C" + dup_4_4[0].id_prev_deadkey + ") here: ") + warningTextArray[0] = warningTextArray[0] + + ("C3 FIRSTTEXT " + + "duplicate 4-4 rule: earlier: [" + + dup_4_4[0].modifier_prev_deadkey + + " " + + dup_4_4[0].prev_deadkey + + "] > dk(C" + + dup_4_4[0].id_prev_deadkey + + ") here: ") } if (amb_5_5.length > 0) { - warningTextArray[1] = warningTextArray[1] + ("C3 SECONDTEXT " + "ambiguous 5-5 rule: earlier: dk(B" + amb_5_5[0].id_prev_deadkey + ") + [" + amb_5_5[0].modifier_deadkey + " " + amb_5_5[0].deadkey + "] > dk(B" + amb_5_5[0].id_deadkey + ") here: ") + warningTextArray[1] = warningTextArray[1] + + ("C3 SECONDTEXT " + + "ambiguous 5-5 rule: earlier: dk(B" + + amb_5_5[0].id_prev_deadkey + + ") + [" + + amb_5_5[0].modifier_deadkey + + " " + + amb_5_5[0].deadkey + + "] > dk(B" + + amb_5_5[0].id_deadkey + + ") here: ") } if (dup_5_5.length > 0) { - warningTextArray[1] = warningTextArray[1] + ("C3 SECONDTEXT " + "duplicate 5-5 rule: earlier: dk(B" + dup_5_5[0].id_prev_deadkey + ") + [" + dup_5_5[0].modifier_deadkey + " " + dup_5_5[0].deadkey + "] > dk(B" + dup_5_5[0].id_deadkey + ") here: ") + warningTextArray[1] = warningTextArray[1] + + ("C3 SECONDTEXT " + + "duplicate 5-5 rule: earlier: dk(B" + + dup_5_5[0].id_prev_deadkey + + ") + [" + + dup_5_5[0].modifier_deadkey + + " " + + dup_5_5[0].deadkey + + "] > dk(B" + + dup_5_5[0].id_deadkey + + ") here: ") } if (amb_6_6.length > 0) { - warningTextArray[2] = warningTextArray[2] + ("C3 THIRDTEXT " + "ambiguous 6-6 rule: earlier: dk(B" + amb_6_6[0].id_deadkey + ") + [" + amb_6_6[0].modifier_key + " " + amb_6_6[0].key + "] > \'" + new TextDecoder().decode(amb_6_6[0].output) + "\' here: ") + warningTextArray[2] = warningTextArray[2] + + ("C3 THIRDTEXT " + + "ambiguous 6-6 rule: earlier: dk(B" + + amb_6_6[0].id_deadkey + + ") + [" + + amb_6_6[0].modifier_key + + " " + + amb_6_6[0].key + + "] > \'" + + new TextDecoder().decode(amb_6_6[0].output) + + "\' here: ") } if (dup_6_6.length > 0) { - warningTextArray[2] = warningTextArray[2] + ("C3 THIRDTEXT " + "duplicate 6-6x rule: earlier: dk(B" + dup_6_6[0].id_deadkey + ") + [" + dup_6_6[0].modifier_key + " " + dup_6_6[0].key + "] > \'" + new TextDecoder().decode(dup_6_6[0].output) + "\' here: ") + warningTextArray[2] = warningTextArray[2] + + + ("C3 THIRDTEXT " + + "duplicate 6-6x rule: earlier: dk(B" + + dup_6_6[0].id_deadkey + + ") + [" + + dup_6_6[0].modifier_key + + " " + + dup_6_6[0].key + + "] > \'" + + new TextDecoder().decode(dup_6_6[0].output) + + "\' here: ") } } @@ -1391,7 +1544,12 @@ export class KeylayoutToKmnConverter { } }); const unique_data_Rules: rule_object[] = data_rules.reduce((unique, o) => { - if (!unique.some((obj: { output: Uint8Array; rule_type: string; modifier_key: string; modifier_deadkey: string; prev_deadkey: string; modifier_prev_deadkey: string; deadkey: string; key: string }) => + if (!unique.some((obj: { + modifier_prev_deadkey: string; prev_deadkey: string; + modifier_deadkey: string; deadkey: string; + rule_type: string; modifier_key: string; key: string; + output: Uint8Array; + }) => new TextDecoder().decode(obj.output) === new TextDecoder().decode(o.output) && obj.rule_type === o.rule_type @@ -1452,7 +1610,13 @@ export class KeylayoutToKmnConverter { // ToDo include condition again if ((warn_text[2].indexOf("duplicate") < 0)) { - data += warn_text[2] + "+ [" + (unique_data_Rules[k].modifier_key + ' ' + unique_data_Rules[k].key).trim() + `] > \'` + new TextDecoder().decode(unique_data_Rules[k].output) + '\'\n' + data += + warn_text[2] + + "+ [" + + (unique_data_Rules[k].modifier_key + ' ' + unique_data_Rules[k].key).trim() + + `] > \'` + + new TextDecoder().decode(unique_data_Rules[k].output) + + '\'\n' } } } @@ -1472,13 +1636,26 @@ export class KeylayoutToKmnConverter { //SECONDTEXT print // ToDo include condition again // if ((warn_text[1].indexOf("duplicate") < 0)) { - data += warn_text[1] + "+ [" + unique_data_Rules[k].modifier_deadkey + " " + unique_data_Rules[k].deadkey + "] > dk(C" + String(unique_data_Rules[k].id_deadkey) + ")\n" + data += warn_text[1] + + "+ [" + + (unique_data_Rules[k].modifier_deadkey + " " + unique_data_Rules[k].deadkey).trim() + + "] > dk(C" + + String(unique_data_Rules[k].id_deadkey) + + ")\n" // } // THIRDTEXT print OK // ToDo include condition again // if ((warn_text[2].indexOf("duplicate") < 0)) { - data += warn_text[2] + "dk(C" + String(unique_data_Rules[k].id_deadkey) + ") + [" + unique_data_Rules[k].modifier_key + " " + unique_data_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_data_Rules[k].output) + "\'\n" + data += + warn_text[2] + + "dk(C" + + (String(unique_data_Rules[k].id_deadkey) + ") + [" + unique_data_Rules[k].modifier_key).trim() + + " " + + unique_data_Rules[k].key + "] > \'" + + new TextDecoder().decode(unique_data_Rules[k].output) + + "\'\n" + data += "\n" // } } @@ -1498,19 +1675,39 @@ export class KeylayoutToKmnConverter { // ToDo include condition again // FIRSTTEXT print // if ((warn_text[0].indexOf("duplicate") < 0)) { - data += warn_text[0] + " [" + unique_data_Rules[k].modifier_prev_deadkey + " " + unique_data_Rules[k].prev_deadkey + "] > dk(A" + String(unique_data_Rules[k].id_prev_deadkey) + ")\n" + data += + warn_text[0] + + " [" + + (unique_data_Rules[k].modifier_prev_deadkey + " " + unique_data_Rules[k].prev_deadkey).trim() + + "] > dk(A" + + String(unique_data_Rules[k].id_prev_deadkey) + ")\n" // } // ToDo include condition again //SECONDTEXT print // if ((warn_text[1].indexOf("duplicate") < 0)) { - data += warn_text[1] + "dk(A" + String(unique_data_Rules[k].id_prev_deadkey) + ") + [" + unique_data_Rules[k].modifier_deadkey + " " + unique_data_Rules[k].deadkey + "] > dk(B" + String(unique_data_Rules[k].id_deadkey) + ")\n" + data += + warn_text[1] + + "dk(A" + + (String(unique_data_Rules[k].id_prev_deadkey) + ") + [" + unique_data_Rules[k].modifier_deadkey).trim() + + " " + + unique_data_Rules[k].deadkey + + "] > dk(B" + + String(unique_data_Rules[k].id_deadkey) + + ")\n" // } // ToDo include condition again // THIRDTEXT print OK // if ((warn_text[2].indexOf("duplicate") < 0)) { - data += warn_text[2] + "dk(B" + String(unique_data_Rules[k].id_deadkey) + ") + [" + unique_data_Rules[k].modifier_key + " " + unique_data_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_data_Rules[k].output) + "\'\n" + data += + warn_text[2] + "dk(B" + + (String(unique_data_Rules[k].id_deadkey) + ") + [" + unique_data_Rules[k].modifier_key).trim() + + " " + + unique_data_Rules[k].key + + "] > \'" + + new TextDecoder().decode(unique_data_Rules[k].output) + + "\'\n" // } // if ((warn_text[0].indexOf("duplicate") < 0) || (warn_text[1].indexOf("duplicate") < 0) || (warn_text[2].indexOf("duplicate") < 0)) { From f3f7155982d723aebc1912e8c8c1f350f5f8fe60 Mon Sep 17 00:00:00 2001 From: Sabine Date: Thu, 27 Feb 2025 16:31:52 +0100 Subject: [PATCH 059/251] feat(developer): start function comments and tests --- .../keylayout-to-kmn-converter.ts | 301 +++++++++++------- .../test/test-keylayout-to-kmn-converter.ts | 127 +++++++- 2 files changed, 309 insertions(+), 119 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index ac6b369b2fa..ee7b29e2d5e 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -74,12 +74,13 @@ import { ConverterToKmnArtifacts } from "../converter-artifacts.js"; // TODO need to use export const USVirtualKeyCodes here // replace unique_prev_deadkey 0, >0 with true, false // TODO what about using actions twice in a row??? -> error msg if chain >4 -// what if keylayout file is not correct e.g missing > +// what if keylayout file is not correct e.g missing '>' // read TODO which stores? // does order of modifier matter ? // remove all markers c0, 1-1, #### C2 ###, ... // better function names for get...... - +// use cmdl parameters +// check semocolon everywhere import { XMLParser } from 'fast-xml-parser'; // for reading an xml file import { readFileSync } from 'fs'; @@ -548,8 +549,9 @@ export class KeylayoutToKmnConverter { // -------------------------------------------------------------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------------------------------------------------------------- let unique_dkB_count = 0 - const list_of_unique_rules: string[][] = [] + const list_of_unique_Text2_rules: string[][] = [] + //this.writeDataset(object_array) //------------------------------------ C2: dk ---------------------------------- // first rule is always unique object_array[0].unique_deadkey = unique_dkB_count @@ -575,10 +577,12 @@ export class KeylayoutToKmnConverter { ruleArray.push(object_array[i].deadkey) ruleArray.push(String(unique_dkB_count)) unique_dkB_count++ - list_of_unique_rules.push(ruleArray) + list_of_unique_Text2_rules.push(ruleArray) } + } } + //console.log("list_of_unique_Text2_rules ", list_of_unique_Text2_rules) //----------------------------------- C3: prev-dk ---------------------------------- let unique_dkA_count = 0 @@ -603,9 +607,9 @@ export class KeylayoutToKmnConverter { if (isFirstUsedHere_prev_dk) { object_array[i].unique_prev_deadkey = unique_dkA_count unique_dkA_count++ - for (let k = 0; k < list_of_unique_rules.length; k++) { - if ((list_of_unique_rules[k][0] === object_array[i].modifier_deadkey) && ((list_of_unique_rules[k][1] === object_array[i].deadkey))) { - object_array[i].unique_deadkey = Number(list_of_unique_rules[k][2]) + for (let k = 0; k < list_of_unique_Text2_rules.length; k++) { + if ((list_of_unique_Text2_rules[k][0] === object_array[i].modifier_deadkey) && ((list_of_unique_Text2_rules[k][1] === object_array[i].deadkey))) { + object_array[i].unique_deadkey = Number(list_of_unique_Text2_rules[k][2]) } } } @@ -617,19 +621,21 @@ export class KeylayoutToKmnConverter { ruleArray.push(object_array[i].prev_deadkey) ruleArray.push(String(unique_dkB_count)) unique_dkB_count++ - list_of_unique_rules.push(ruleArray) + list_of_unique_Text2_rules.push(ruleArray) + } } } + //console.log("list_of_unique_Text2_rules ", list_of_unique_Text2_rules) - // loop through object_array and mark first occurence each rule of list_of_unique_rules + // loop through object_array and mark first occurence each rule of list_of_unique_Text2_rules for (let i = 0; i < object_array.length; i++) { - for (let j = 0; j < list_of_unique_rules.length; j++) { - if ((object_array[i].modifier_prev_deadkey === list_of_unique_rules[j][0]) && (object_array[i].prev_deadkey === list_of_unique_rules[j][1])) { - object_array[i].id_prev_deadkey = Number(list_of_unique_rules[j][2]) + for (let j = 0; j < list_of_unique_Text2_rules.length; j++) { + if ((object_array[i].modifier_prev_deadkey === list_of_unique_Text2_rules[j][0]) && (object_array[i].prev_deadkey === list_of_unique_Text2_rules[j][1])) { + object_array[i].id_prev_deadkey = Number(list_of_unique_Text2_rules[j][2]) } - if ((object_array[i].modifier_deadkey === list_of_unique_rules[j][0]) && (object_array[i].deadkey === list_of_unique_rules[j][1])) { - object_array[i].id_deadkey = Number(list_of_unique_rules[j][2]) + if ((object_array[i].modifier_deadkey === list_of_unique_Text2_rules[j][0]) && (object_array[i].deadkey === list_of_unique_Text2_rules[j][1])) { + object_array[i].id_deadkey = Number(list_of_unique_Text2_rules[j][2]) } } } @@ -640,12 +646,14 @@ export class KeylayoutToKmnConverter { // --------------------------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------------------------- - /* - in: Block 3 - b3_actionId a19 - out: Block 2 - b2_keyname_arr ['K_8', 'K_M] - do: create array of Array of Keycode eg: ['K_8', 'K_M] from an actionId a16 + + /** + * @brief loop through data, find the actionID and and return array of keymanes + * @param data :any - an object containing all data read from a .keylayout file + * @param search :string - an actionID + * @return a string[] of keynames */ - public get_KecCode_arr__From__ActionId(data: any, search: string): string[] { + /*public get_KecCode_arr__From__ActionId(data: any, search: string): string[] { const returnarray: string[] = [] for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { @@ -657,12 +665,14 @@ export class KeylayoutToKmnConverter { } } return returnarray - } - /* - in: Block 5 - b5_actionId_arr a16, a18 - out: Block 4 - b4_code_arr [ '6', '31', '32' ] - do: create array of keycodes from an array of keymapIndex - */ + }*/ + + /** + * @brief loop through data, find the actionID and and return array of keycodes + * @param data :any - an object containing all data read from a .keylayout file + * @param search :string[][] - array of [ actionID,state,output] + * @return a string[] of keycodes + */ public get_KeyMap_Code_array__From__KeyMap_Action(data: any, search: string[]): string[] { const returnarray: string[] = [] for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { @@ -676,11 +686,13 @@ export class KeylayoutToKmnConverter { } return returnarray } - /* - in: Block 6 - b6_actionId_arr [ 'a9','1','â'] - out: Block 1 - b1_keycode_arr ['49','K_SPACE','a0','0','Â'] - do: create array of ['49','K_SPACE','a0','0','Â'] from create array of [ 'a9','1','â'] - */ + + /** + * @brief loop through data, find the actionID in search and and return array of [Keycode,Keyname,actionId,actionIDIndex, output] + * @param data :any - an object containing all data read from a .keylayout file + * @param search :string[][] - array of [ actionID,state,output] + * @return a string[][] containing [Keycode,Keyname,actionId,actionIDIndex, output] + */ public get_KeyMap_Code_array__From__KeyMap_Action_array2D(data: any, search: string[][]): string[][] { const returnarray2D: string[][] = [] for (let k = 0; k < search.length; k++) { @@ -703,11 +715,13 @@ export class KeylayoutToKmnConverter { } return returnarray2D } - /* - in: action_id a19 - out: b1_actionIndex behav. 1 - do: get the actionIdIndex from action id a18 - */ + + /** + * @brief loop through data, find the actionID and return its index + * @param data :any - an object containing all data read from a .keylayout file + * @param search :string - value next to be found + * @return a number containing the index of an actionId + */ public get_ActionID_Index__From__ActionID_Id(data: any, search: string): number { for (let i = 0; i < data.keyboard.actions.action.length; i++) { if (data.keyboard.actions.action[i]['@_id'] === search) { @@ -717,11 +731,12 @@ export class KeylayoutToKmnConverter { return 0 } - /* - in: Block 5 - b5_value_state state = 3 - out: Block 3 - b3_actionId a19 - do: get the actionIdI from state / next -*/ + /** + * @brief loop through data, find the actionID of a certain state-next pair + * @param data :any an object containing all data read from a .keylayout file + * @param search :string value next to be found + * @return a string containing the actionId of a certain state-next pair + */ public get_ActionID_Id__From__ActionID_next(data: any, search: string): string { if (search !== "none") { for (let i = 0; i < data.keyboard.actions.action.length; i++) { @@ -734,11 +749,13 @@ export class KeylayoutToKmnConverter { } return "" } - /* - in: Block 5 - b5_value_next next = 1 - out: Block 6 - b6_actionId_arr 'a9','1','â'] - do: create array of [ 'a9','1','â'] from state / next -*/ + + /** + * @brief loop through data, find all actionId-output pairs for a certain state and store in an array + * @param data : any an object containing all data read from a .keylayout file + * @param search : string a state to be found + * @return an array: string[][] containing all [actionId, state, output] for a certain state + */ public get_ActionID_Output_array__From__ActionID_State(data: any, search: string) { const returnarray2D: string[][] = [] for (let i = 0; i < data.keyboard.actions.action.length; i++) { @@ -756,11 +773,13 @@ export class KeylayoutToKmnConverter { } return returnarray2D } - /* - in: Block 1 - action_id a18 - out: Block 6 - outputchar 'A' - do: create output Array from action_id -*/ + + /** + * @brief loop through data, find the output for a certain actionID for state none + * @param data :any an object containing all data read from a .keylayout file + * @param search :string an actionId to be found + * @return a string containing the output character + */ public get_Action2ID_NoneOutput__From__ActionID_Id(data: any, search: string): string { let OutputValue: string = "" @@ -775,11 +794,14 @@ export class KeylayoutToKmnConverter { } return OutputValue } - /* - in: Block 1 - b1_keycode_arr ['49','K_SPACE','a0','0','Â'] - out: Block 1 - b1_modifierKey_arr ['K_SPACE','a0','0','NCAPS','Â'] - do: create array of key+modi+out from array of b1_keycode_arr -*/ + + /** + * @brief loop through data and create an 2D array of [KeyName,actionId,behaviour,modifier,output] + * @param data : any an object containing all data read from a .keylayout file + * @param search : array of [keycode,keyname,actionId,behaviour,output] to be found + * @param isCAPSused : boolean flag to indicate if CAPS is used in a keylayout file or not + * @return an array: string[][] containing [KeyName,actionId,behaviour,modifier,output] + */ public get_KeyMapModiKeyArray__from__array(data: any, search: string[][], isCAPSused: boolean): string[][] { const returnarray: string[][] = [] @@ -789,7 +811,7 @@ export class KeylayoutToKmnConverter { for (let j = 0; j < data.keyboard.modifierMap.keyMapSelect[behaviour].modifier.length; j++) { const returnarray1D: string[] = [] returnarray1D.push(search[i][1]) /* KeyName*/ - returnarray1D.push(search[i][2]) /* action*/ + returnarray1D.push(search[i][2]) /* actionId*/ returnarray1D.push(search[i][3]) /* behaviour*/ returnarray1D.push(this.create_kmn_modifier(data.keyboard.modifierMap.keyMapSelect[behaviour].modifier[j]['@_keys'], isCAPSused)) /* modifier */ returnarray1D.push(search[i][4]) /* char*/ @@ -811,12 +833,16 @@ export class KeylayoutToKmnConverter { ); return unique_returnarray } - /* ?? - in: Block C1 - action_id a19 - in: Block C1 - out 'A' - out: Block C1 - b1_modifierKey_arr - do: create array of key+mod+out from array of b1_modifierKey_arr -*/ + + /** + * @brief loop through data and create an array of [actionID,output,actionID, behaviour,keyname,modifier] for a given actionId + * @param data : any - an object containing all data read from a .keylayout file + * @param modi : any - an array of modifiers + * @param search : string - an actionId to be found + * @param outchar : string - the output character + * @param isCAPSused : boolean - flag to indicate if CAPS is used in a keylayout file or not + * @return an array: string[][] containing [actionID,output,actionID, behaviour,keyname,modifier] + */ public get_Datat_array2D__From__ActionID_stateOutput(data: any, modi: any, search: string, outchar: string, isCapsused: boolean): string[][] { const returnarray2D: string[][] = [] @@ -858,11 +884,13 @@ export class KeylayoutToKmnConverter { return unique_returnarray } - /* - in: Block - action_id a19 - out: Block 4 - b4_deadkey_arr [['24', 0], ['24', 3]] - do: create array of [['24', 0], ['24', 3]] from behaviour id -*/ + + /** + * @brief loop through data and create an array of [keycode,modifier] for a given actionId + * @param data : any - an object containing all data read from a .keylayout file + * @param search : string - an actionId to be found + * @return an array: number[][] containing [keycode,modifier] + */ public get_KeyMap_Code_array__From__ActionID_Action(data: any, search: string): number[][] { const mapIndexArray_max: number[][] = [] for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { @@ -881,11 +909,13 @@ export class KeylayoutToKmnConverter { } return mapIndexArray_max } - /* - in: Block 4 - b4_deadkey_arr [['24', 0], ['24', 3]] - out: Block 4 - b4_deadkeyModifier_arr [['','caps?'], ['Caps']] - do: create array of from array of b4_deadkey_arr -*/ + + /** + * @brief loop through data and create an array of modifier behaviours for a given keycode in [keycode,modifier] + * @param data : any - an object containing all data read from a .keylayout file + * @param search : number[][] - an array[keycode,modifier] to be found + * @return an array: string[] containing behaviours + */ public get_KeyMap_Modifier_array__From__behaviour_arr(data: any, search: number[][]): string[] { const mapIndexArray_max: string[] = [] for (let i = 0; i < search.length; i++) { @@ -894,12 +924,12 @@ export class KeylayoutToKmnConverter { return mapIndexArray_max } - /** - * @brief member function to create a string of modifiers in kmn-style from the modifierMap section of .keylayout-file - * @param keylayout_modifier the modifier value used in the .keylayout-file - * @return kmn_modifier the modifier value used in the .kmn-file + /** + * @brief create a kmn modifier from a keylayout modifier + * @param keylayout_modifier :string - modifier used in a .keylayout file + * @param isCAPSused : boolean flag to indicate if CAPS is used in a keylayout file or not + * @return string - a modifier value suitable to use in a .kmn-file */ - //ToDo review lower part public create_kmn_modifier(keylayout_modifier: string, isCAPSused: boolean): string { let add_modifier: string = "" let kmn_modifier: string = "" @@ -945,13 +975,13 @@ export class KeylayoutToKmnConverter { add_modifier = "SHIFT "; } else if ((modifier_state[i].toUpperCase() === 'ANYCONTROL') || (modifier_state[i].toUpperCase() === 'CONTROL')) { - add_modifier = "RCTRL "; + add_modifier = "CTRL "; } else if ((modifier_state[i].toUpperCase() === "LEFTCONTROL") || (modifier_state[i].toUpperCase() === "LCONTROL")) { - add_modifier = "CTRL "; + add_modifier = "LCTRL "; } - else if ((modifier_state[i].toUpperCase() === "RIGHTCONTROL") || (modifier_state[i].toUpperCase() === "LCONTROL")) { - add_modifier = "CTRL "; + else if ((modifier_state[i].toUpperCase() === "RIGHTCONTROL") || (modifier_state[i].toUpperCase() === "RCONTROL")) { + add_modifier = "RCTRL "; } else if ((modifier_state[i].toUpperCase() === "LEFTOPTION") || (modifier_state[i].toUpperCase() === "LOPTION")) { add_modifier = "RALT "; @@ -976,10 +1006,22 @@ export class KeylayoutToKmnConverter { return unique_modifier.flat().toString().replace(/,/g, " ") } + /** + * @brief check if CAPS is used in a keylayout file or not + * @param keylayout_modifier the modifier value used in the .keylayout-file + * @return kmn_modifier the modifier value used in the .kmn-file + */ + // TODO caps <-> Caps <-> cAPs,... public checkIfCapsIsUsed(keylayout_modifier: string[][]): boolean { return JSON.stringify(keylayout_modifier).includes("caps") } + /** + * @brief check if CAPS is used in a keylayout file or not + * @param keylayout_modifier the modifier value used in the .keylayout-file + * @return true if a modifier can be used in keyman + * false if not + */ public isAcceptableKeymanModifier(keylayout_modifier: string): boolean { let iskKeymanModifier: boolean = true const modifier_single: string[] = keylayout_modifier.split(" "); @@ -1005,8 +1047,15 @@ export class KeylayoutToKmnConverter { return iskKeymanModifier } - // definition of comparisons 1-1, 2-4, 6-6,... see https://docs.google.com/document/d/12J3NGO6RxIthCpZDTR8FYSRjiMgXJDLwPY2z9xqKzJ0/edit?tab=t.0#heading=h.pcz8rjyrl5ug - // todo remove comments n filters after check of several keylayout files + /** + * @brief check rules for acceptable modifiers, duplicate or ambiguous rules and return an array containing possible warnings + * definition of comparisons e.g. 1-1, 2-4, 6-6 + * see https://docs.google.com/document/d/12J3NGO6RxIthCpZDTR8FYSRjiMgXJDLwPY2z9xqKzJ0/edit?tab=t.0#heading=h.pcz8rjyrl5ug + * @param rule : rule_object[] - an array of all rules + * @param index the index of a rule in array[rule] + * @return a string[] containing possible warnings for a rule + */ + // todo remove comments in filters after check of several keylayout files public reviewRules(rule: rule_object[], index: number): string[] { const warningTextArray: string[] = Array(3).fill(""); @@ -1218,7 +1267,7 @@ export class KeylayoutToKmnConverter { //&& (idx < index) ); - // 2-4 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(C1) + // 2-4 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(B11) const amb_2_4 = rule.filter((curr, idx) => ((curr.rule_type === "C2")) && curr.modifier_deadkey === rule[index].modifier_prev_deadkey @@ -1469,7 +1518,7 @@ export class KeylayoutToKmnConverter { public map_UkeleleKC_To_VK(pos: number): string { // ukelele KC --> // VK_US - if (pos === 0x0A) return "K_BKQUOTE" /* ^ */ + if (pos === 0x0A) return "K_BKQUOTE" /* ^ */ else if (pos === 0x12) return "K_1" /* 1 */ else if (pos === 0x13) return "K_2" /* 2 */ else if (pos === 0x14) return "K_3" /* 3 */ @@ -1530,6 +1579,12 @@ export class KeylayoutToKmnConverter { //---------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------- + + /** + * @brief member function to create a list of rule that will be printed to the resulting kmn file + * @param data_ukelele an object containing all data read from a .keylayout file + * @return string - a list of rules + */ public createData_Rules(data_ukelele: convert_object): string { let data: string = "" @@ -1572,7 +1627,7 @@ export class KeylayoutToKmnConverter { console.log("xx data_ukelele.arrayOf_Rules", data_ukelele.arrayOf_Rules.length) //console.log("xx data_ukelele.arrayOf_Rules", this.writeDataset(data_ukelele.arrayOf_Rules)) console.log("xx unique_data_Rules", unique_data_Rules.length) - console.log("xx unique_data_Rules", this.writeDataset(unique_data_Rules)) + //console.log("xx unique_data_Rules", this.writeDataset(unique_data_Rules)) //................................................ C0 C1 ................................................................ //................................................ C0 C1 ................................................................ @@ -1635,29 +1690,31 @@ export class KeylayoutToKmnConverter { //SECONDTEXT print // ToDo include condition again - // if ((warn_text[1].indexOf("duplicate") < 0)) { - data += warn_text[1] - + "+ [" - + (unique_data_Rules[k].modifier_deadkey + " " + unique_data_Rules[k].deadkey).trim() - + "] > dk(C" - + String(unique_data_Rules[k].id_deadkey) - + ")\n" - // } + if ((warn_text[1].indexOf("duplicate") < 0)) { + data += warn_text[1] + + "+ [" + + (unique_data_Rules[k].modifier_deadkey + " " + unique_data_Rules[k].deadkey).trim() + // + "] > dk(C" + + "] > dk(A" + + String(unique_data_Rules[k].id_deadkey) + + ")\n" + } // THIRDTEXT print OK // ToDo include condition again - // if ((warn_text[2].indexOf("duplicate") < 0)) { - data += - warn_text[2] - + "dk(C" - + (String(unique_data_Rules[k].id_deadkey) + ") + [" + unique_data_Rules[k].modifier_key).trim() - + " " - + unique_data_Rules[k].key + "] > \'" - + new TextDecoder().decode(unique_data_Rules[k].output) - + "\'\n" + if ((warn_text[2].indexOf("duplicate") < 0)) { + data += + warn_text[2] + // + "dk(C" + + "dk(A" + + (String(unique_data_Rules[k].id_deadkey) + ") + [" + unique_data_Rules[k].modifier_key).trim() + + " " + + unique_data_Rules[k].key + "] > \'" + + new TextDecoder().decode(unique_data_Rules[k].output) + + "\'\n" - data += "\n" - // } + data += "\n" + } } } @@ -1674,32 +1731,34 @@ export class KeylayoutToKmnConverter { // ToDo include condition again // FIRSTTEXT print - // if ((warn_text[0].indexOf("duplicate") < 0)) { + // if ((warn_text[0].indexOf("duplicate") < 0)) { data += warn_text[0] + " [" + (unique_data_Rules[k].modifier_prev_deadkey + " " + unique_data_Rules[k].prev_deadkey).trim() - + "] > dk(A" + //+ "] > dk(A" + + "] > dk(C" + String(unique_data_Rules[k].id_prev_deadkey) + ")\n" // } // ToDo include condition again //SECONDTEXT print - // if ((warn_text[1].indexOf("duplicate") < 0)) { + // if ((warn_text[1].indexOf("duplicate") < 0)) { data += warn_text[1] - + "dk(A" + //+ "dk(A" + + "dk(C" + (String(unique_data_Rules[k].id_prev_deadkey) + ") + [" + unique_data_Rules[k].modifier_deadkey).trim() + " " + unique_data_Rules[k].deadkey + "] > dk(B" + String(unique_data_Rules[k].id_deadkey) + ")\n" - // } + // } // ToDo include condition again // THIRDTEXT print OK - // if ((warn_text[2].indexOf("duplicate") < 0)) { + // if ((warn_text[2].indexOf("duplicate") < 0)) { data += warn_text[2] + "dk(B" + (String(unique_data_Rules[k].id_deadkey) + ") + [" + unique_data_Rules[k].modifier_key).trim() @@ -1708,7 +1767,7 @@ export class KeylayoutToKmnConverter { + "] > \'" + new TextDecoder().decode(unique_data_Rules[k].output) + "\'\n" - // } + // } // if ((warn_text[0].indexOf("duplicate") < 0) || (warn_text[1].indexOf("duplicate") < 0) || (warn_text[2].indexOf("duplicate") < 0)) { data += "\n" @@ -1720,7 +1779,11 @@ export class KeylayoutToKmnConverter { return data } - + /** + * @brief member function to create list of stores that will be printed to the resulting kmn file + * @param data_ukelele an object containing all data read from a .keylayout file + * @return string - a list of stores + */ public createData_Stores(data_ukelele: convert_object): string { let data: string = "" @@ -1760,9 +1823,10 @@ export class KeylayoutToKmnConverter { (dataRules[i].modifier_deadkey !== "" ? dataRules[i].modifier_deadkey.padEnd(30, " ") : "--".padEnd(30, " ")), (dataRules[i].deadkey !== "" ? dataRules[i].deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), - dataRules[i].rule_type === "C2" ? (dataRules[i].unique_deadkey !== 0 ? ("unique(C" + String(dataRules[i].unique_deadkey) + ")").padEnd(9, " ") : "--".padEnd(9, " ")) : ((dataRules[i].unique_prev_deadkey !== 0 ? ("unique(B" + ")").padEnd(9, " ") : "--".padEnd(9, " "))), - dataRules[i].id_deadkey, + dataRules[i].rule_type === "C2" ? (dataRules[i].unique_deadkey !== 0 ? ("unique(C" + String(dataRules[i].unique_deadkey) + ")").padEnd(9, " ") : "--".padEnd(9, " ")) : ((dataRules[i].unique_prev_deadkey !== 0 ? ("unique(B" + dataRules[i].id_deadkey + ")").padEnd(9, " ") : "--".padEnd(9, " "))), + dataRules[i].id_prev_deadkey, + dataRules[i].id_deadkey, "| ", (dataRules[i].modifier_key !== "" ? dataRules[i].modifier_key.padEnd(40, " ") : "--".padEnd(40, " ")), (dataRules[i].key !== "" ? dataRules[i].key.padEnd(8, " ") : "--".padEnd(8, " ")), @@ -1785,10 +1849,10 @@ export class KeylayoutToKmnConverter { (dataRules.modifier_deadkey !== "" ? dataRules.modifier_deadkey.padEnd(30, " ") : "--".padEnd(30, " ")), (dataRules.deadkey !== "" ? dataRules.deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), - dataRules.rule_type === "C2" ? (dataRules.unique_deadkey !== 0 ? ("unique(C" + String(dataRules.unique_deadkey) + ")").padEnd(9, " ") : "--".padEnd(9, " ")) : ((dataRules.unique_prev_deadkey !== 0 ? ("unique(B" + ")").padEnd(9, " ") : "--".padEnd(9, " "))), + dataRules.rule_type === "C2" ? (dataRules.unique_deadkey !== 0 ? ("unique(C" + String(dataRules.unique_deadkey) + ")").padEnd(9, " ") : "--".padEnd(9, " ")) : ((dataRules.unique_prev_deadkey !== 0 ? ("unique(B" + dataRules.id_deadkey + ")").padEnd(9, " ") : "--".padEnd(9, " "))), - dataRules.id_deadkey, dataRules.id_prev_deadkey, + dataRules.id_deadkey, "| ", (dataRules.modifier_key !== "" ? dataRules.modifier_key.padEnd(40, " ") : "--".padEnd(40, " ")), (dataRules.key !== "" ? dataRules.key.padEnd(8, " ") : "--".padEnd(8, " ")), @@ -1799,6 +1863,9 @@ export class KeylayoutToKmnConverter { } } +/** + * @brief class for all storing a rule containing data for key, deadkey, previous deadkey, output) + */ class Rules { constructor( public rule_type: string, /* C0, C1, C2, C3, or C4 */ diff --git a/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts index c33c4cc0a59..cd132151171 100644 --- a/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts @@ -10,9 +10,10 @@ import 'mocha'; import { assert } from 'chai'; import { compilerTestCallbacks, compilerTestOptions } from './helpers/index.js'; import { KeylayoutToKmnConverter } from '../src/keylayout-to-kmn/keylayout-to-kmn-converter.js'; - import { makePathToFixture } from './helpers/index.js'; // _S2 my imports + + describe('KeylayoutToKmnConverter', function () { before(function () { @@ -45,7 +46,7 @@ describe('KeylayoutToKmnConverter', function () { //const inputFilename = makePathToFixture('../data/US_complete.keylayout'); // OK //const inputFilename = makePathToFixture('../data/German_complete.keylayout'); // OK - const inputFilename = makePathToFixture('../data/Italian_copy.keylayout'); // OK + const inputFilename = makePathToFixture('../data/Italian_copy.keylayout'); // OK //const inputFilename = makePathToFixture('../data/German_Standard_copy.keylayout'); //OK //const inputFilename = makePathToFixture('../data/German_Standard2.keylayout'); //OK //const inputFilename = makePathToFixture('../data/German_StandardTweaked.keylayout'); //NO C3 @@ -73,5 +74,127 @@ describe('KeylayoutToKmnConverter', function () { } assert.isTrue(threw); }); + //------------------------ + + it('should should return empty array on null input', async function () { + const converter = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const result = converter.read(null); + assert.isEmpty(result); + }); + + it('should should return empty array on empty input', async function () { + const converter = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const result = converter.read(""); + assert.isEmpty(result); + }); + + it('should should return empty array on space as input', async function () { + const converter = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const result = converter.read(" "); + assert.isEmpty(result); + }); + + it('should should return filled array on correct input', async function () { + const inputFilename = makePathToFixture('../data/Italian_copy.keylayout'); + const converter = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const result = converter.read(inputFilename); + assert.isNotEmpty(result); + }); + + + // todo test read - wrong name, empty string, ok name + // todo test for all public func for all "return paths" + + //----------------- + + + describe("create kmn modifier ", function () { + [ + ["anycontrol", true, "NCAPS CTRL"], + ["shift?", true, "NCAPS"], + ["?", true, "NCAPS"], + ["?", false, ""], + ["caps", true, "CAPS"], + ["", true, "NCAPS"], + [" ", false, ""], + ["wrongModifierName", false, "wrongModifierName"], + ["shift", false, "SHIFT"], + ["shift command", true, "NCAPS SHIFT command"], + ["rshift", true, "NCAPS SHIFT"], + ["rshift", false, "SHIFT"], + ["rightshift", true, "NCAPS SHIFT"], + ["riGhtsHift", true, "NCAPS SHIFT"], + ["LEFTCONTROL", true, "NCAPS LCTRL"], + ["RCONTROL", true, "NCAPS RCTRL"], + ["leftoption", true, "NCAPS RALT"], + ["loption", true, "NCAPS RALT"], + ].forEach(function (values) { + + it('should convert "' + values[0] + '" to "' + values[2] + '"', async function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const result = sut.create_kmn_modifier(values[0] as string, values[1] as boolean); + assert.equal(result, values[2]); + }); + }) + }) + + describe("isAcceptableKeymanModifier ", function () { + [ + ["NCAPS", true], + ["NxCAPS", false], + ["SHIFT", true], + ["ALT", true], + ["RALT", true], + ["LALT", true], + ["CTRL", true], + ["LCTRL", true], + ["RCTRL", true], + ["", true], + ["LCTRL CAPS", true], + ["LCTRL X", false], + ].forEach(function (values) { + it( "'" + values[0] + "'" +' should return ' + values[1] , async function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const result = sut.isAcceptableKeymanModifier(values[0] as string); + assert.equal(result, values[1]); + }); + }) + }) + + describe("map_UkeleleKC_To_VK ", function () { + [ + [0x00, "K_A"], + [0x31, "K_SPACE"], + [0x18, "K_EQUAL"], + [0x10, "K_Y"], + [0x18, "K_EQUAL"], + [0x21, "K_LBRKT"], + [0x999, ""], + [-1, ""], + ].forEach(function (values) { + it( values[0] + ' should return ' + "'"+values[1] +"'", async function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const result = sut.map_UkeleleKC_To_VK(values[0] as number); + assert.equal(result, values[1]); + }); + }) + }) + + describe("checkIfCapsIsUsed ", function () { + + it('should return true', async function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const input: string[][] = [["caps", "xxx"], ["yyy"]] + const result = sut.checkIfCapsIsUsed(input); + assert.isTrue(result); + }); + + it('should return false', async function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const input: string[][] = [["zzz", "xxx"], ["yyy"]] + const result = sut.checkIfCapsIsUsed(input); + assert.isFalse(result); + }); + }) }); From 5ba3201eb543bd52791d568948f6995ec626e039 Mon Sep 17 00:00:00 2001 From: Sabine Date: Thu, 27 Feb 2025 17:14:56 +0100 Subject: [PATCH 060/251] feat(developer): untrack files (kmn and keylayout) --- developer/src/kmc-convert/data/MyResult.kmn | 691 -------------------- 1 file changed, 691 deletions(-) delete mode 100644 developer/src/kmc-convert/data/MyResult.kmn diff --git a/developer/src/kmc-convert/data/MyResult.kmn b/developer/src/kmc-convert/data/MyResult.kmn deleted file mode 100644 index 9d99c6180ae..00000000000 --- a/developer/src/kmc-convert/data/MyResult.kmn +++ /dev/null @@ -1,691 +0,0 @@ - -c -c Keyman keyboard generated by kmn-convert -c - -########## OK ################################################################# -store(&VERSION) '...' -store(&TARGETS) 'any' -store(&KEYBOARDVERSION) '...' -store(©RIGHT) '© 2024 SIL International -########## OK ################################################################# - -begin Unicode > use(main) - -group(main) using keys - -########## OK ################################################################# -Tipp: if K_? is replaced by undefined-> no enry in kmn_Key_Name=> add K_? there and it will be shown here -Tipp: keys that are marked with sction do not aoear in ukelele_Array_output->do not appear in kmn - - -0-(modif:3-0) + [NCAPS RALT K_A] > 'å' -0-(modif:4-0) + [SHIFT NCAPS RALT K_A] > 'Å' -0-(modif:5-0) + [CAPS RALT K_A] > 'Å' -0-(modif:6-0) + [NCAPS RALT K_A] > 'å' -0-(modif:7-0) + [NCAPS CTRL K_A] > '' -0-(modif:7-1) + [NCAPS RALT CTRL K_A] > '' - -1-(modif:0-0) + [NCAPS K_S] > 's' -1-(modif:0-1) + [NCAPS K_S] > 's' -1-(modif:1-0) + [SHIFT NCAPS K_S] > 'S' -1-(modif:1-1) + [RIGHTSHIFT NCAPS K_S] > 'S' -1-(modif:1-2) + [LEFTSHIFT NCAPS K_S] > 'S' -1-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_S] > 'S' -1-(modif:2-0) + [CAPS K_S] > 'S' -1-(modif:3-0) + [NCAPS RALT K_S] > 'ß' -1-(modif:4-0) + [SHIFT NCAPS RALT K_S] > '¯' -1-(modif:5-0) + [CAPS RALT K_S] > 'ß' -1-(modif:6-0) + [NCAPS RALT K_S] > 'ß' -1-(modif:7-0) + [NCAPS CTRL K_S] > '' -1-(modif:7-1) + [NCAPS RALT CTRL K_S] > '' - -2-(modif:0-0) + [NCAPS K_D] > 'd' -2-(modif:0-1) + [NCAPS K_D] > 'd' -2-(modif:1-0) + [SHIFT NCAPS K_D] > 'D' -2-(modif:1-1) + [RIGHTSHIFT NCAPS K_D] > 'D' -2-(modif:1-2) + [LEFTSHIFT NCAPS K_D] > 'D' -2-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_D] > 'D' -2-(modif:2-0) + [CAPS K_D] > 'D' -2-(modif:3-0) + [NCAPS RALT K_D] > '∂' -2-(modif:4-0) + [SHIFT NCAPS RALT K_D] > '˘' -2-(modif:5-0) + [CAPS RALT K_D] > '∂' -2-(modif:6-0) + [NCAPS RALT K_D] > '∂' -2-(modif:7-0) + [NCAPS CTRL K_D] > '' -2-(modif:7-1) + [NCAPS RALT CTRL K_D] > '' - -3-(modif:0-0) + [NCAPS K_F] > 'f' -3-(modif:0-1) + [NCAPS K_F] > 'f' -3-(modif:1-0) + [SHIFT NCAPS K_F] > 'F' -3-(modif:1-1) + [RIGHTSHIFT NCAPS K_F] > 'F' -3-(modif:1-2) + [LEFTSHIFT NCAPS K_F] > 'F' -3-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_F] > 'F' -3-(modif:2-0) + [CAPS K_F] > 'F' -3-(modif:3-0) + [NCAPS RALT K_F] > 'ƒ' -3-(modif:4-0) + [SHIFT NCAPS RALT K_F] > '˙' -3-(modif:5-0) + [CAPS RALT K_F] > 'ƒ' -3-(modif:6-0) + [NCAPS RALT K_F] > 'ƒ' -3-(modif:7-0) + [NCAPS CTRL K_F] > '' -3-(modif:7-1) + [NCAPS RALT CTRL K_F] > '' - -4-(modif:0-0) + [NCAPS K_H] > 'h' -4-(modif:0-1) + [NCAPS K_H] > 'h' -4-(modif:1-0) + [SHIFT NCAPS K_H] > 'H' -4-(modif:1-1) + [RIGHTSHIFT NCAPS K_H] > 'H' -4-(modif:1-2) + [LEFTSHIFT NCAPS K_H] > 'H' -4-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_H] > 'H' -4-(modif:2-0) + [CAPS K_H] > '@' -4-(modif:3-0) + [NCAPS RALT K_H] > '∆' -4-(modif:4-0) + [SHIFT NCAPS RALT K_H] > '¸' -4-(modif:5-0) + [CAPS RALT K_H] > '€' -4-(modif:6-0) + [NCAPS RALT K_H] > 'ẞ' -4-(modif:7-0) + [NCAPS CTRL K_H] > '' -4-(modif:7-1) + [NCAPS RALT CTRL K_H] > '' - -5-(modif:0-0) + [NCAPS K_G] > 'g' -5-(modif:0-1) + [NCAPS K_G] > 'g' -5-(modif:1-0) + [SHIFT NCAPS K_G] > 'G' -5-(modif:1-1) + [RIGHTSHIFT NCAPS K_G] > 'G' -5-(modif:1-2) + [LEFTSHIFT NCAPS K_G] > 'G' -5-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_G] > 'G' -5-(modif:2-0) + [CAPS K_G] > 'G' -5-(modif:3-0) + [NCAPS RALT K_G] > '∞' -5-(modif:4-0) + [SHIFT NCAPS RALT K_G] > '˚' -5-(modif:5-0) + [CAPS RALT K_G] > '∞' -5-(modif:6-0) + [NCAPS RALT K_G] > '∞' -5-(modif:7-0) + [NCAPS CTRL K_G] > '' -5-(modif:7-1) + [NCAPS RALT CTRL K_G] > '' - -6-(modif:0-0) + [NCAPS K_Z] > 'z' -6-(modif:0-1) + [NCAPS K_Z] > 'z' -6-(modif:1-0) + [SHIFT NCAPS K_Z] > 'Z' -6-(modif:1-1) + [RIGHTSHIFT NCAPS K_Z] > 'Z' -6-(modif:1-2) + [LEFTSHIFT NCAPS K_Z] > 'Z' -6-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_Z] > 'Z' -6-(modif:2-0) + [CAPS K_Z] > 'Z' -6-(modif:3-0) + [NCAPS RALT K_Z] > '∑' -6-(modif:5-0) + [CAPS RALT K_Z] > '∑' -6-(modif:6-0) + [NCAPS RALT K_Z] > '∑' -6-(modif:7-0) + [NCAPS CTRL K_Z] > '' -6-(modif:7-1) + [NCAPS RALT CTRL K_Z] > '' - -7-(modif:0-0) + [NCAPS K_X] > 'x' -7-(modif:0-1) + [NCAPS K_X] > 'x' -7-(modif:1-0) + [SHIFT NCAPS K_X] > 'X' -7-(modif:1-1) + [RIGHTSHIFT NCAPS K_X] > 'X' -7-(modif:1-2) + [LEFTSHIFT NCAPS K_X] > 'X' -7-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_X] > 'X' -7-(modif:2-0) + [CAPS K_X] > 'X' -7-(modif:3-0) + [NCAPS RALT K_X] > '†' -7-(modif:4-0) + [SHIFT NCAPS RALT K_X] > '‡' -7-(modif:5-0) + [CAPS RALT K_X] > '†' -7-(modif:6-0) + [NCAPS RALT K_X] > '†' -7-(modif:7-0) + [NCAPS CTRL K_X] > '' -7-(modif:7-1) + [NCAPS RALT CTRL K_X] > '' - -8-(modif:0-0) + [NCAPS K_C] > 'c' -8-(modif:0-1) + [NCAPS K_C] > 'c' -8-(modif:1-0) + [SHIFT NCAPS K_C] > 'C' -8-(modif:1-1) + [RIGHTSHIFT NCAPS K_C] > 'C' -8-(modif:1-2) + [LEFTSHIFT NCAPS K_C] > 'C' -8-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_C] > 'C' -8-(modif:2-0) + [CAPS K_C] > 'C' -8-(modif:3-0) + [NCAPS RALT K_C] > '©' -8-(modif:4-0) + [SHIFT NCAPS RALT K_C] > 'Á' -8-(modif:5-0) + [CAPS RALT K_C] > '©' -8-(modif:6-0) + [NCAPS RALT K_C] > '©' -8-(modif:7-0) + [NCAPS CTRL K_C] > '' -8-(modif:7-1) + [NCAPS RALT CTRL K_C] > '' - -9-(modif:0-0) + [NCAPS K_V] > 'v' -9-(modif:0-1) + [NCAPS K_V] > 'v' -9-(modif:1-0) + [SHIFT NCAPS K_V] > 'V' -9-(modif:1-1) + [RIGHTSHIFT NCAPS K_V] > 'V' -9-(modif:1-2) + [LEFTSHIFT NCAPS K_V] > 'V' -9-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_V] > 'V' -9-(modif:2-0) + [CAPS K_V] > 'V' -9-(modif:3-0) + [NCAPS RALT K_V] > '√' -9-(modif:4-0) + [SHIFT NCAPS RALT K_V] > 'É' -9-(modif:5-0) + [CAPS RALT K_V] > '√' -9-(modif:6-0) + [NCAPS RALT K_V] > '√' -9-(modif:7-0) + [NCAPS CTRL K_V] > '' -9-(modif:7-1) + [NCAPS RALT CTRL K_V] > '' - -10-(modif:0-0) + [NCAPS K_BKQUOTE] > '\' -10-(modif:0-1) + [NCAPS K_BKQUOTE] > '\' -10-(modif:1-0) + [SHIFT NCAPS K_BKQUOTE] > '|' -10-(modif:1-1) + [RIGHTSHIFT NCAPS K_BKQUOTE] > '|' -10-(modif:1-2) + [LEFTSHIFT NCAPS K_BKQUOTE] > '|' -10-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_BKQUOTE] > '|' -10-(modif:2-0) + [CAPS K_BKQUOTE] > '\' -10-(modif:3-0) + [NCAPS RALT K_BKQUOTE] > '`' -10-(modif:4-0) + [SHIFT NCAPS RALT K_BKQUOTE] > 'ı' -10-(modif:5-0) + [CAPS RALT K_BKQUOTE] > '`' -10-(modif:6-0) + [NCAPS RALT K_BKQUOTE] > '`' -10-(modif:7-0) + [NCAPS CTRL K_BKQUOTE] > '' -10-(modif:7-1) + [NCAPS RALT CTRL K_BKQUOTE] > '' - -11-(modif:0-0) + [NCAPS K_B] > 'b' -11-(modif:0-1) + [NCAPS K_B] > 'b' -11-(modif:1-0) + [SHIFT NCAPS K_B] > 'B' -11-(modif:1-1) + [RIGHTSHIFT NCAPS K_B] > 'B' -11-(modif:1-2) + [LEFTSHIFT NCAPS K_B] > 'B' -11-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_B] > 'B' -11-(modif:2-0) + [CAPS K_B] > 'B' -11-(modif:3-0) + [NCAPS RALT K_B] > '∫' -11-(modif:4-0) + [SHIFT NCAPS RALT K_B] > 'Í' -11-(modif:5-0) + [CAPS RALT K_B] > '∫' -11-(modif:6-0) + [NCAPS RALT K_B] > '∫' -11-(modif:7-0) + [NCAPS CTRL K_B] > '' -11-(modif:7-1) + [NCAPS RALT CTRL K_B] > '' - -12-(modif:0-0) + [NCAPS K_Q] > 'q' -12-(modif:0-1) + [NCAPS K_Q] > 'q' -12-(modif:1-0) + [SHIFT NCAPS K_Q] > 'Q' -12-(modif:1-1) + [RIGHTSHIFT NCAPS K_Q] > 'Q' -12-(modif:1-2) + [LEFTSHIFT NCAPS K_Q] > 'Q' -12-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_Q] > 'Q' -12-(modif:2-0) + [CAPS K_Q] > 'Q' -12-(modif:3-0) + [NCAPS RALT K_Q] > '„' -12-(modif:4-0) + [SHIFT NCAPS RALT K_Q] > '‚' -12-(modif:5-0) + [CAPS RALT K_Q] > '„' -12-(modif:6-0) + [NCAPS RALT K_Q] > '„' -12-(modif:7-0) + [NCAPS CTRL K_Q] > '' -12-(modif:7-1) + [NCAPS RALT CTRL K_Q] > '' - -13-(modif:0-0) + [NCAPS K_W] > 'w' -13-(modif:0-1) + [NCAPS K_W] > 'w' -13-(modif:1-0) + [SHIFT NCAPS K_W] > 'W' -13-(modif:1-1) + [RIGHTSHIFT NCAPS K_W] > 'W' -13-(modif:1-2) + [LEFTSHIFT NCAPS K_W] > 'W' -13-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_W] > 'W' -13-(modif:2-0) + [CAPS K_W] > 'W' -13-(modif:3-0) + [NCAPS RALT K_W] > 'Ω' -13-(modif:4-0) + [SHIFT NCAPS RALT K_W] > 'À' -13-(modif:5-0) + [CAPS RALT K_W] > 'Ω' -13-(modif:6-0) + [NCAPS RALT K_W] > 'Ω' -13-(modif:7-0) + [NCAPS CTRL K_W] > '' -13-(modif:7-1) + [NCAPS RALT CTRL K_W] > '' - -14-(modif:3-0) + [NCAPS RALT K_E] > '€' -14-(modif:4-0) + [SHIFT NCAPS RALT K_E] > 'È' -14-(modif:5-0) + [CAPS RALT K_E] > '€' -14-(modif:6-0) + [NCAPS RALT K_E] > '€' -14-(modif:7-0) + [NCAPS CTRL K_E] > '' -14-(modif:7-1) + [NCAPS RALT CTRL K_E] > '' - -15-(modif:0-0) + [NCAPS K_R] > 'r' -15-(modif:0-1) + [NCAPS K_R] > 'r' -15-(modif:1-0) + [SHIFT NCAPS K_R] > 'R' -15-(modif:1-1) + [RIGHTSHIFT NCAPS K_R] > 'R' -15-(modif:1-2) + [LEFTSHIFT NCAPS K_R] > 'R' -15-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_R] > 'R' -15-(modif:2-0) + [CAPS K_R] > 'R' -15-(modif:3-0) + [NCAPS RALT K_R] > '®' -15-(modif:4-0) + [SHIFT NCAPS RALT K_R] > 'Ì' -15-(modif:5-0) + [CAPS RALT K_R] > '®' -15-(modif:6-0) + [NCAPS RALT K_R] > '®' -15-(modif:7-0) + [NCAPS CTRL K_R] > '' -15-(modif:7-1) + [NCAPS RALT CTRL K_R] > '' - -16-(modif:3-0) + [NCAPS RALT K_Y] > 'æ' -16-(modif:4-0) + [SHIFT NCAPS RALT K_Y] > 'Æ' -16-(modif:5-0) + [CAPS RALT K_Y] > 'Æ' -16-(modif:6-0) + [NCAPS RALT K_Y] > 'æ' -16-(modif:7-0) + [NCAPS CTRL K_Y] > '' -16-(modif:7-1) + [NCAPS RALT CTRL K_Y] > '' - -17-(modif:0-0) + [NCAPS K_T] > 't' -17-(modif:0-1) + [NCAPS K_T] > 't' -17-(modif:1-0) + [SHIFT NCAPS K_T] > 'T' -17-(modif:1-1) + [RIGHTSHIFT NCAPS K_T] > 'T' -17-(modif:1-2) + [LEFTSHIFT NCAPS K_T] > 'T' -17-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_T] > 'T' -17-(modif:2-0) + [CAPS K_T] > 'T' -17-(modif:3-0) + [NCAPS RALT K_T] > '™' -17-(modif:4-0) + [SHIFT NCAPS RALT K_T] > 'Ò' -17-(modif:5-0) + [CAPS RALT K_T] > '™' -17-(modif:6-0) + [NCAPS RALT K_T] > '™' -17-(modif:7-0) + [NCAPS CTRL K_T] > '' -17-(modif:7-1) + [NCAPS RALT CTRL K_T] > '' - -18-(modif:0-0) + [NCAPS K_1] > '1' -18-(modif:0-1) + [NCAPS K_1] > '1' -18-(modif:1-0) + [SHIFT NCAPS K_1] > '!' -18-(modif:1-1) + [RIGHTSHIFT NCAPS K_1] > '!' -18-(modif:1-2) + [LEFTSHIFT NCAPS K_1] > '!' -18-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_1] > '!' -18-(modif:2-0) + [CAPS K_1] > '1' -18-(modif:3-0) + [NCAPS RALT K_1] > '«' -18-(modif:4-0) + [SHIFT NCAPS RALT K_1] > '»' -18-(modif:5-0) + [CAPS RALT K_1] > '«' -18-(modif:6-0) + [NCAPS RALT K_1] > '«' -18-(modif:7-0) + [NCAPS CTRL K_1] > '1' -18-(modif:7-1) + [NCAPS RALT CTRL K_1] > '1' - -19-(modif:0-0) + [NCAPS K_2] > '2' -19-(modif:0-1) + [NCAPS K_2] > '2' -19-(modif:1-0) + [SHIFT NCAPS K_2] > '"' -19-(modif:1-1) + [RIGHTSHIFT NCAPS K_2] > '"' -19-(modif:1-2) + [LEFTSHIFT NCAPS K_2] > '"' -19-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_2] > '"' -19-(modif:2-0) + [CAPS K_2] > '2' -19-(modif:3-0) + [NCAPS RALT K_2] > '“' -19-(modif:4-0) + [SHIFT NCAPS RALT K_2] > '”' -19-(modif:5-0) + [CAPS RALT K_2] > '“' -19-(modif:6-0) + [NCAPS RALT K_2] > '“' -19-(modif:7-0) + [NCAPS CTRL K_2] > '2' -19-(modif:7-1) + [NCAPS RALT CTRL K_2] > '2' - -20-(modif:0-0) + [NCAPS K_3] > '3' -20-(modif:0-1) + [NCAPS K_3] > '3' -20-(modif:1-0) + [SHIFT NCAPS K_3] > '£' -20-(modif:1-1) + [RIGHTSHIFT NCAPS K_3] > '£' -20-(modif:1-2) + [LEFTSHIFT NCAPS K_3] > '£' -20-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_3] > '£' -20-(modif:2-0) + [CAPS K_3] > '3' -20-(modif:3-0) + [NCAPS RALT K_3] > '‘' -20-(modif:4-0) + [SHIFT NCAPS RALT K_3] > '’' -20-(modif:5-0) + [CAPS RALT K_3] > '‘' -20-(modif:6-0) + [NCAPS RALT K_3] > '‘' -20-(modif:7-0) + [NCAPS CTRL K_3] > '3' -20-(modif:7-1) + [NCAPS RALT CTRL K_3] > '3' - -21-(modif:0-0) + [NCAPS K_4] > '4' -21-(modif:0-1) + [NCAPS K_4] > '4' -21-(modif:1-0) + [SHIFT NCAPS K_4] > '$' -21-(modif:1-1) + [RIGHTSHIFT NCAPS K_4] > '$' -21-(modif:1-2) + [LEFTSHIFT NCAPS K_4] > '$' -21-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_4] > '$' -21-(modif:2-0) + [CAPS K_4] > '4' -21-(modif:3-0) + [NCAPS RALT K_4] > '¥' -21-(modif:4-0) + [SHIFT NCAPS RALT K_4] > '¢' -21-(modif:5-0) + [CAPS RALT K_4] > '¥' -21-(modif:6-0) + [NCAPS RALT K_4] > '¥' -21-(modif:7-0) + [NCAPS CTRL K_4] > '4' -21-(modif:7-1) + [NCAPS RALT CTRL K_4] > '4' - -22-(modif:0-0) + [NCAPS K_6] > '6' -22-(modif:0-1) + [NCAPS K_6] > '6' -22-(modif:1-0) + [SHIFT NCAPS K_6] > '&' -22-(modif:1-1) + [RIGHTSHIFT NCAPS K_6] > '&' -22-(modif:1-2) + [LEFTSHIFT NCAPS K_6] > '&' -22-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_6] > '&' -22-(modif:2-0) + [CAPS K_6] > '6' -22-(modif:3-0) + [NCAPS RALT K_6] > '‹' -22-(modif:4-0) + [SHIFT NCAPS RALT K_6] > '›' -22-(modif:5-0) + [CAPS RALT K_6] > '‹' -22-(modif:6-0) + [NCAPS RALT K_6] > '‹' -22-(modif:7-0) + [NCAPS CTRL K_6] > '6' -22-(modif:7-1) + [NCAPS RALT CTRL K_6] > '6' - -23-(modif:0-0) + [NCAPS K_5] > '5' -23-(modif:0-1) + [NCAPS K_5] > '5' -23-(modif:1-0) + [SHIFT NCAPS K_5] > '%' -23-(modif:1-1) + [RIGHTSHIFT NCAPS K_5] > '%' -23-(modif:1-2) + [LEFTSHIFT NCAPS K_5] > '%' -23-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_5] > '%' -23-(modif:2-0) + [CAPS K_5] > '5' -23-(modif:3-0) + [NCAPS RALT K_5] > '~' -23-(modif:4-0) + [SHIFT NCAPS RALT K_5] > '‰' -23-(modif:5-0) + [CAPS RALT K_5] > '~' -23-(modif:6-0) + [NCAPS RALT K_5] > '~' -23-(modif:7-0) + [NCAPS CTRL K_5] > '5' -23-(modif:7-1) + [NCAPS RALT CTRL K_5] > '5' - -24-(modif:1-0) + [SHIFT NCAPS K_EQUAL] > '^' -24-(modif:1-1) + [RIGHTSHIFT NCAPS K_EQUAL] > '^' -24-(modif:1-2) + [LEFTSHIFT NCAPS K_EQUAL] > '^' -24-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_EQUAL] > '^' -24-(modif:2-0) + [CAPS K_EQUAL] > 'ì' -24-(modif:4-0) + [SHIFT NCAPS RALT K_EQUAL] > '±' -24-(modif:5-0) + [CAPS RALT K_EQUAL] > 'ˆ' -24-(modif:6-0) + [NCAPS RALT K_EQUAL] > 'ˆ' -24-(modif:7-0) + [NCAPS CTRL K_EQUAL] > '=' -24-(modif:7-1) + [NCAPS RALT CTRL K_EQUAL] > '=' - -25-(modif:0-0) + [NCAPS K_9] > '9' -25-(modif:0-1) + [NCAPS K_9] > '9' -25-(modif:1-0) + [SHIFT NCAPS K_9] > ')' -25-(modif:1-1) + [RIGHTSHIFT NCAPS K_9] > ')' -25-(modif:1-2) + [LEFTSHIFT NCAPS K_9] > ')' -25-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_9] > ')' -25-(modif:2-0) + [CAPS K_9] > '9' -25-(modif:5-0) + [CAPS RALT K_9] > '`' -25-(modif:6-0) + [NCAPS RALT K_9] > '`' -25-(modif:7-0) + [NCAPS CTRL K_9] > '9' -25-(modif:7-1) + [NCAPS RALT CTRL K_9] > '9' - -26-(modif:0-0) + [NCAPS K_7] > '7' -26-(modif:0-1) + [NCAPS K_7] > '7' -26-(modif:1-0) + [SHIFT NCAPS K_7] > '/' -26-(modif:1-1) + [RIGHTSHIFT NCAPS K_7] > '/' -26-(modif:1-2) + [LEFTSHIFT NCAPS K_7] > '/' -26-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_7] > '/' -26-(modif:2-0) + [CAPS K_7] > '7' -26-(modif:3-0) + [NCAPS RALT K_7] > '÷' -26-(modif:4-0) + [SHIFT NCAPS RALT K_7] > '⁄' -26-(modif:5-0) + [CAPS RALT K_7] > '÷' -26-(modif:6-0) + [NCAPS RALT K_7] > '÷' -26-(modif:7-0) + [NCAPS CTRL K_7] > '7' -26-(modif:7-1) + [NCAPS RALT CTRL K_7] > '7' - -27-(modif:0-0) + [NCAPS K_HYPHEN] > ''' -27-(modif:0-1) + [NCAPS K_HYPHEN] > ''' -27-(modif:1-0) + [SHIFT NCAPS K_HYPHEN] > '?' -27-(modif:1-1) + [RIGHTSHIFT NCAPS K_HYPHEN] > '?' -27-(modif:1-2) + [LEFTSHIFT NCAPS K_HYPHEN] > '?' -27-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_HYPHEN] > '?' -27-(modif:2-0) + [CAPS K_HYPHEN] > ''' -27-(modif:3-0) + [NCAPS RALT K_HYPHEN] > '¡' -27-(modif:4-0) + [SHIFT NCAPS RALT K_HYPHEN] > '¿' -27-(modif:5-0) + [CAPS RALT K_HYPHEN] > '¡' -27-(modif:6-0) + [NCAPS RALT K_HYPHEN] > '¡' -27-(modif:7-0) + [NCAPS CTRL K_HYPHEN] > '' -27-(modif:7-1) + [NCAPS RALT CTRL K_HYPHEN] > '' - -28-(modif:0-0) + [NCAPS K_8] > '8' -28-(modif:0-1) + [NCAPS K_8] > '8' -28-(modif:1-0) + [SHIFT NCAPS K_8] > '(' -28-(modif:1-1) + [RIGHTSHIFT NCAPS K_8] > '(' -28-(modif:1-2) + [LEFTSHIFT NCAPS K_8] > '(' -28-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_8] > '(' -28-(modif:2-0) + [CAPS K_8] > '8' -28-(modif:4-0) + [SHIFT NCAPS RALT K_8] > '' -28-(modif:5-0) + [CAPS RALT K_8] > '´' -28-(modif:6-0) + [NCAPS RALT K_8] > '´' -28-(modif:7-0) + [NCAPS CTRL K_8] > '8' -28-(modif:7-1) + [NCAPS RALT CTRL K_8] > '8' - -29-(modif:0-0) + [NCAPS K_0] > '0' -29-(modif:0-1) + [NCAPS K_0] > '0' -29-(modif:1-0) + [SHIFT NCAPS K_0] > '=' -29-(modif:1-1) + [RIGHTSHIFT NCAPS K_0] > '=' -29-(modif:1-2) + [LEFTSHIFT NCAPS K_0] > '=' -29-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_0] > '=' -29-(modif:2-0) + [CAPS K_0] > '0' -29-(modif:3-0) + [NCAPS RALT K_0] > '≠' -29-(modif:4-0) + [SHIFT NCAPS RALT K_0] > '≈' -29-(modif:5-0) + [CAPS RALT K_0] > '≠' -29-(modif:6-0) + [NCAPS RALT K_0] > '≠' -29-(modif:7-0) + [NCAPS CTRL K_0] > '0' -29-(modif:7-1) + [NCAPS RALT CTRL K_0] > '0' - -30-(modif:0-0) + [NCAPS K_RBRKT] > '+' -30-(modif:0-1) + [NCAPS K_RBRKT] > '+' -30-(modif:1-0) + [SHIFT NCAPS K_RBRKT] > '*' -30-(modif:1-1) + [RIGHTSHIFT NCAPS K_RBRKT] > '*' -30-(modif:1-2) + [LEFTSHIFT NCAPS K_RBRKT] > '*' -30-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_RBRKT] > '*' -30-(modif:2-0) + [CAPS K_RBRKT] > '+' -30-(modif:3-0) + [NCAPS RALT K_RBRKT] > ']' -30-(modif:4-0) + [SHIFT NCAPS RALT K_RBRKT] > '}' -30-(modif:5-0) + [CAPS RALT K_RBRKT] > ']' -30-(modif:6-0) + [NCAPS RALT K_RBRKT] > ']' -30-(modif:7-0) + [NCAPS CTRL K_RBRKT] > '' -30-(modif:7-1) + [NCAPS RALT CTRL K_RBRKT] > '' - -31-(modif:3-0) + [NCAPS RALT K_O] > 'ø' -31-(modif:4-0) + [SHIFT NCAPS RALT K_O] > 'Ø' -31-(modif:5-0) + [CAPS RALT K_O] > 'Ø' -31-(modif:6-0) + [NCAPS RALT K_O] > 'ø' -31-(modif:7-0) + [NCAPS CTRL K_O] > '' -31-(modif:7-1) + [NCAPS RALT CTRL K_O] > '' - -32-(modif:4-0) + [SHIFT NCAPS RALT K_U] > 'Ù' -32-(modif:5-0) + [CAPS RALT K_U] > '¨' -32-(modif:6-0) + [NCAPS RALT K_U] > '¨' -32-(modif:7-0) + [NCAPS CTRL K_U] > '' -32-(modif:7-1) + [NCAPS RALT CTRL K_U] > '' - -33-(modif:0-0) + [NCAPS K_LBRKT] > 'è' -33-(modif:0-1) + [NCAPS K_LBRKT] > 'è' -33-(modif:1-0) + [SHIFT NCAPS K_LBRKT] > 'é' -33-(modif:1-1) + [RIGHTSHIFT NCAPS K_LBRKT] > 'é' -33-(modif:1-2) + [LEFTSHIFT NCAPS K_LBRKT] > 'é' -33-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_LBRKT] > 'é' -33-(modif:2-0) + [CAPS K_LBRKT] > 'è' -33-(modif:3-0) + [NCAPS RALT K_LBRKT] > '[' -33-(modif:4-0) + [SHIFT NCAPS RALT K_LBRKT] > '{' -33-(modif:5-0) + [CAPS RALT K_LBRKT] > '[' -33-(modif:6-0) + [NCAPS RALT K_LBRKT] > '[' -33-(modif:7-0) + [NCAPS CTRL K_LBRKT] > '' -33-(modif:7-1) + [NCAPS RALT CTRL K_LBRKT] > '' - -34-(modif:3-0) + [NCAPS RALT K_I] > 'œ' -34-(modif:4-0) + [SHIFT NCAPS RALT K_I] > 'Œ' -34-(modif:5-0) + [CAPS RALT K_I] > 'Œ' -34-(modif:6-0) + [NCAPS RALT K_I] > 'œ' -34-(modif:7-0) + [NCAPS CTRL K_I] > ' ' -34-(modif:7-1) + [NCAPS RALT CTRL K_I] > ' ' - -35-(modif:0-0) + [NCAPS K_P] > 'p' -35-(modif:0-1) + [NCAPS K_P] > 'p' -35-(modif:1-0) + [SHIFT NCAPS K_P] > 'P' -35-(modif:1-1) + [RIGHTSHIFT NCAPS K_P] > 'P' -35-(modif:1-2) + [LEFTSHIFT NCAPS K_P] > 'P' -35-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_P] > 'P' -35-(modif:2-0) + [CAPS K_P] > 'P' -35-(modif:3-0) + [NCAPS RALT K_P] > 'π' -35-(modif:4-0) + [SHIFT NCAPS RALT K_P] > '∏' -35-(modif:5-0) + [CAPS RALT K_P] > '∏' -35-(modif:6-0) + [NCAPS RALT K_P] > 'π' -35-(modif:7-0) + [NCAPS CTRL K_P] > '' -35-(modif:7-1) + [NCAPS RALT CTRL K_P] > '' - -36-(modif:0-0) + [NCAPS K_ENTER] > ' ' -36-(modif:0-1) + [NCAPS K_ENTER] > ' ' -36-(modif:1-0) + [SHIFT NCAPS K_ENTER] > ' ' -36-(modif:1-1) + [RIGHTSHIFT NCAPS K_ENTER] > ' ' -36-(modif:1-2) + [LEFTSHIFT NCAPS K_ENTER] > ' ' -36-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_ENTER] > ' ' -36-(modif:2-0) + [CAPS K_ENTER] > ' ' -36-(modif:3-0) + [NCAPS RALT K_ENTER] > ' ' -36-(modif:4-0) + [SHIFT NCAPS RALT K_ENTER] > ' ' -36-(modif:5-0) + [CAPS RALT K_ENTER] > ' ' -36-(modif:6-0) + [NCAPS RALT K_ENTER] > ' ' -36-(modif:7-0) + [NCAPS CTRL K_ENTER] > ' ' -36-(modif:7-1) + [NCAPS RALT CTRL K_ENTER] > ' ' - -37-(modif:0-0) + [NCAPS K_L] > 'l' -37-(modif:0-1) + [NCAPS K_L] > 'l' -37-(modif:1-0) + [SHIFT NCAPS K_L] > 'L' -37-(modif:1-1) + [RIGHTSHIFT NCAPS K_L] > 'L' -37-(modif:1-2) + [LEFTSHIFT NCAPS K_L] > 'L' -37-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_L] > 'L' -37-(modif:2-0) + [CAPS K_L] > 'L' -37-(modif:3-0) + [NCAPS RALT K_L] > '¬' -37-(modif:4-0) + [SHIFT NCAPS RALT K_L] > 'ˇ' -37-(modif:5-0) + [CAPS RALT K_L] > '¬' -37-(modif:6-0) + [NCAPS RALT K_L] > '¬' -37-(modif:7-0) + [NCAPS CTRL K_L] > ' ' -37-(modif:7-1) + [NCAPS RALT CTRL K_L] > ' ' - -38-(modif:0-0) + [NCAPS K_J] > 'j' -38-(modif:0-1) + [NCAPS K_J] > 'j' -38-(modif:1-0) + [SHIFT NCAPS K_J] > 'J' -38-(modif:1-1) + [RIGHTSHIFT NCAPS K_J] > 'J' -38-(modif:1-2) + [LEFTSHIFT NCAPS K_J] > 'J' -38-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_J] > 'J' -38-(modif:2-0) + [CAPS K_J] > 'J' -38-(modif:3-0) + [NCAPS RALT K_J] > 'ª' -38-(modif:4-0) + [SHIFT NCAPS RALT K_J] > '˝' -38-(modif:5-0) + [CAPS RALT K_J] > 'ª' -38-(modif:6-0) + [NCAPS RALT K_J] > 'ª' -38-(modif:7-0) + [NCAPS CTRL K_J] > ' ' -38-(modif:7-1) + [NCAPS RALT CTRL K_J] > ' ' - -39-(modif:0-0) + [NCAPS K_QUOTE] > 'à' -39-(modif:0-1) + [NCAPS K_QUOTE] > 'à' -39-(modif:1-0) + [SHIFT NCAPS K_QUOTE] > '°' -39-(modif:1-1) + [RIGHTSHIFT NCAPS K_QUOTE] > '°' -39-(modif:1-2) + [LEFTSHIFT NCAPS K_QUOTE] > '°' -39-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_QUOTE] > '°' -39-(modif:2-0) + [CAPS K_QUOTE] > 'à' -39-(modif:3-0) + [NCAPS RALT K_QUOTE] > '#' -39-(modif:4-0) + [SHIFT NCAPS RALT K_QUOTE] > '∞' -39-(modif:5-0) + [CAPS RALT K_QUOTE] > '#' -39-(modif:6-0) + [NCAPS RALT K_QUOTE] > '#' -39-(modif:7-0) + [NCAPS CTRL K_QUOTE] > '%' -39-(modif:7-1) + [NCAPS RALT CTRL K_QUOTE] > '%' - -40-(modif:0-0) + [NCAPS K_K] > 'k' -40-(modif:0-1) + [NCAPS K_K] > 'k' -40-(modif:1-0) + [SHIFT NCAPS K_K] > 'K' -40-(modif:1-1) + [RIGHTSHIFT NCAPS K_K] > 'K' -40-(modif:1-2) + [LEFTSHIFT NCAPS K_K] > 'K' -40-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_K] > 'K' -40-(modif:2-0) + [CAPS K_K] > 'K' -40-(modif:3-0) + [NCAPS RALT K_K] > 'º' -40-(modif:4-0) + [SHIFT NCAPS RALT K_K] > '˛' -40-(modif:5-0) + [CAPS RALT K_K] > 'º' -40-(modif:6-0) + [NCAPS RALT K_K] > 'º' -40-(modif:7-0) + [NCAPS CTRL K_K] > ' ' -40-(modif:7-1) + [NCAPS RALT CTRL K_K] > ' ' - -41-(modif:0-0) + [NCAPS K_COLON] > 'ò' -41-(modif:0-1) + [NCAPS K_COLON] > 'ò' -41-(modif:1-0) + [SHIFT NCAPS K_COLON] > 'ç' -41-(modif:1-1) + [RIGHTSHIFT NCAPS K_COLON] > 'ç' -41-(modif:1-2) + [LEFTSHIFT NCAPS K_COLON] > 'ç' -41-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_COLON] > 'ç' -41-(modif:2-0) + [CAPS K_COLON] > 'ò' -41-(modif:3-0) + [NCAPS RALT K_COLON] > '@' -41-(modif:4-0) + [SHIFT NCAPS RALT K_COLON] > 'Ç' -41-(modif:5-0) + [CAPS RALT K_COLON] > '@' -41-(modif:6-0) + [NCAPS RALT K_COLON] > '@' -41-(modif:7-0) + [NCAPS CTRL K_COLON] > ' ' -41-(modif:7-1) + [NCAPS RALT CTRL K_COLON] > ' ' - -42-(modif:0-0) + [NCAPS K_BKSLASH] > 'ù' -42-(modif:0-1) + [NCAPS K_BKSLASH] > 'ù' -42-(modif:1-0) + [SHIFT NCAPS K_BKSLASH] > '§' -42-(modif:1-1) + [RIGHTSHIFT NCAPS K_BKSLASH] > '§' -42-(modif:1-2) + [LEFTSHIFT NCAPS K_BKSLASH] > '§' -42-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_BKSLASH] > '§' -42-(modif:2-0) + [CAPS K_BKSLASH] > 'ù' -42-(modif:3-0) + [NCAPS RALT K_BKSLASH] > '¶' -42-(modif:4-0) + [SHIFT NCAPS RALT K_BKSLASH] > '◊' -42-(modif:5-0) + [CAPS RALT K_BKSLASH] > '¶' -42-(modif:6-0) + [NCAPS RALT K_BKSLASH] > '¶' -42-(modif:7-0) + [NCAPS CTRL K_BKSLASH] > '°' -42-(modif:7-1) + [NCAPS RALT CTRL K_BKSLASH] > '°' - -43-(modif:0-0) + [NCAPS K_COMMA] > ',' -43-(modif:0-1) + [NCAPS K_COMMA] > ',' -43-(modif:1-0) + [SHIFT NCAPS K_COMMA] > ';' -43-(modif:1-1) + [RIGHTSHIFT NCAPS K_COMMA] > ';' -43-(modif:1-2) + [LEFTSHIFT NCAPS K_COMMA] > ';' -43-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_COMMA] > ';' -43-(modif:2-0) + [CAPS K_COMMA] > ',' -43-(modif:3-0) + [NCAPS RALT K_COMMA] > '…' -43-(modif:5-0) + [CAPS RALT K_COMMA] > '…' -43-(modif:6-0) + [NCAPS RALT K_COMMA] > '…' -43-(modif:7-0) + [NCAPS CTRL K_COMMA] > '.' -43-(modif:7-1) + [NCAPS RALT CTRL K_COMMA] > '.' - -44-(modif:0-0) + [NCAPS K_SLASH] > '-' -44-(modif:0-1) + [NCAPS K_SLASH] > '-' -44-(modif:1-0) + [SHIFT NCAPS K_SLASH] > '_' -44-(modif:1-1) + [RIGHTSHIFT NCAPS K_SLASH] > '_' -44-(modif:1-2) + [LEFTSHIFT NCAPS K_SLASH] > '_' -44-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_SLASH] > '_' -44-(modif:2-0) + [CAPS K_SLASH] > '-' -44-(modif:3-0) + [NCAPS RALT K_SLASH] > '–' -44-(modif:4-0) + [SHIFT NCAPS RALT K_SLASH] > '—' -44-(modif:5-0) + [CAPS RALT K_SLASH] > '–' -44-(modif:6-0) + [NCAPS RALT K_SLASH] > '–' -44-(modif:7-0) + [NCAPS CTRL K_SLASH] > '!' -44-(modif:7-1) + [NCAPS RALT CTRL K_SLASH] > '!' - -45-(modif:4-0) + [SHIFT NCAPS RALT K_N] > 'Ó' -45-(modif:5-0) + [CAPS RALT K_N] > '˜' -45-(modif:6-0) + [NCAPS RALT K_N] > '˜' -45-(modif:7-0) + [NCAPS CTRL K_N] > '' -45-(modif:7-1) + [NCAPS RALT CTRL K_N] > '' - -46-(modif:0-0) + [NCAPS K_M] > 'm' -46-(modif:0-1) + [NCAPS K_M] > 'm' -46-(modif:1-0) + [SHIFT NCAPS K_M] > 'M' -46-(modif:1-1) + [RIGHTSHIFT NCAPS K_M] > 'M' -46-(modif:1-2) + [LEFTSHIFT NCAPS K_M] > 'M' -46-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_M] > 'M' -46-(modif:2-0) + [CAPS K_M] > 'M' -46-(modif:3-0) + [NCAPS RALT K_M] > 'µ' -46-(modif:4-0) + [SHIFT NCAPS RALT K_M] > 'Ú' -46-(modif:5-0) + [CAPS RALT K_M] > 'µ' -46-(modif:6-0) + [NCAPS RALT K_M] > 'µ' -46-(modif:7-0) + [NCAPS CTRL K_M] > '?' -46-(modif:7-1) + [NCAPS RALT CTRL K_M] > '?' - -47-(modif:0-0) + [NCAPS K_PERIOD] > '.' -47-(modif:0-1) + [NCAPS K_PERIOD] > '.' -47-(modif:1-0) + [SHIFT NCAPS K_PERIOD] > ':' -47-(modif:1-1) + [RIGHTSHIFT NCAPS K_PERIOD] > ':' -47-(modif:1-2) + [LEFTSHIFT NCAPS K_PERIOD] > ':' -47-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_PERIOD] > ':' -47-(modif:2-0) + [CAPS K_PERIOD] > '.' -47-(modif:3-0) + [NCAPS RALT K_PERIOD] > '•' -47-(modif:4-0) + [SHIFT NCAPS RALT K_PERIOD] > '·' -47-(modif:5-0) + [CAPS RALT K_PERIOD] > '•' -47-(modif:6-0) + [NCAPS RALT K_PERIOD] > '•' -47-(modif:7-0) + [NCAPS CTRL K_PERIOD] > '/' -47-(modif:7-1) + [NCAPS RALT CTRL K_PERIOD] > '/' - -48-(modif:0-0) + [NCAPS K_BKSLASH] > ' ' -48-(modif:0-1) + [NCAPS K_BKSLASH] > ' ' -48-(modif:1-0) + [SHIFT NCAPS K_BKSLASH] > ' ' -48-(modif:1-1) + [RIGHTSHIFT NCAPS K_BKSLASH] > ' ' -48-(modif:1-2) + [LEFTSHIFT NCAPS K_BKSLASH] > ' ' -48-(modif:1-3) + [SHIFT LEFTSHIFT CAPS K_BKSLASH] > ' ' -48-(modif:2-0) + [CAPS K_BKSLASH] > ' ' -48-(modif:3-0) + [NCAPS RALT K_BKSLASH] > ' ' -48-(modif:4-0) + [SHIFT NCAPS RALT K_BKSLASH] > ' ' -48-(modif:5-0) + [CAPS RALT K_BKSLASH] > ' ' -48-(modif:6-0) + [NCAPS RALT K_BKSLASH] > ' ' -48-(modif:7-0) + [NCAPS CTRL K_BKSLASH] > ' ' -48-(modif:7-1) + [NCAPS RALT CTRL K_BKSLASH] > ' ' - -########## OK ################################################################# - -NOW MY C4 RULES **ccc ********* (only to get 02C6 ect) ********************* - -+ [NCAPS K_EQUAL] > dk(02C6) -+ [NCAPS RALT K_EQUAL] > dk(02C6) -+ [NCAPS RALT K_9] > dk(0060) -+ [NCAPS RALT K_8] > dk(00B4) -+ [NCAPS RALT K_U] > dk(00A8) -+ [NCAPS RALT K_N] > dk(02DC) - -########## OK ################################################################# - -match > use(deadkeys) - - -group(deadkeys) - - - -dk: 02C6 -deadkeyablesArray'a' 'A' 'e' 'E' 'o' 'O' 'u' 'U' 'i' 'I' -deadkeyedArray 'â' 'Â' 'ê' 'Ê' 'ô' 'Ô' 'û' 'Û' 'î' 'Î' - -dk: 02C6 -deadkeyablesArray'a' 'A' 'e' 'E' 'o' 'O' 'u' 'U' 'i' 'I' -deadkeyedArray 'â' 'Â' 'ê' 'Ê' 'ô' 'Ô' 'û' 'Û' 'î' 'Î' - -dk: 0060 -deadkeyablesArray'a' 'A' 'e' 'E' 'o' 'O' 'u' 'U' 'i' 'I' -deadkeyedArray 'à' 'À' 'è' 'È' 'ò' 'Ò' 'ù' 'Ù' 'ì' 'Ì' - -dk: 00B4 -deadkeyablesArray'a' 'A' 'e' 'E' 'o' 'O' 'u' 'U' 'i' 'I' -deadkeyedArray 'á' 'Á' 'é' 'É' 'ó' 'Ó' 'ú' 'Ú' 'í' 'Í' - -dk: 00A8 -deadkeyablesArray'a' 'A' 'e' 'E' 'y' 'Y' 'o' 'O' 'u' 'U' 'i' 'I' -deadkeyedArray 'ä' 'Ä' 'ë' 'Ë' 'ÿ' 'Ÿ' 'ö' 'Ö' 'ü' 'Ü' 'ï' 'Ï' - -dk: 02DC -deadkeyablesArray'a' 'A' 'o' 'O' 'n' 'N' -deadkeyedArray 'ã' 'Ã' 'õ' 'Õ' 'ñ' 'Ñ' From a2c592e335f273a57cad74128e6147117b3992dd Mon Sep 17 00:00:00 2001 From: Sabine Date: Wed, 5 Mar 2025 08:05:16 +0100 Subject: [PATCH 061/251] feat(developer): small changes in src due to new tests --- .../keylayout-to-kmn-converter.ts | 252 +++++++++--------- 1 file changed, 129 insertions(+), 123 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index ee7b29e2d5e..8b633d462cb 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -63,6 +63,7 @@ import { ConverterToKmnArtifacts } from "../converter-artifacts.js"; // OK check for keys < 50 whern working with keys // OK NO OUTPUT FOR SPACE in C0C1 !!! // OK check code for code styles keyman +// check (string |number) <-> number // tests for 3 functions read write convert // Return conditions // Tests throws @@ -80,7 +81,30 @@ import { ConverterToKmnArtifacts } from "../converter-artifacts.js"; // remove all markers c0, 1-1, #### C2 ###, ... // better function names for get...... // use cmdl parameters -// check semocolon everywhere +// check semicolon everywhere +// OK test run +// OK test read +// OK test convert +// OK test write +// test createRuleData +// OK test get_KeyMap_Code_array__From__KeyMap_Action +// OK test get_KeyMap_Code_array__From__KeyMap_Action_array2D +// OK test get_ActionID_Index__From__ActionID_Id +// OK test get_ActionID_Id__From__ActionID_next +// OK test get_ActionID_Output_array__From__ActionID_State +// OK test get_Action2ID_NoneOutput__From__ActionID_Id +// OK test get_KeyMapModiKeyArray__from__array +// OK test get_Datat_array2D__From__ActionID_stateOutput +// OK test get_KeyMap_Code_array__From__ActionID_Action +// OK test get_KeyMap_Modifier_array__From__behaviour_arr +// OK test create_kmn_modifier +// OK test checkIfCapsIsUsed +// OK test isAcceptableKeymanModifier +// test reviewRules +// OK test map_UkeleleKC_To_VK +// test writeData_Rules +// OK test createData_Stores +// what if nodes in keylayout file do not exist/ diff name keyboard <-> keyboardA import { XMLParser } from 'fast-xml-parser'; // for reading an xml file import { readFileSync } from 'fs'; @@ -220,29 +244,34 @@ export class KeylayoutToKmnConverter { const modifierBehavior: string[][] = [] // modifier for each keymapselect const rule_object: rule_object[] = [] // an array of objects which hold data for a kmn rule - const jsonObj_any: any = jsonObj - const keylayout_file: string = jsonObj_any.keyboard['@_name'] + ".keylayout" const data_object: convert_object = { - keylayout_filename: keylayout_file, - arrayOf_Modifiers: modifierBehavior, // ukelele uses behaviours e.g. 18 modifiersCombinations in 8 KeyMapSelect(behaviors) - arrayOf_Rules: rule_object + keylayout_filename: "", + arrayOf_Modifiers: [], + arrayOf_Rules: [] }; - // create an array of modifier combinations (e.g. shift? leftShift caps? ) and store in data_object - for (let j = 0; j < jsonObj.keyboard.modifierMap.keyMapSelect.length; j++) { - const singleModifierSet: string[] = [] - for (let k = 0; k < jsonObj.keyboard.modifierMap.keyMapSelect[j].modifier.length; k++) { - singleModifierSet.push(jsonObj.keyboard.modifierMap.keyMapSelect[j].modifier[k]['@_keys']) + if (jsonObj_any.hasOwnProperty("keyboard")) { + + data_object.keylayout_filename = jsonObj_any.keyboard['@_name'] + ".keylayout" + data_object.arrayOf_Modifiers = modifierBehavior // ukelele uses behaviours e.g. 18 modifiersCombinations in 8 KeyMapSelect(behaviors) + data_object.arrayOf_Rules = rule_object + + // create an array of modifier combinations (e.g. shift? leftShift caps? ) and store in data_object + for (let j = 0; j < jsonObj.keyboard.modifierMap.keyMapSelect.length; j++) { + const singleModifierSet: string[] = [] + for (let k = 0; k < jsonObj.keyboard.modifierMap.keyMapSelect[j].modifier.length; k++) { + singleModifierSet.push(jsonObj.keyboard.modifierMap.keyMapSelect[j].modifier[k]['@_keys']) + } + modifierBehavior.push(singleModifierSet) } - modifierBehavior.push(singleModifierSet) + // fill rules into arrayOf_Rules of data_object + return this.createRuleData(data_object, jsonObj) } - // fill rules into arrayOf_Rules of data_object - return this.createRuleData(data_object, jsonObj) + return data_object } - /** * @brief member function to write data fro object to file * @param data_ukelele the array holding keyboard data @@ -257,7 +286,7 @@ export class KeylayoutToKmnConverter { data += this.createData_Stores(data_ukelele) // add bottom part of kmn file: RULES - data += this.createData_Rules(data_ukelele) + data += this.writeData_Rules(data_ukelele) this.callbacks.fs.writeFileSync("data/MyResult.kmn", new TextEncoder().encode(data)) @@ -367,6 +396,8 @@ export class KeylayoutToKmnConverter { /* key */ b1_modifierKey_arr[m][4], /* output */ new TextEncoder().encode(outputchar) ) + // ToDo "undefined" or undefined ???? + // if (b1_modifierKey_arr[n4][4] !== "undefined") { object_array.push(rule_obj) } } @@ -437,7 +468,9 @@ export class KeylayoutToKmnConverter { /* key */ b1_modifierKey_arr[n4][0], /* output */ new TextEncoder().encode(b1_modifierKey_arr[n4][4]), ) - if (b1_modifierKey_arr[n4][4] !== undefined) { + // ToDo "undefined" or undefined ???? + if (b1_modifierKey_arr[n4][4] !== "undefined") { + //if (b1_modifierKey_arr[n4][4] !== undefined) { object_array.push(rule_obj) } } @@ -473,7 +506,7 @@ export class KeylayoutToKmnConverter { // Data of Block Nr 4 ........................................................................................................................................................................ // with present action_id (a16) find all keycode-behaviour-pairs that use this action (a16) => (keymapIndex 3/keycode 32) .................................................................... // from these create an array of modifier combinations e.g. [ [ 'anyOption', 'Caps' ] ] ..................................................................................................... - /* e.g. [['32', 3]] */ const b4_deadkey_arr: number[][] = this.get_KeyMap_Code_array__From__ActionID_Action(jsonObj, String(action_id)) + /* e.g. [['32', 3]] */ const b4_deadkey_arr: number[][] = this.get_KeyMap_Code_array__From__ActionID_Action(jsonObj, action_id) /* e.g. [ [ 'anyOption', 'Caps' ] ]*/ const b4_deadkeyModifier_arr: string[] = this.get_KeyMap_Modifier_array__From__behaviour_arr(data_ukelele.arrayOf_Modifiers, b4_deadkey_arr) // ........................................................................................................................................................................................... @@ -485,13 +518,12 @@ export class KeylayoutToKmnConverter { // Data of Block Nr 2 ....................................................................................................................................................................... // with present action_id (a17) find all keynames and behaviours that use this action (a17) => (keymapIndex 3/keycode 28) .................................................................... // from these create an array of modifier combinations e.g. [ [ 'anyOption', 'Caps' ] ] ..................................................................................................... - /* eg: index=3 */ const b2_prev_deadkey_arr: number[][] = this.get_KeyMap_Code_array__From__ActionID_Action(jsonObj, String(b3_actionId)) + /* eg: index=3 */ const b2_prev_deadkey_arr: number[][] = this.get_KeyMap_Code_array__From__ActionID_Action(jsonObj, String(b3_actionId)) // concersion not neccessary /* e.g. [ [ 'anyOption', 'Caps' ] ] */ const b2_prev_deadkeyModifier_arr: string[] = this.get_KeyMap_Modifier_array__From__behaviour_arr(data_ukelele.arrayOf_Modifiers, b2_prev_deadkey_arr) // ........................................................................................................................................................................................... - // Data of Block Nr 6 ........................................................................................................................................................................ // create an array[action id,state,output] from all state-output-pairs that use state = b5_value_next (e.g. use 1 in ) ......................................... - /* eg: [ 'a9','1','â'] */ const b6_actionId_arr: string[][] = this.get_ActionID_Output_array__From__ActionID_State(jsonObj, b5_value_next) + /* eg:[ [ 'a9','1','â'] ]*/ const b6_actionId_arr: string[][] = this.get_ActionID_Output_array__From__ActionID_State(jsonObj, b5_value_next) // ........................................................................................................................................................................................... // Data of Block Nr 1 ....................................................................................................................................................................... @@ -524,6 +556,8 @@ export class KeylayoutToKmnConverter { /* key */ b1_modifierKey_arr[n7][0], /* output */ new TextEncoder().encode(b1_modifierKey_arr[n7][4]), ) + + // ToDo "undefined" or undefined ???? if (b1_modifierKey_arr[n7][4] !== undefined) { object_array.push(rule_obj) } @@ -647,46 +681,6 @@ export class KeylayoutToKmnConverter { // --------------------------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------------------------- - /** - * @brief loop through data, find the actionID and and return array of keymanes - * @param data :any - an object containing all data read from a .keylayout file - * @param search :string - an actionID - * @return a string[] of keynames - */ - /*public get_KecCode_arr__From__ActionId(data: any, search: string): string[] { - const returnarray: string[] = [] - for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { - for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { - if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search - && data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'] < KeylayoutToKmnConverter.USED_KEYS_COUNT) { - returnarray.push(this.map_UkeleleKC_To_VK(Number(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']))) - - } - } - } - return returnarray - }*/ - - /** - * @brief loop through data, find the actionID and and return array of keycodes - * @param data :any - an object containing all data read from a .keylayout file - * @param search :string[][] - array of [ actionID,state,output] - * @return a string[] of keycodes - */ - public get_KeyMap_Code_array__From__KeyMap_Action(data: any, search: string[]): string[] { - const returnarray: string[] = [] - for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { - for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { - if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search - && data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'] < KeylayoutToKmnConverter.USED_KEYS_COUNT) { - returnarray.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']) - - } - } - } - return returnarray - } - /** * @brief loop through data, find the actionID in search and and return array of [Keycode,Keyname,actionId,actionIDIndex, output] * @param data :any - an object containing all data read from a .keylayout file @@ -694,6 +688,7 @@ export class KeylayoutToKmnConverter { * @return a string[][] containing [Keycode,Keyname,actionId,actionIDIndex, output] */ public get_KeyMap_Code_array__From__KeyMap_Action_array2D(data: any, search: string[][]): string[][] { + const returnarray2D: string[][] = [] for (let k = 0; k < search.length; k++) { for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { @@ -756,8 +751,9 @@ export class KeylayoutToKmnConverter { * @param search : string a state to be found * @return an array: string[][] containing all [actionId, state, output] for a certain state */ - public get_ActionID_Output_array__From__ActionID_State(data: any, search: string) { + public get_ActionID_Output_array__From__ActionID_State(data: any, search: string): string[][] { const returnarray2D: string[][] = [] + for (let i = 0; i < data.keyboard.actions.action.length; i++) { for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { const returnarray: string[] = [] @@ -802,7 +798,7 @@ export class KeylayoutToKmnConverter { * @param isCAPSused : boolean flag to indicate if CAPS is used in a keylayout file or not * @return an array: string[][] containing [KeyName,actionId,behaviour,modifier,output] */ - public get_KeyMapModiKeyArray__from__array(data: any, search: string[][], isCAPSused: boolean): string[][] { + public get_KeyMapModiKeyArray__from__array(data: any, search: (boolean | string)[][], isCAPSused: boolean): string[][] { const returnarray: string[][] = [] for (let i = 0; i < search.length; i++) { @@ -810,11 +806,11 @@ export class KeylayoutToKmnConverter { for (let j = 0; j < data.keyboard.modifierMap.keyMapSelect[behaviour].modifier.length; j++) { const returnarray1D: string[] = [] - returnarray1D.push(search[i][1]) /* KeyName*/ - returnarray1D.push(search[i][2]) /* actionId*/ - returnarray1D.push(search[i][3]) /* behaviour*/ - returnarray1D.push(this.create_kmn_modifier(data.keyboard.modifierMap.keyMapSelect[behaviour].modifier[j]['@_keys'], isCAPSused)) /* modifier */ - returnarray1D.push(search[i][4]) /* char*/ + returnarray1D.push(String(search[i][1])) /* KeyName*/ + returnarray1D.push(String(search[i][2])) /* actionId*/ + returnarray1D.push(String(search[i][3])) /* behaviour*/ + returnarray1D.push(String(this.create_kmn_modifier(data.keyboard.modifierMap.keyMapSelect[behaviour].modifier[j]['@_keys'], isCAPSused))) /* modifier */ + returnarray1D.push(String(search[i][4])) /* char*/ if (returnarray1D.length > 0) { returnarray.push(returnarray1D) } @@ -846,6 +842,10 @@ export class KeylayoutToKmnConverter { public get_Datat_array2D__From__ActionID_stateOutput(data: any, modi: any, search: string, outchar: string, isCapsused: boolean): string[][] { const returnarray2D: string[][] = [] + if ((search === "") || (search === undefined) || !((isCapsused === true) || (isCapsused === false))) { + return [] + } + // loop behaviors ( in ukelele it is possible to define multiple modifier combinations that behave in the same) for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { for (let j = 0; j < KeylayoutToKmnConverter.USED_KEYS_COUNT; j++) { @@ -892,36 +892,34 @@ export class KeylayoutToKmnConverter { * @return an array: number[][] containing [keycode,modifier] */ public get_KeyMap_Code_array__From__ActionID_Action(data: any, search: string): number[][] { - const mapIndexArray_max: number[][] = [] + const mapIndexArray_2D: number[][] = [] for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { for (let j = 0; j < KeylayoutToKmnConverter.USED_KEYS_COUNT; j++) { - const mapIndexArrayperKey: number[] = [] - if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { mapIndexArrayperKey.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']) mapIndexArrayperKey.push(i) } if (mapIndexArrayperKey.length > 0) { - mapIndexArray_max.push(mapIndexArrayperKey) + mapIndexArray_2D.push(mapIndexArrayperKey) } } } - return mapIndexArray_max + return mapIndexArray_2D } /** * @brief loop through data and create an array of modifier behaviours for a given keycode in [keycode,modifier] * @param data : any - an object containing all data read from a .keylayout file * @param search : number[][] - an array[keycode,modifier] to be found - * @return an array: string[] containing behaviours + * @return an array: string[] containing modifiers */ - public get_KeyMap_Modifier_array__From__behaviour_arr(data: any, search: number[][]): string[] { - const mapIndexArray_max: string[] = [] + public get_KeyMap_Modifier_array__From__behaviour_arr(data: any, search: (string | number)[][]): string[] { + const mapIndexArray_2D: string[] = [] for (let i = 0; i < search.length; i++) { - mapIndexArray_max.push(data[search[i][1]]) + mapIndexArray_2D.push(data[search[i][1]]) } - return mapIndexArray_max + return mapIndexArray_2D } /** @@ -1023,6 +1021,9 @@ export class KeylayoutToKmnConverter { * false if not */ public isAcceptableKeymanModifier(keylayout_modifier: string): boolean { + if (keylayout_modifier === null) + return false + let iskKeymanModifier: boolean = true const modifier_single: string[] = keylayout_modifier.split(" "); @@ -1585,20 +1586,16 @@ export class KeylayoutToKmnConverter { * @param data_ukelele an object containing all data read from a .keylayout file * @return string - a list of rules */ - public createData_Rules(data_ukelele: convert_object): string { + public writeData_Rules(data_ukelele: convert_object): string { let data: string = "" - // create array of all rules and remove duplicates - const data_rules: rule_object[] = data_ukelele.arrayOf_Rules.filter((curr) => { - if ((curr.output !== new TextEncoder().encode("") || curr.output !== undefined) - && (curr.rule_type === "C0") || (curr.rule_type === "C1") || (curr.rule_type === "C2") || (curr.rule_type === "C3")) { - return curr; - } else { - return "" - } - }); - const unique_data_Rules: rule_object[] = data_rules.reduce((unique, o) => { + // filter array of all rules and remove duplicates + + const unique_data_Rules: rule_object[] = data_ukelele.arrayOf_Rules.filter((curr) => { + return ((curr.output !== new TextEncoder().encode("") || curr.output !== undefined) + && (curr.rule_type === "C0") || (curr.rule_type === "C1") || (curr.rule_type === "C2") || (curr.rule_type === "C3")) + }).reduce((unique, o) => { if (!unique.some((obj: { modifier_prev_deadkey: string; prev_deadkey: string; modifier_deadkey: string; deadkey: string; @@ -1624,9 +1621,9 @@ export class KeylayoutToKmnConverter { // ToDo remove //const unique_data_Rules: rule_object[] = data_ukelele.arrayOf_Rules - console.log("xx data_ukelele.arrayOf_Rules", data_ukelele.arrayOf_Rules.length) + //console.log("xx data_ukelele.arrayOf_Rules", data_ukelele.arrayOf_Rules.length) //console.log("xx data_ukelele.arrayOf_Rules", this.writeDataset(data_ukelele.arrayOf_Rules)) - console.log("xx unique_data_Rules", unique_data_Rules.length) + // console.log("xx unique_data_Rules", unique_data_Rules.length) //console.log("xx unique_data_Rules", this.writeDataset(unique_data_Rules)) //................................................ C0 C1 ................................................................ @@ -1728,46 +1725,55 @@ export class KeylayoutToKmnConverter { if (unique_data_Rules[k].rule_type === "C3") { const warn_text = this.reviewRules(unique_data_Rules, k) - + // Todo somewhere (A12) <-> (C12) // ToDo include condition again // FIRSTTEXT print - // if ((warn_text[0].indexOf("duplicate") < 0)) { - data += - warn_text[0] - + " [" - + (unique_data_Rules[k].modifier_prev_deadkey + " " + unique_data_Rules[k].prev_deadkey).trim() - //+ "] > dk(A" - + "] > dk(C" - + String(unique_data_Rules[k].id_prev_deadkey) + ")\n" - // } + if ((warn_text[0].indexOf("duplicate") < 0) + || ((warn_text[0].indexOf("duplicate") >= 0) && (warn_text[0].indexOf("ambiguous") >= 0)) + || ((warn_text[0].indexOf("duplicate") >= 0) && (warn_text[0].indexOf("unavailable") >= 0)) + ) { + data += + warn_text[0] + + " [" + + (unique_data_Rules[k].modifier_prev_deadkey + " " + unique_data_Rules[k].prev_deadkey).trim() + //+ "] > dk(A" + + "] > dk(C" + + String(unique_data_Rules[k].id_prev_deadkey) + ")\n" + } // ToDo include condition again //SECONDTEXT print - // if ((warn_text[1].indexOf("duplicate") < 0)) { - data += - warn_text[1] - //+ "dk(A" - + "dk(C" - + (String(unique_data_Rules[k].id_prev_deadkey) + ") + [" + unique_data_Rules[k].modifier_deadkey).trim() - + " " - + unique_data_Rules[k].deadkey - + "] > dk(B" - + String(unique_data_Rules[k].id_deadkey) - + ")\n" - // } + if ((warn_text[1].indexOf("duplicate") < 0) + || ((warn_text[1].indexOf("duplicate") >= 0) && (warn_text[1].indexOf("ambiguous") >= 0)) + || ((warn_text[1].indexOf("duplicate") >= 0) && (warn_text[1].indexOf("unavailable") >= 0)) + ) { + data += + warn_text[1] + //+ "dk(A" + + "dk(C" + + (String(unique_data_Rules[k].id_prev_deadkey) + ") + [" + unique_data_Rules[k].modifier_deadkey).trim() + + " " + + unique_data_Rules[k].deadkey + + "] > dk(B" + + String(unique_data_Rules[k].id_deadkey) + + ")\n" + } // ToDo include condition again // THIRDTEXT print OK - // if ((warn_text[2].indexOf("duplicate") < 0)) { - data += - warn_text[2] + "dk(B" - + (String(unique_data_Rules[k].id_deadkey) + ") + [" + unique_data_Rules[k].modifier_key).trim() - + " " - + unique_data_Rules[k].key - + "] > \'" - + new TextDecoder().decode(unique_data_Rules[k].output) - + "\'\n" - // } + if ((warn_text[2].indexOf("duplicate") < 0) + || ((warn_text[2].indexOf("duplicate") >= 0) && (warn_text[2].indexOf("ambiguous") >= 0)) + || ((warn_text[2].indexOf("duplicate") >= 0) && (warn_text[2].indexOf("unavailable") >= 0)) + ) { + data += + warn_text[2] + "dk(B" + + (String(unique_data_Rules[k].id_deadkey) + ") + [" + unique_data_Rules[k].modifier_key).trim() + + " " + + unique_data_Rules[k].key + + "] > \'" + + new TextDecoder().decode(unique_data_Rules[k].output) + + "\'\n" + } // if ((warn_text[0].indexOf("duplicate") < 0) || (warn_text[1].indexOf("duplicate") < 0) || (warn_text[2].indexOf("duplicate") < 0)) { data += "\n" From 3bbbc91531871b09b1699b4d8836336444389fed Mon Sep 17 00:00:00 2001 From: Sabine Date: Wed, 5 Mar 2025 18:36:10 +0100 Subject: [PATCH 062/251] feat(developer): tests for kmc-convert --- .../keylayout-to-kmn-converter.ts | 35 +- .../test/test-keylayout-to-kmn-converter.ts | 776 +++++++++++++++--- 2 files changed, 699 insertions(+), 112 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 8b633d462cb..1987f0d3038 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -103,8 +103,9 @@ import { ConverterToKmnArtifacts } from "../converter-artifacts.js"; // test reviewRules // OK test map_UkeleleKC_To_VK // test writeData_Rules -// OK test createData_Stores +// OK test writeData_Stores // what if nodes in keylayout file do not exist/ diff name keyboard <-> keyboardA +// separate createRuleData and check for duplicates/amb rules import { XMLParser } from 'fast-xml-parser'; // for reading an xml file import { readFileSync } from 'fs'; @@ -183,6 +184,7 @@ export class KeylayoutToKmnConverter { const jsonO: object = this.read(inputFilename) if (!jsonO) { + throw new Error('read() not OK'); // new SAB return null; } @@ -190,6 +192,7 @@ export class KeylayoutToKmnConverter { const outArray: convert_object = await this.convert(jsonO); if (!outArray) { + throw new Error('convert() not OK'); // new SAB return null; } @@ -197,12 +200,14 @@ export class KeylayoutToKmnConverter { const out_text: boolean = this.write(outArray) if (!out_text) { + throw new Error('write() not OK'); // new SAB return null; } // TODO throws console.log(';;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; FINISHED OK ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;'); - throw new Error('Not finished yet'); + //throw new Error('Not finished yet'); // new SAB + return null // new SAB } /** @@ -235,7 +240,8 @@ export class KeylayoutToKmnConverter { /** - * @brief member function to convert data of .keylayout-file to kmn-file This will convert/rename modifiers, position of Keys and deadkeys and save into an array + * @brief member function to convert data of .keylayout-file to kmn-file. This will convert/rename modifiers, position of Keys and deadkeys and save into an array + * if no tags are provided an empty data_object will be returned * @param take data_ukelele and create a mapping from mac Keycodes to key-names and save to data_ukelele object * @param data_ukelele (Uint8Array) data of the ukelele .keylayout-file * @return outArray Uint8Array keys_all_Layers, the converted data for kmn-files if all layers have been converted; else null @@ -282,20 +288,24 @@ export class KeylayoutToKmnConverter { let data: string = "\n" + // TODO use path also + // const savename = "data//" + data_ukelele.keylayout_filename.substring(0, data_ukelele.keylayout_filename.lastIndexOf(".")) + ".kmn" + // add top part of kmn file: STORES - data += this.createData_Stores(data_ukelele) + data += this.writeData_Stores(data_ukelele) // add bottom part of kmn file: RULES data += this.writeData_Rules(data_ukelele) - this.callbacks.fs.writeFileSync("data/MyResult.kmn", new TextEncoder().encode(data)) - - // ToDo conditions? - if (data.length > 0) { + try { + this.callbacks.fs.writeFileSync("data/MyResult.kmn", new TextEncoder().encode(data)) + //this.callbacks.fs.writeFileSync(savename, new TextEncoder().encode(data)) return true; - } else { + } catch (err) { + console.log('Error writing kmn file:' + err.message) return false } + } // TODO move outside of class? @@ -616,7 +626,6 @@ export class KeylayoutToKmnConverter { } } - //console.log("list_of_unique_Text2_rules ", list_of_unique_Text2_rules) //----------------------------------- C3: prev-dk ---------------------------------- let unique_dkA_count = 0 @@ -660,7 +669,6 @@ export class KeylayoutToKmnConverter { } } } - //console.log("list_of_unique_Text2_rules ", list_of_unique_Text2_rules) // loop through object_array and mark first occurence each rule of list_of_unique_Text2_rules for (let i = 0; i < object_array.length; i++) { @@ -689,6 +697,9 @@ export class KeylayoutToKmnConverter { */ public get_KeyMap_Code_array__From__KeyMap_Action_array2D(data: any, search: string[][]): string[][] { + if ((search === undefined) || (search === null)) + return [] + const returnarray2D: string[][] = [] for (let k = 0; k < search.length; k++) { for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { @@ -1790,7 +1801,7 @@ export class KeylayoutToKmnConverter { * @param data_ukelele an object containing all data read from a .keylayout file * @return string - a list of stores */ - public createData_Stores(data_ukelele: convert_object): string { + public writeData_Stores(data_ukelele: convert_object): string { let data: string = "" data += "c ......................................................................\n" diff --git a/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts index cd132151171..2f7c09814da 100644 --- a/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts @@ -5,14 +5,46 @@ cd developer/src/kmc-convert/ ./build_disp.sh test*/ +// Todo +// check all +// ["a14"], +// ["unknownIdentifier"], +// [""], +// [" "], +// [null], +// [undefined], + +// definition of converter,... to top part +// change run second test NOT +// data inpout/output read in array +// write more tests + +// sut??? + +// data inpout/output convert in array +// check output sentence +// map_UkeleleKC_To_VK add " " and "" +// checkIfCapsIsUsed Caps? CapsWrongtext +// get_KeyMap_Modifier_array__From__behaviour_arr add " " and "" +// get_KeyMap_Modifier_array__From__behaviour_arr add undefined +// get_KeyMap_Code_array__From__ActionID_Action add undefined +// get_ActionID_Index__From__ActionID_Id add undefined +// get_ActionID_Id__From__ActionID_next add undefined +// get_KeyMapModiKeyArray__from__array not finished +// writeData_Stores data inpout/output convert in array +//get_Datat_array2D__From__ActionID_stateOutput add " " and "" undefined +//get_KeyMap_Code_array__From__KeyMap_Action_array2D add " " and "" undefined + + + import 'mocha'; import { assert } from 'chai'; import { compilerTestCallbacks, compilerTestOptions } from './helpers/index.js'; import { KeylayoutToKmnConverter } from '../src/keylayout-to-kmn/keylayout-to-kmn-converter.js'; -import { makePathToFixture } from './helpers/index.js'; // _S2 my imports - +import { makePathToFixture } from './helpers/index.js'; +//----------------------------------------------------------------------------------------------------------------------- describe('KeylayoutToKmnConverter', function () { @@ -20,8 +52,32 @@ describe('KeylayoutToKmnConverter', function () { compilerTestCallbacks.clear(); }); - // _S2 first test - /* it('should throw on null inputs', async function () { + //----------------------------------------------------------------------------------------------------------------------- + + // usable convert_object + const inputFilename = makePathToFixture('../data/Italian_copy.keylayout'); + const converter = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const read = converter.read(inputFilename); + const converted = converter.convert(read); + + // convert_object from unavailable file + const inputFilename_unavailable = makePathToFixture('X.keylayout'); + const read_unavailable = converter.read(inputFilename_unavailable); + const converted_unavailable = converter.convert(read_unavailable); + + // empty convert_object + const converted_empty = { ...converted_unavailable } + converted_empty.arrayOf_Modifiers = [] + converted_empty.arrayOf_Rules = [] + converted_empty.keylayout_filename = "" + + //----------------------------------------------------------------------------------------------------------------------- + // test run + describe("run() ", function () { + + // _S2 first test + it('should throw on null inputs', async function () { // const inputFilename = makePathToFixture('file.keylayout'); const converter = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); // note, could use 'chai as promised' library to make this more fluent: @@ -32,112 +88,214 @@ describe('KeylayoutToKmnConverter', function () { threw = true; } assert.isTrue(threw); - });*/ - - - // _S2 My tests... // later throws on NOT all elements loaded - it('should throw on all elements loaded', async function () { - - // some keys, no deadkeys - //const inputFilename = makePathToFixture('../data/Mysample.keylayout'); - - // all keys, some deadkeys - // copy into C:\Projects\keyman\keyman\developer\src\kmc-convert\test\DATA then they run OK - - //const inputFilename = makePathToFixture('../data/US_complete.keylayout'); // OK - //const inputFilename = makePathToFixture('../data/German_complete.keylayout'); // OK - const inputFilename = makePathToFixture('../data/Italian_copy.keylayout'); // OK - //const inputFilename = makePathToFixture('../data/German_Standard_copy.keylayout'); //OK - //const inputFilename = makePathToFixture('../data/German_Standard2.keylayout'); //OK - //const inputFilename = makePathToFixture('../data/German_StandardTweaked.keylayout'); //NO C3 - //const inputFilename = makePathToFixture('../data/Spanish_copy.keylayout'); // OK - //const inputFilename = makePathToFixture('../data/Latin_American_copy.keylayout'); // OK - //const inputFilename = makePathToFixture('../data/My_dk_Keyboard.keylayout'); // No - //const inputFilename = makePathToFixture('../data/Swiss_French_copy.keylayout'); // OK - //const inputFilename = makePathToFixture('../data/Swiss_German_copy.keylayout'); // OK - //const inputFilename = makePathToFixture('../data/US_copy.keylayout'); // OK - - const outputFilename = makePathToFixture('../data/MyResult.kmn'); - - // TODO check filename if correct - console.log(' inputFilename', inputFilename) - console.log(' outputFilename', outputFilename) - - // _S2 create obj of derived class-> use derived functions - const converter = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - - let threw = false; - try { - await converter.run(inputFilename, outputFilename); - } catch { - threw = true; - } - assert.isTrue(threw); - }); - //------------------------ + }); - it('should should return empty array on null input', async function () { - const converter = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const result = converter.read(null); - assert.isEmpty(result); - }); + it('should throw on wrong output file', async function () { + // const inputFilename = makePathToFixture('file.keylayout'); + const converter = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + // note, could use 'chai as promised' library to make this more fluent: + let threw = false; + try { + await converter.run(null, "X"); + } catch { + threw = true; + } + assert.isTrue(threw); + }); - it('should should return empty array on empty input', async function () { - const converter = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const result = converter.read(""); - assert.isEmpty(result); - }); + it('should throw on wrong intput file', async function () { + // const inputFilename = makePathToFixture('file.keylayout'); + const converter = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + // note, could use 'chai as promised' library to make this more fluent: + let threw = false; + try { + await converter.run("X", null); + } catch { + threw = true; + } + assert.isTrue(threw); + }); - it('should should return empty array on space as input', async function () { - const converter = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const result = converter.read(" "); - assert.isEmpty(result); - }); + // _S2 My tests... // later throws n NOT all elements loaded + it('should return true if ran OK', async function () { - it('should should return filled array on correct input', async function () { - const inputFilename = makePathToFixture('../data/Italian_copy.keylayout'); - const converter = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const result = converter.read(inputFilename); - assert.isNotEmpty(result); - }); + // some keys, no deadkeys + //const inputFilename = makePathToFixture('../data/Mysample.keylayout'); + // all keys, some deadkeys + // copy into C:\Projects\keyman\keyman\developer\src\kmc-convert\test\DATA then they run OK - // todo test read - wrong name, empty string, ok name - // todo test for all public func for all "return paths" + //const inputFilename = makePathToFixture('../data/US_complete.keylayout'); // OK + //const inputFilename = makePathToFixture('../data/German_complete.keylayout'); // OK + const inputFilename = makePathToFixture('../data/Italian_copy.keylayout'); // OK + //const inputFilename = makePathToFixture('../data/German_Standard_copy.keylayout'); //OK + //const inputFilename = makePathToFixture('../data/German_Standard2.keylayout'); //OK + //const inputFilename = makePathToFixture('../data/German_StandardTweaked.keylayout'); //NO C3 + //const inputFilename = makePathToFixture('../data/Spanish_copy.keylayout'); // OK + //const inputFilename = makePathToFixture('../data/Latin_American_copy.keylayout'); // OK + //const inputFilename = makePathToFixture('../data/My_dk_Keyboard.keylayout'); // No + //const inputFilename = makePathToFixture('../data/Swiss_French_copy.keylayout'); // OK + //const inputFilename = makePathToFixture('../data/Swiss_German_copy.keylayout'); // OK + //const inputFilename = makePathToFixture('../data/US_copy.keylayout'); // OK + + const outputFilename = makePathToFixture('../data/MyResult.kmn'); - //----------------- + // TODO check filename if correct + console.log(' inputFilename', inputFilename) + console.log(' outputFilename', outputFilename) + // _S2 create obj of derived class-> use derived functions + const converter = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - describe("create kmn modifier ", function () { + let threw = false; + try { + await converter.run(inputFilename, outputFilename); + } catch { + threw = true; + } + assert.isFalse(threw); + }); + }) + + //----------------------------------------------------------------------------------------------------------------------- + + + // OK test read + describe("read() ", function () { + it('should return filled array on correct input', async function () { + const result = converter.read(inputFilename); + assert.isNotEmpty(result); + }); + + it('should return empty array on null input', async function () { + const result = converter.read(null); + assert.isEmpty(result); + }); + + it('should return empty array on empty input', async function () { + const result = converter.read(""); + assert.isEmpty(result); + }); + + it('should return empty array on space as input', async function () { + const result = converter.read(" "); + assert.isEmpty(result); + }); + + it('should return empty array on unavailable file name', async function () { + ; + const result = converter.read(inputFilename_unavailable); + assert.isEmpty(result); + }); + + it('should return empty array on typo in path', async function () { + const result = converter.read('../data|Italian_copy.keylayout'); + assert.isEmpty(result); + }); + }) + + //----------------------------------------------------------------------------------------------------------------------- + // OK test write + describe("write() ", function () { + it('should return true if no inputfile', async function () { + const result = converter.write(converted_unavailable); + assert.isTrue(result); + }); + }) + describe("write() ", function () { + //const outArray = sut.convert(read); + it('should return true if written', async function () { + const result = converter.write(converted); + assert.isTrue(result); + }); + }) + + //----------------------------------------------------------------------------------------------------------------------- + // OK test convert + describe("convert() ", function () { + + // use converted from above + it('should return converted array on correct input', async function () { + assert.isTrue(converted.arrayOf_Rules.length !== 0); + }); + + const converted_empty = converter.convert({ + keylayout_filename: '', + arrayOf_Modifiers: [], + arrayOf_Rules: [] + }); + it('should return empty on empty input', async function () { + assert.isTrue((converted_empty.keylayout_filename === '' + && converted_empty.arrayOf_Modifiers.length === 0 + && converted_empty.arrayOf_Rules.length === 0)); + }); + + const converted_name = converter.convert({ + keylayout_filename: 'X.keylayout', + arrayOf_Modifiers: [], + arrayOf_Rules: [] + }); + it('should return empty on only name as input', async function () { + assert.isTrue((converted_name.keylayout_filename === '' + && converted_name.arrayOf_Modifiers.length === 0 + && converted_name.arrayOf_Rules.length === 0)); + }); + + const converted_mod = converter.convert({ + keylayout_filename: '', + arrayOf_Modifiers: [['caps'], ['Shift'], ['command']], + arrayOf_Rules: [] + }); + it('should return empty on only modifiers as input', async function () { + assert.isTrue((converted_mod.keylayout_filename === '' + && converted_mod.arrayOf_Modifiers.length === 0 + && converted_mod.arrayOf_Rules.length === 0)); + }); + + const converted_rule = converter.convert({ + keylayout_filename: '', + arrayOf_Modifiers: [], + arrayOf_Rules: [["C0", "", "", 0, 0, "", "", 0, 0, "CAPS", "K_A", "A"]] + }); + it('should return empty on only rules as input', async function () { + assert.isTrue((converted_rule.keylayout_filename === '' + && converted_rule.arrayOf_Modifiers.length === 0 + && converted_rule.arrayOf_Rules.length === 0)); + }); + }) + + //----------------------------------------------------------------------------------------------------------------------- + // OK test create_kmn_modifier + describe('create_kmn_modifier ', function () { [ - ["anycontrol", true, "NCAPS CTRL"], - ["shift?", true, "NCAPS"], - ["?", true, "NCAPS"], - ["?", false, ""], - ["caps", true, "CAPS"], - ["", true, "NCAPS"], - [" ", false, ""], - ["wrongModifierName", false, "wrongModifierName"], - ["shift", false, "SHIFT"], - ["shift command", true, "NCAPS SHIFT command"], - ["rshift", true, "NCAPS SHIFT"], - ["rshift", false, "SHIFT"], - ["rightshift", true, "NCAPS SHIFT"], - ["riGhtsHift", true, "NCAPS SHIFT"], - ["LEFTCONTROL", true, "NCAPS LCTRL"], - ["RCONTROL", true, "NCAPS RCTRL"], - ["leftoption", true, "NCAPS RALT"], - ["loption", true, "NCAPS RALT"], + ['anycontrol', true, 'NCAPS CTRL'], + ['shift?', true, 'NCAPS'], + ['?', true, 'NCAPS'], + ['?', false, ''], + ['caps', true, 'CAPS'], + ['', true, 'NCAPS'], + [' ', false, ''], + ['wrongModifierName', false, 'wrongModifierName'], + ['shift', false, 'SHIFT'], + ['shift command', true, 'NCAPS SHIFT command'], + ['rshift', true, 'NCAPS SHIFT'], + ['rshift', false, 'SHIFT'], + ['rightshift', true, 'NCAPS SHIFT'], + ['riGhtsHift', true, 'NCAPS SHIFT'], + ['LEFTCONTROL', true, 'NCAPS LCTRL'], + ['RCONTROL', true, 'NCAPS RCTRL'], + ['leftoption', true, 'NCAPS RALT'], + ['loption', true, 'NCAPS RALT'], ].forEach(function (values) { - - it('should convert "' + values[0] + '" to "' + values[2] + '"', async function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + it(('(should convert "' + values[0] + '"').padEnd(36, " ") + 'to \t"' + values[2] + '"', async function () { const result = sut.create_kmn_modifier(values[0] as string, values[1] as boolean); assert.equal(result, values[2]); }); }) }) + //----------------------------------------------------------------------------------------------------------------------- + // OK test isAcceptableKeymanModifier describe("isAcceptableKeymanModifier ", function () { [ ["NCAPS", true], @@ -149,18 +307,20 @@ describe('KeylayoutToKmnConverter', function () { ["CTRL", true], ["LCTRL", true], ["RCTRL", true], - ["", true], ["LCTRL CAPS", true], ["LCTRL X", false], + ["", true], + [null, false], ].forEach(function (values) { - it( "'" + values[0] + "'" +' should return ' + values[1] , async function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + it("'" + values[0] + "'" + ' should return ' + values[1], async function () { const result = sut.isAcceptableKeymanModifier(values[0] as string); assert.equal(result, values[1]); }); }) }) + //----------------------------------------------------------------------------------------------------------------------- + // OK test map_UkeleleKC_To_VK describe("map_UkeleleKC_To_VK ", function () { [ [0x00, "K_A"], @@ -171,30 +331,446 @@ describe('KeylayoutToKmnConverter', function () { [0x21, "K_LBRKT"], [0x999, ""], [-1, ""], + [null, ""], ].forEach(function (values) { - it( values[0] + ' should return ' + "'"+values[1] +"'", async function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + it(values[0] + ' should return ' + "'" + values[1] + "'", async function () { const result = sut.map_UkeleleKC_To_VK(values[0] as number); assert.equal(result, values[1]); }); }) }) + //----------------------------------------------------------------------------------------------------------------------- + // OK test checkIfCapsIsUsed describe("checkIfCapsIsUsed ", function () { it('should return true', async function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const input: string[][] = [["caps", "xxx"], ["yyy"]] const result = sut.checkIfCapsIsUsed(input); assert.isTrue(result); }); it('should return false', async function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const input: string[][] = [["zzz", "xxx"], ["yyy"]] const result = sut.checkIfCapsIsUsed(input); assert.isFalse(result); }); + it('should return false', async function () { + const input: string[][] = [null] + const result = sut.checkIfCapsIsUsed(input); + assert.isFalse(result); + }); + }) + + //----------------------------------------------------------------------------------------------------------------------- + // OK test get_KeyMap_Modifier_array__From__behaviour_arr + describe("get_KeyMap_Modifier_array__From__behaviour_arr ", function () { + + [ + [[['0', 0]], [['', 'shift? caps? ']]], + [[['0', 1]], [['anyShift caps?', 'shift? rightShift caps? ', 'shift? leftShift caps? ', 'shift leftShift caps ']]], + [[['0', 999]], [null]], + [[['999',]], [null]], + [[['0', -999]], [null]], + [[['0']], [null]], + [[[null]], [null]], + ].forEach(function (values) { + it((values[1][0] !== null) ? + "['0'," + values[0][0][1] + "]" + " should return ['" + values[1][0][0] + "', '" + values[1][0][1] + "']" : + "['0'," + values[0][0][1] + "]" + " should return ['" + values[1][0] + "']", async function () { + const result = converter.get_KeyMap_Modifier_array__From__behaviour_arr(converted.arrayOf_Modifiers, values[0]) + assert.deepStrictEqual(JSON.stringify(result), JSON.stringify(values[1])); + }); + }) + }) + + //----------------------------------------------------------------------------------------------------------------------- + // OK test get_KeyMap_Code_array__From__ActionID_Action + describe("get_KeyMap_Code_array__From__ActionID_Action ", function () { + [ + ["a16", [['32', 3]]], + ["a19", [['45', 3]]], + ["a18", [['24', 0], ['24', 3]]], + ["unknownIdentifier", []], + [undefined, []], + [null, []], + [" ", []], + ["", []], + ].forEach(function (values) { + let outstring = "[ "; + for (let i = 0; i < values[1].length; i++) { + outstring = outstring + "[ '" + values[1][i][0] + "', " + values[1][i][1].toString() + "], " + } + it("'" + values[0] + "'" + ' should return ' + outstring.substring(0, outstring.lastIndexOf(']') + 2) + " ]", async function () { + const result = converter.get_KeyMap_Code_array__From__ActionID_Action(read, String(values[0])); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }) + }) + + //----------------------------------------------------------------------------------------------------------------------- + // OK test get_ActionID_Id__From__ActionID_next + describe("get_ActionID_Id__From__ActionID_next ", function () { + [ + ["none", ""], + ["a18", ""], + ["0", ""], + ["1", "a16"], + ["2", "a8"], + ["3", "a17"], + ["", ""], + [" ", ""], + ["99", ""], + [null, ""], + [undefined, ""], + ["unknownIdentifier", ""], + ].forEach(function (values) { + it("'" + values[0] + "'" + ' should return ' + "'" + values[1] + "'", async function () { + const result = converter.get_ActionID_Id__From__ActionID_next(read, String(values[0])); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }) + }) + + //----------------------------------------------------------------------------------------------------------------------- + // OK test get_ActionID_Index__From__ActionID_Id + describe("get_ActionID_Index__From__ActionID_Id ", function () { + [ + ["none", 0], + ["a16", 8], + ["a18", 10], + ["a19", 11], + ["0", 0], + ["", 0], + [" ", 0], + [null, 0], + [undefined, 0], + ["unknownIdentifier", 0], + ].forEach(function (values) { + it("'" + values[0] + "'" + ' should return ' + values[1], async function () { + const result = converter.get_ActionID_Index__From__ActionID_Id(read, String(values[0])); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }) + }) + + //----------------------------------------------------------------------------------------------------------------------- + // OK test get_Action2ID_NoneOutput__From__ActionID_Id + describe("get_Action2ID_NoneOutput__From__ActionID_Id ", function () { + [ + ["a14", "u"], + ["", ""], + [" ", ""], + [null, ""], + [undefined, ""], + [99, ""], + ["a18", undefined], + ["unknownIdentifier", ""], + ].forEach(function (values) { + it((typeof (values[1]) === "string") ? + "'" + values[0] + "'" + ' should return ' + "'" + values[1] + "'" + : "'" + values[0] + "'" + ' should return ' + values[1], async function () { + const result = converter.get_Action2ID_NoneOutput__From__ActionID_Id(read, String(values[0])); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }) + }) + + //----------------------------------------------------------------------------------------------------------------------- + // TODO test get_KeyMapModiKeyArray__from__array + describe("get_KeyMapModiKeyArray__from__array ", function () { + + + + [ + [[['0', 'K_A', 'a9', '0', 'â']], true, [['K_A', 'a9', '0', 'NCAPS', 'â']]], + [[['0', 'K_A', 'xa9', '0', 'â']], true, [['K_A', 'xa9', '0', 'NCAPS', 'â']]], + + ].forEach(function (values) { + + /* const i = [['0', 'K_A', 'a9', '0', 'â']] + console.log("i[0][0] ", String(i[0][0])) + const all = [[['0', 'K_A', 'xa9', '0', 'â']], true, [['K_A', 'xa9', '0', 'NCAPS', 'â']]] + console.log("all", all) + console.log(" all[0", all[0]) + console.log(" values[0", values[0]) + + console.log(" all[1", all[1]) + console.log(" values[1", values[1]) + console.log(" all[2", all[2]) + console.log(" values[2", values[2]) + const new2 = JSON.stringify(values[2]) + console.log("new2 ", typeof (new2), new2) + console.log("new2[0] ", new2[0]) + console.log("new2[1] ", new2[1]) + console.log("new2[0][0] ", new2[0][0]) + + + + + console.log("values_values ", values) + console.log("values[0] ", values[0]) + // console.log("values[0][0] ", String(values[0][0])) + console.log("values[1] ", values[1]) + console.log("values[2] ", values[2]) + console.log(" ",)*/ + + + + /* let outstring = "[ "; + for (let i = 0; i < values[1].length; i++) { + outstring = outstring + "[ '" + values[1][i][0] + "', " + values[1][i][1].toString() + "], " + }*/ + // it("'" + values[0] + "'" + ' should return ' + outstring.substring(0, outstring.lastIndexOf(']') + 2) + " ]", async function () { + it("'" + values[0] + "'" + ' should return ' + values[1], async function () { + //const result = converter.get_KeyMapModiKeyArray__from__array(read, values[0], values[1]); + //assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + assert.equal(0, 0); + }); + }) + }) + + + + + //----------------------------------------------------------------------------------------------------------------------- + // OK test writeData_Stores + describe("writeData_Stores() ", function () { + + const written_correct = converter.writeData_Stores(converted) + + const converted_empty = converter.convert(converter.read("")); + const written_empty = converter.writeData_Stores(converted_empty) + + const converted_onlyName = converter.convert(converter.read("")); + converted_onlyName.keylayout_filename = "X.keylayout" + const written_onlyName = converter.writeData_Stores(converted_onlyName) + + const out_expected_first: string = + "c ......................................................................\n" + + "c ......................................................................\n" + + "c Keyman keyboard generated by kmn-convert\n" + + "c from Ukelele file: " + + const out_expected_last: string = + "\n" + + "c ......................................................................\n" + + "c ......................................................................\n" + + "\n" + + "store(&VERSION) '10.0'\n" + + "store(&TARGETS) 'any'\n" + + "store(&KEYBOARDVERSION) '1.0'\n" + + "store(©RIGHT) '© 2024 SIL International'\n" + + "\n" + + "begin Unicode > use(main)\n\n" + + "group(main) using keys\n\n" + + "\n" + + + + + + it('should return store text with filename on correct input', async function () { + assert.equal(written_correct, (out_expected_first + converted.keylayout_filename + out_expected_last)); + }); + + it('should return store text without filename on empty input', async function () { + assert.equal(written_empty, (out_expected_first + out_expected_last)); + }); + + it('should return store text without filename on only filename as input', async function () { + assert.equal(written_onlyName, (out_expected_first + converted_onlyName.keylayout_filename + out_expected_last)); + }); + }) + + //---------------------------------------------------------------------------------------------------------------------- + // test get_ActionID_Output_array__From__ActionID_State + describe("get_ActionID_Output_array__From__ActionID_State ", function () { + [ + ["1", [ + ['a0', '1', 'ˆ'], + ['a1', '1', 'Â'], + ['a10', '1', 'ê'], + ['a11', '1', 'î'], + ['a13', '1', 'ô'], + ['a14', '1', 'û'], + ['a2', '1', 'Ê'], + ['a3', '1', 'Î'], + ['a5', '1', 'Ô'], + ['a6', '1', 'Û'], + ['a9', '1', 'â']],], + ["2", [ + ['a0', '2', '`'], + ['a1', '2', 'À'], + ['a10', '2', 'è'], + ['a11', '2', 'ì'], + ['a13', '2', 'ò'], + ['a14', '2', 'ù'], + ['a2', '2', 'È'], + ['a3', '2', 'Ì'], + ['a5', '2', 'Ò'], + ['a6', '2', 'Ù'], + ['a9', '2', 'à']],], + ["789", [],], + ["", [],], + [" ", [],], + [123, [],], + [null, [],], + [undefined, [],], + ].forEach(function (values) { + it((JSON.stringify(values[1]).length > 30) ? + ("'" + values[0] + "'").padEnd(11, " ") + ' should return an array of object' : + ("'" + values[0] + "'").padEnd(11, " ") + ' should return ' + "'" + JSON.stringify(values[1]) + "'", async function () { + const result = converter.get_ActionID_Output_array__From__ActionID_State(read, String(values[0])); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }) + }) + + //----------------------------------------------------------------------------------------------------------------------- + // test get_Datat_array2D__From__ActionID_stateOutput + describe("get_Datat_array2D__From__ActionID_stateOutput ", function () { + [ + ["a1", "A", true, [ + ['a1', 'A', 'a1', '1', 'K_A', 'SHIFT NCAPS'], + ['a1', 'A', 'a1', '1', 'K_A', 'SHIFT CAPS'], + ['a1', 'A', 'a1', '2', 'K_A', 'CAPS']] + ], + ["a1", "A", false, [ + ['a1', 'A', 'a1', '1', 'K_A', 'SHIFT'], + ['a1', 'A', 'a1', '1', 'K_A', 'SHIFT CAPS'], + ['a1', 'A', 'a1', '2', 'K_A', 'CAPS']] + ], + ["a9", "a", true, [['a9', 'a', 'a9', '0', 'K_A', 'NCAPS']]], + ["a9", "a", false, [['a9', 'a', 'a9', '0', 'K_A', '']]], + ["a9", "a", , [['a9', 'a', 'a9', '0', 'K_A', '']]], + ["a9", "", true, [["a9", "", "a9", "0", "K_A", "NCAPS"]]], + ["a9", "", false, [["a9", "", "a9", "0", "K_A", ""]]], + ["", "a", true, []], + ["", "a", false, []], + ["", "", , []], + + ].forEach(function (values) { + it((JSON.stringify(values[3]).length > 35) ? + ("get_Datat_array2D__From__ActionID_stateOutput('" + values[0] + "', '" + values[1] + "', " + values[2] + ")").padEnd(67, " ") + ' should return an array of object' : + ("get_Datat_array2D__From__ActionID_stateOutput('" + values[0] + "', '" + values[1] + "', " + values[2] + ")").padEnd(67, " ") + ' should return ' + "'" + JSON.stringify(values[3]) + "'", async function () { + const result = converter.get_Datat_array2D__From__ActionID_stateOutput(read, converted.arrayOf_Modifiers, String(values[0]), String(values[1]), Boolean(values[2])) + assert.equal(JSON.stringify(result), JSON.stringify(values[3])); + }); + }) + }) + + //----------------------------------------------------------------------------------------------------------------------- + /*const inputFilename9 = makePathToFixture('../data/Italian_copy.keylayout'); + const converter9 = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + //const sut9 = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const read9 = converter9.read(inputFilename9); + const converted9 = converter9.convert(read9); + console.log("converted9 ", typeof (converted9))*/ + + + + // test get_KeyMap_Code_array__From__KeyMap_Action_array2D + describe("get_KeyMap_Code_array__From__KeyMap_Action_array2D ", function () { + + const b6_actionId_arr = [ + ['a0', '1', 'ˆ'], + ['a1', '1', 'Â'], + ['a10', '1', 'ê'], + ['a11', '1', 'î'], + ['a13', '1', 'ô'], + ['a14', '1', 'û'], + ['a2', '1', 'Ê'], + ['a3', '1', 'Î'], + ['a5', '1', 'Ô'], + ['a6', '1', 'Û'], + ['a9', '1', 'â'] + ]; + const b1_keycode_arr = [ + ['49', 'K_SPACE', 'a0', '0', 'ˆ'], + ['49', 'K_SPACE', 'a0', '1', 'ˆ'], + ['49', 'K_SPACE', 'a0', '2', 'ˆ'], + ['6', 'K_Z', 'a0', '4', 'ˆ'], + ['25', 'K_9', 'a0', '4', 'ˆ'], + ['43', 'K_COMMA', 'a0', '4', 'ˆ'], + ['49', 'K_SPACE', 'a0', '7', 'ˆ'], + ['0', 'K_A', 'a1', '1', 'Â'], + ['0', 'K_A', 'a1', '2', 'Â'], + ['14', 'K_E', 'a10', '0', 'ê'], + ['34', 'K_I', 'a11', '0', 'î'], + ['31', 'K_O', 'a13', '0', 'ô'], + ['32', 'K_U', 'a14', '0', 'û'], + ['14', 'K_E', 'a2', '1', 'Ê'], + ['14', 'K_E', 'a2', '2', 'Ê'], + ['34', 'K_I', 'a3', '1', 'Î'], + ['34', 'K_I', 'a3', '2', 'Î'], + ['31', 'K_O', 'a5', '1', 'Ô'], + ['31', 'K_O', 'a5', '2', 'Ô'], + ['32', 'K_U', 'a6', '1', 'Û'], + ['32', 'K_U', 'a6', '2', 'Û'], + ['0', 'K_A', 'a9', '0', 'â'] + ]; + const oneEntryResult = + [["49", "K_SPACE", "a0", "0", "ˆ"], + ["49", "K_SPACE", "a0", "1", "ˆ"], + ["49", "K_SPACE", "a0", "2", "ˆ"], + ["6", "K_Z", "a0", "4", "ˆ"], + ["25", "K_9", "a0", "4", "ˆ"], + ["43", "K_COMMA", "a0", "4", "ˆ"], + ["49", "K_SPACE", "a0", "7", "ˆ"] + ]; + const oneEntryResultNoOutput = + [["49", "K_SPACE", "a0", "0", ""], + ["49", "K_SPACE", "a0", "1", ""], + ["49", "K_SPACE", "a0", "2", ""], + ["6", "K_Z", "a0", "4", ""], + ["25", "K_9", "a0", "4", ""], + ["43", "K_COMMA", "a0", "4", ""], + ["49", "K_SPACE", "a0", "7", ""] + ]; + + [ + [b6_actionId_arr, b1_keycode_arr], + [[['a0', '1', 'ˆ']], oneEntryResult], + [[['a0', '1', '']], oneEntryResultNoOutput], + [[['a0', '', 'ˆ']], oneEntryResult], + [[['', '1', 'ˆ']], []], + [[['', '', '']], []], + [[[' ', ' ', '']], []], + [[], []], + [undefined, []], + [null, []], + ].forEach(function (values) { + it(((values[0] === undefined) || (values.some(function (value) { return value === null })) || (values[0].length === 0)) ? + ("get_KeyMap_Code_array__From__KeyMap_Action_array2D(" + values[0] + ")").padEnd(73, " ") + ' should return ' + "'[" + values[1] + "]'" + : (JSON.stringify(values[1]).length > 35) ? + (values[0].length > 0) ? + ("get_KeyMap_Code_array__From__KeyMap_Action_array2D([['" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "'],..])").padEnd(73, " ") + ' should return an array of object' + : ("get_KeyMap_Code_array__From__KeyMap_Action_array2D(['" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "'])").padEnd(73, " ") + ' should return an array of object' + : ("get_KeyMap_Code_array__From__KeyMap_Action_array2D(['" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "'])").padEnd(73, " ") + ' should return ' + "'[" + values[1] + "]'", async function () { + const result = converter.get_KeyMap_Code_array__From__KeyMap_Action_array2D(read, values[0]) + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }) }) + //----------------------------------------------------------------------------------------------------------------------- + + // todo test for all public func for all "return paths" + // todo check input null + + // test createRuleData + // test reviewRules + // test writeData_Rules + //----------------------------------------------------------------------------------------------------------------------- + // ToDo remove + describe("END ", function () { + it('################################################## TESTs DONE ####################################################################################################', async function () { + assert.equal(0, 0); + }); + }) + + + + }); From 3bd2c5e9fd8d097e627cbd886770e9513ad6047b Mon Sep 17 00:00:00 2001 From: Sabine Date: Thu, 6 Mar 2025 13:12:01 +0100 Subject: [PATCH 063/251] feat(developer): more tests for kmc-convert --- .../test/test-keylayout-to-kmn-converter.ts | 694 ++++++++---------- 1 file changed, 322 insertions(+), 372 deletions(-) diff --git a/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts index 2f7c09814da..e9f1b2dd075 100644 --- a/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts @@ -1,40 +1,10 @@ /* * Keyman is copyright (C) SIL International. MIT License. */ + /*run with cd developer/src/kmc-convert/ -./build_disp.sh test*/ - -// Todo -// check all -// ["a14"], -// ["unknownIdentifier"], -// [""], -// [" "], -// [null], -// [undefined], - -// definition of converter,... to top part -// change run second test NOT -// data inpout/output read in array -// write more tests - -// sut??? - -// data inpout/output convert in array -// check output sentence -// map_UkeleleKC_To_VK add " " and "" -// checkIfCapsIsUsed Caps? CapsWrongtext -// get_KeyMap_Modifier_array__From__behaviour_arr add " " and "" -// get_KeyMap_Modifier_array__From__behaviour_arr add undefined -// get_KeyMap_Code_array__From__ActionID_Action add undefined -// get_ActionID_Index__From__ActionID_Id add undefined -// get_ActionID_Id__From__ActionID_next add undefined -// get_KeyMapModiKeyArray__from__array not finished -// writeData_Stores data inpout/output convert in array -//get_Datat_array2D__From__ActionID_stateOutput add " " and "" undefined -//get_KeyMap_Code_array__From__KeyMap_Action_array2D add " " and "" undefined - +./build.sh test*/ @@ -52,220 +22,176 @@ describe('KeylayoutToKmnConverter', function () { compilerTestCallbacks.clear(); }); - //----------------------------------------------------------------------------------------------------------------------- + // convert_object + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - // usable convert_object + // convert_object from usable file name const inputFilename = makePathToFixture('../data/Italian_copy.keylayout'); - const converter = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const read = converter.read(inputFilename); - const converted = converter.convert(read); + const read = sut.read(inputFilename); + const converted = sut.convert(read); - // convert_object from unavailable file + // empty convert_object from unavailable file name const inputFilename_unavailable = makePathToFixture('X.keylayout'); - const read_unavailable = converter.read(inputFilename_unavailable); - const converted_unavailable = converter.convert(read_unavailable); + const read_unavailable = sut.read(inputFilename_unavailable); + const converted_unavailable = sut.convert(read_unavailable); - // empty convert_object - const converted_empty = { ...converted_unavailable } - converted_empty.arrayOf_Modifiers = [] - converted_empty.arrayOf_Rules = [] - converted_empty.keylayout_filename = "" + // empty convert_object from empty filename + const inputFilename_empty = makePathToFixture(''); + const read_empty = sut.read(inputFilename_empty); + const converted_empty = sut.convert(read_empty); - //----------------------------------------------------------------------------------------------------------------------- - // test run describe("run() ", function () { - // _S2 first test - it('should throw on null inputs', async function () { - // const inputFilename = makePathToFixture('file.keylayout'); - const converter = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + it('run() should throw on null inputs', async function () { // note, could use 'chai as promised' library to make this more fluent: let threw = false; try { - await converter.run(null, null); + await sut.run(null, null); } catch { threw = true; } assert.isTrue(threw); }); - it('should throw on wrong output file', async function () { - // const inputFilename = makePathToFixture('file.keylayout'); - const converter = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - // note, could use 'chai as promised' library to make this more fluent: + it('run() should throw on wrong output file', async function () { let threw = false; try { - await converter.run(null, "X"); + await sut.run(null, "X"); } catch { threw = true; } assert.isTrue(threw); }); - it('should throw on wrong intput file', async function () { - // const inputFilename = makePathToFixture('file.keylayout'); - const converter = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - // note, could use 'chai as promised' library to make this more fluent: + it('run() should throw on wrong intput file', async function () { let threw = false; try { - await converter.run("X", null); + await sut.run("X", null); } catch { threw = true; } assert.isTrue(threw); }); - // _S2 My tests... // later throws n NOT all elements loaded - it('should return true if ran OK', async function () { - - // some keys, no deadkeys - //const inputFilename = makePathToFixture('../data/Mysample.keylayout'); - - // all keys, some deadkeys - // copy into C:\Projects\keyman\keyman\developer\src\kmc-convert\test\DATA then they run OK - - //const inputFilename = makePathToFixture('../data/US_complete.keylayout'); // OK - //const inputFilename = makePathToFixture('../data/German_complete.keylayout'); // OK - const inputFilename = makePathToFixture('../data/Italian_copy.keylayout'); // OK - //const inputFilename = makePathToFixture('../data/German_Standard_copy.keylayout'); //OK - //const inputFilename = makePathToFixture('../data/German_Standard2.keylayout'); //OK - //const inputFilename = makePathToFixture('../data/German_StandardTweaked.keylayout'); //NO C3 - //const inputFilename = makePathToFixture('../data/Spanish_copy.keylayout'); // OK - //const inputFilename = makePathToFixture('../data/Latin_American_copy.keylayout'); // OK - //const inputFilename = makePathToFixture('../data/My_dk_Keyboard.keylayout'); // No - //const inputFilename = makePathToFixture('../data/Swiss_French_copy.keylayout'); // OK - //const inputFilename = makePathToFixture('../data/Swiss_German_copy.keylayout'); // OK - //const inputFilename = makePathToFixture('../data/US_copy.keylayout'); // OK + it('run() should return true if ran OK', async function () { + + //copy into C:\Projects\keyman\keyman\developer\src\kmc-convert\test\DATA then they run OK + //const inputFilename = makePathToFixture('../data/US_complete.keylayout'); // OK + //const inputFilename = makePathToFixture('../data/German_complete.keylayout'); // OK + const inputFilename = makePathToFixture('../data/Italian_copy.keylayout'); // OK + //const inputFilename = makePathToFixture('../data/German_Standard_copy.keylayout'); // OK + //const inputFilename = makePathToFixture('../data/German_Standard2.keylayout'); // OK + //const inputFilename = makePathToFixture('../data/German_StandardTweaked.keylayout'); // NO C3 + //const inputFilename = makePathToFixture('../data/Spanish_copy.keylayout'); // OK + //const inputFilename = makePathToFixture('../data/Latin_American_copy.keylayout'); // OK + //const inputFilename = makePathToFixture('../data/My_dk_Keyboard.keylayout'); // No + //const inputFilename = makePathToFixture('../data/Swiss_French_copy.keylayout'); // OK + //const inputFilename = makePathToFixture('../data/Swiss_German_copy.keylayout'); // OK + //const inputFilename = makePathToFixture('../data/US_copy.keylayout'); // OK + + // TODO use path also + // const outputFilename = "data//" +inputFilename.substring(0, inputFilename.lastIndexOf(".")) + ".kmn" const outputFilename = makePathToFixture('../data/MyResult.kmn'); - // TODO check filename if correct - console.log(' inputFilename', inputFilename) - console.log(' outputFilename', outputFilename) - - // _S2 create obj of derived class-> use derived functions - const converter = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - let threw = false; try { - await converter.run(inputFilename, outputFilename); + await sut.run(inputFilename, outputFilename); } catch { threw = true; } - assert.isFalse(threw); + assert.isTrue(!threw); }); }) - //----------------------------------------------------------------------------------------------------------------------- - - - // OK test read describe("read() ", function () { - it('should return filled array on correct input', async function () { - const result = converter.read(inputFilename); + it('read() should return filled array on correct input', async function () { + const result = sut.read(inputFilename); assert.isNotEmpty(result); }); - it('should return empty array on null input', async function () { - const result = converter.read(null); + it('read() should return empty array on null input', async function () { + const result = sut.read(null); assert.isEmpty(result); }); - it('should return empty array on empty input', async function () { - const result = converter.read(""); + it('read() should return empty array on empty input', async function () { + const result = sut.read(""); assert.isEmpty(result); }); - it('should return empty array on space as input', async function () { - const result = converter.read(" "); + it('read() should return empty array on space as input', async function () { + const result = sut.read(" "); assert.isEmpty(result); }); - it('should return empty array on unavailable file name', async function () { - ; - const result = converter.read(inputFilename_unavailable); + it('read() should return empty array on unavailable file name', async function () { + const result = sut.read(inputFilename_unavailable); assert.isEmpty(result); }); - it('should return empty array on typo in path', async function () { - const result = converter.read('../data|Italian_copy.keylayout'); + it('read() should return empty array on typo in path', async function () { + const result = sut.read('../data|Italian_copy.keylayout'); assert.isEmpty(result); }); }) - //----------------------------------------------------------------------------------------------------------------------- - // OK test write describe("write() ", function () { - it('should return true if no inputfile', async function () { - const result = converter.write(converted_unavailable); + it('write() should return true (no error) if no inputfile', async function () { + const result = sut.write(converted_unavailable); assert.isTrue(result); }); - }) - describe("write() ", function () { - //const outArray = sut.convert(read); - it('should return true if written', async function () { - const result = converter.write(converted); + + it('write() should return true (no error) if written', async function () { + const result = sut.write(converted); assert.isTrue(result); }); }) - //----------------------------------------------------------------------------------------------------------------------- - // OK test convert describe("convert() ", function () { - // use converted from above it('should return converted array on correct input', async function () { + // we use 'converted' from above assert.isTrue(converted.arrayOf_Rules.length !== 0); }); - const converted_empty = converter.convert({ - keylayout_filename: '', - arrayOf_Modifiers: [], - arrayOf_Rules: [] - }); it('should return empty on empty input', async function () { + // we use 'converted_empty' from above assert.isTrue((converted_empty.keylayout_filename === '' && converted_empty.arrayOf_Modifiers.length === 0 && converted_empty.arrayOf_Rules.length === 0)); }); - const converted_name = converter.convert({ - keylayout_filename: 'X.keylayout', - arrayOf_Modifiers: [], - arrayOf_Rules: [] - }); it('should return empty on only name as input', async function () { - assert.isTrue((converted_name.keylayout_filename === '' - && converted_name.arrayOf_Modifiers.length === 0 - && converted_name.arrayOf_Rules.length === 0)); + // we use 'converted_unavailable' from above + assert.isTrue((converted_unavailable.keylayout_filename === '' + && converted_unavailable.arrayOf_Modifiers.length === 0 + && converted_unavailable.arrayOf_Rules.length === 0)); }); - const converted_mod = converter.convert({ - keylayout_filename: '', - arrayOf_Modifiers: [['caps'], ['Shift'], ['command']], - arrayOf_Rules: [] - }); it('should return empty on only modifiers as input', async function () { + const converted_mod = sut.convert({ + keylayout_filename: '', + arrayOf_Modifiers: [['caps'], ['Shift'], ['command']], + arrayOf_Rules: [] + }); assert.isTrue((converted_mod.keylayout_filename === '' && converted_mod.arrayOf_Modifiers.length === 0 && converted_mod.arrayOf_Rules.length === 0)); }); - const converted_rule = converter.convert({ - keylayout_filename: '', - arrayOf_Modifiers: [], - arrayOf_Rules: [["C0", "", "", 0, 0, "", "", 0, 0, "CAPS", "K_A", "A"]] - }); it('should return empty on only rules as input', async function () { + const converted_rule = sut.convert({ + keylayout_filename: '', + arrayOf_Modifiers: [], + arrayOf_Rules: [["C0", "", "", 0, 0, "", "", 0, 0, "CAPS", "K_A", "A"]] + }); assert.isTrue((converted_rule.keylayout_filename === '' && converted_rule.arrayOf_Modifiers.length === 0 && converted_rule.arrayOf_Rules.length === 0)); }); }) - //----------------------------------------------------------------------------------------------------------------------- - // OK test create_kmn_modifier describe('create_kmn_modifier ', function () { [ ['anycontrol', true, 'NCAPS CTRL'], @@ -287,15 +213,13 @@ describe('KeylayoutToKmnConverter', function () { ['leftoption', true, 'NCAPS RALT'], ['loption', true, 'NCAPS RALT'], ].forEach(function (values) { - it(('(should convert "' + values[0] + '"').padEnd(36, " ") + 'to \t"' + values[2] + '"', async function () { + it(('should convert "' + values[0] + '"').padEnd(36, " ") + 'to "' + values[2] + '"', async function () { const result = sut.create_kmn_modifier(values[0] as string, values[1] as boolean); assert.equal(result, values[2]); }); }) }) - //----------------------------------------------------------------------------------------------------------------------- - // OK test isAcceptableKeymanModifier describe("isAcceptableKeymanModifier ", function () { [ ["NCAPS", true], @@ -312,15 +236,13 @@ describe('KeylayoutToKmnConverter', function () { ["", true], [null, false], ].forEach(function (values) { - it("'" + values[0] + "'" + ' should return ' + values[1], async function () { + it(("isAcceptableKeymanModifier(" + values[0] + ")").padEnd(38, " ") + ' should return ' + values[1], async function () { const result = sut.isAcceptableKeymanModifier(values[0] as string); assert.equal(result, values[1]); }); }) }) - //----------------------------------------------------------------------------------------------------------------------- - // OK test map_UkeleleKC_To_VK describe("map_UkeleleKC_To_VK ", function () { [ [0x00, "K_A"], @@ -333,83 +255,85 @@ describe('KeylayoutToKmnConverter', function () { [-1, ""], [null, ""], ].forEach(function (values) { - it(values[0] + ' should return ' + "'" + values[1] + "'", async function () { + it(("map_UkeleleKC_To_VK(" + values[0] + ")").padEnd(26, " ") + "should return " + "'" + values[1] + "'", async function () { const result = sut.map_UkeleleKC_To_VK(values[0] as number); assert.equal(result, values[1]); }); }) }) - //----------------------------------------------------------------------------------------------------------------------- - // OK test checkIfCapsIsUsed describe("checkIfCapsIsUsed ", function () { - it('should return true', async function () { - const input: string[][] = [["caps", "xxx"], ["yyy"]] - const result = sut.checkIfCapsIsUsed(input); + it(("checkIfCapsIsUsed([['caps', 'xxx'], ['yyy']])").padEnd(45, " ") + " should return true", async function () { + const result = sut.checkIfCapsIsUsed([["caps", "xxx"], ["yyy"]]); assert.isTrue(result); }); - it('should return false', async function () { - const input: string[][] = [["zzz", "xxx"], ["yyy"]] - const result = sut.checkIfCapsIsUsed(input); + it(("checkIfCapsIsUsed([['zzz', 'xxx'], ['yyy']])").padEnd(45, " ") + " should return false", async function () { + const result = sut.checkIfCapsIsUsed([["zzz", "xxx"], ["yyy"]]); assert.isFalse(result); }); - it('should return false', async function () { - const input: string[][] = [null] - const result = sut.checkIfCapsIsUsed(input); + it(("checkIfCapsIsUsed([['', ''], ['']])").padEnd(45, " ") + " should return false", async function () { + const result = sut.checkIfCapsIsUsed([["", ""], [""]]); + assert.isFalse(result); + }); + it(("checkIfCapsIsUsed([null])").padEnd(45, " ") + " should return false", async function () { + const result = sut.checkIfCapsIsUsed([null]); assert.isFalse(result); }); }) - //----------------------------------------------------------------------------------------------------------------------- - // OK test get_KeyMap_Modifier_array__From__behaviour_arr describe("get_KeyMap_Modifier_array__From__behaviour_arr ", function () { - - [ - [[['0', 0]], [['', 'shift? caps? ']]], - [[['0', 1]], [['anyShift caps?', 'shift? rightShift caps? ', 'shift? leftShift caps? ', 'shift leftShift caps ']]], - [[['0', 999]], [null]], - [[['999',]], [null]], - [[['0', -999]], [null]], - [[['0']], [null]], - [[[null]], [null]], + [[[['0', 0]], [['', 'shift? caps? ']]], + [[['0', 1]], [['anyShift caps?', 'shift? rightShift caps? ', 'shift? leftShift caps? ', 'shift leftShift caps ']]], + [[['0', 999]], [null]], + [[['999',]], [null]], + [[['0', -999]], [null]], + [[['0']], [null]], ].forEach(function (values) { it((values[1][0] !== null) ? - "['0'," + values[0][0][1] + "]" + " should return ['" + values[1][0][0] + "', '" + values[1][0][1] + "']" : - "['0'," + values[0][0][1] + "]" + " should return ['" + values[1][0] + "']", async function () { - const result = converter.get_KeyMap_Modifier_array__From__behaviour_arr(converted.arrayOf_Modifiers, values[0]) + ("get_KeyMap_Modifier_array__From__behaviour_arr(['" + values[0][0][0] + "', '" + values[0][0][1] + "'])").padEnd(68, " ") + " should return ['" + values[1][0][0] + "', '" + values[1][0][1] + "']" : + ("get_KeyMap_Modifier_array__From__behaviour_arr(['" + values[0][0][0] + "', '" + values[0][0][1] + "'])").padEnd(68, " ") + " should return ['" + values[1][0] + "']", async function () { + const result = sut.get_KeyMap_Modifier_array__From__behaviour_arr(converted.arrayOf_Modifiers, values[0]) assert.deepStrictEqual(JSON.stringify(result), JSON.stringify(values[1])); }); + }); + + [[[[null]], [null]], + [[[undefined]], [null]], + [[[]], [null]], + ].forEach(function (values) { + it(("get_KeyMap_Modifier_array__From__behaviour_arr([" + values[0][0] + "])").padEnd(68, " ") + " should return ['" + values[1][0] + "']", async function () { + const result = sut.get_KeyMap_Modifier_array__From__behaviour_arr(converted.arrayOf_Modifiers, values[0]) + assert.deepStrictEqual(JSON.stringify(result), JSON.stringify(values[1])); + }); }) }) - //----------------------------------------------------------------------------------------------------------------------- - // OK test get_KeyMap_Code_array__From__ActionID_Action describe("get_KeyMap_Code_array__From__ActionID_Action ", function () { [ ["a16", [['32', 3]]], ["a19", [['45', 3]]], ["a18", [['24', 0], ['24', 3]]], - ["unknownIdentifier", []], + ["unknown", []], [undefined, []], [null, []], [" ", []], ["", []], ].forEach(function (values) { + let outstring = "[ "; for (let i = 0; i < values[1].length; i++) { outstring = outstring + "[ '" + values[1][i][0] + "', " + values[1][i][1].toString() + "], " } - it("'" + values[0] + "'" + ' should return ' + outstring.substring(0, outstring.lastIndexOf(']') + 2) + " ]", async function () { - const result = converter.get_KeyMap_Code_array__From__ActionID_Action(read, String(values[0])); + + it(("get_KeyMap_Code_array__From__ActionID_Action('" + values[0] + "')").padEnd(57, " ") + ' should return ' + outstring.substring(0, outstring.lastIndexOf(']') + 2) + " ]", async function () { + const result = sut.get_KeyMap_Code_array__From__ActionID_Action(read, String(values[0])); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }) }) - //----------------------------------------------------------------------------------------------------------------------- - // OK test get_ActionID_Id__From__ActionID_next describe("get_ActionID_Id__From__ActionID_next ", function () { [ ["none", ""], @@ -423,17 +347,15 @@ describe('KeylayoutToKmnConverter', function () { ["99", ""], [null, ""], [undefined, ""], - ["unknownIdentifier", ""], + ["unknown", ""], ].forEach(function (values) { - it("'" + values[0] + "'" + ' should return ' + "'" + values[1] + "'", async function () { - const result = converter.get_ActionID_Id__From__ActionID_next(read, String(values[0])); + it(("get_ActionID_Id__From__ActionID_next('" + values[0] + "')").padEnd(49, " ") + ' should return ' + "'" + values[1] + "'", async function () { + const result = sut.get_ActionID_Id__From__ActionID_next(read, String(values[0])); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }) }) - //----------------------------------------------------------------------------------------------------------------------- - // OK test get_ActionID_Index__From__ActionID_Id describe("get_ActionID_Index__From__ActionID_Id ", function () { [ ["none", 0], @@ -445,106 +367,152 @@ describe('KeylayoutToKmnConverter', function () { [" ", 0], [null, 0], [undefined, 0], - ["unknownIdentifier", 0], + ["unknown", 0], ].forEach(function (values) { - it("'" + values[0] + "'" + ' should return ' + values[1], async function () { - const result = converter.get_ActionID_Index__From__ActionID_Id(read, String(values[0])); + it(("get_ActionID_Index__From__ActionID_Id('" + values[0] + "')").padEnd(50, " ") + ' should return ' + values[1], async function () { + const result = sut.get_ActionID_Index__From__ActionID_Id(read, String(values[0])); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }) }) - //----------------------------------------------------------------------------------------------------------------------- - // OK test get_Action2ID_NoneOutput__From__ActionID_Id describe("get_Action2ID_NoneOutput__From__ActionID_Id ", function () { - [ - ["a14", "u"], - ["", ""], - [" ", ""], - [null, ""], - [undefined, ""], - [99, ""], - ["a18", undefined], - ["unknownIdentifier", ""], + [["a14", "u"], + ["", ""], + [" ", ""], + ["a18", undefined], + ["unknown", ""], ].forEach(function (values) { - it((typeof (values[1]) === "string") ? - "'" + values[0] + "'" + ' should return ' + "'" + values[1] + "'" - : "'" + values[0] + "'" + ' should return ' + values[1], async function () { - const result = converter.get_Action2ID_NoneOutput__From__ActionID_Id(read, String(values[0])); + it( + ("get_Action2ID_NoneOutput__From__ActionID_Id('" + values[0] + "')").padEnd(56, " ") + ' should return ' + "'" + values[1] + "'", async function () { + const result = sut.get_Action2ID_NoneOutput__From__ActionID_Id(read, String(values[0])); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); + }); + + [[null, ""], + [undefined, ""], + [99, ""], + ].forEach(function (values) { + it(("get_Action2ID_NoneOutput__From__ActionID_Id('" + values[0] + "')").padEnd(56, " ") + ' should return ' + values[1], async function () { + const result = sut.get_Action2ID_NoneOutput__From__ActionID_Id(read, String(values[0])); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); }) }) - //----------------------------------------------------------------------------------------------------------------------- - // TODO test get_KeyMapModiKeyArray__from__array describe("get_KeyMapModiKeyArray__from__array ", function () { + const b1_keycode_arr = [ + ['49', 'K_SPACE', 'a0', '0', 'ˆ'], + ['49', 'K_SPACE', 'a0', '1', 'ˆ'], + ['49', 'K_SPACE', 'a0', '2', 'ˆ'], + ['6', 'K_Z', 'a0', '4', 'ˆ'], + ['25', 'K_9', 'a0', '4', 'ˆ'], + ['43', 'K_COMMA', 'a0', '4', 'ˆ'], + ['49', 'K_SPACE', 'a0', '7', 'ˆ'], + ['0', 'K_A', 'a1', '1', 'Â'], + ['0', 'K_A', 'a1', '2', 'Â'], + ['14', 'K_E', 'a10', '0', 'ê'], + ['34', 'K_I', 'a11', '0', 'î'], + ['31', 'K_O', 'a13', '0', 'ô'], + ['32', 'K_U', 'a14', '0', 'û'], + ['14', 'K_E', 'a2', '1', 'Ê'], + ['14', 'K_E', 'a2', '2', 'Ê'], + ['34', 'K_I', 'a3', '1', 'Î'], + ['34', 'K_I', 'a3', '2', 'Î'], + ['31', 'K_O', 'a5', '1', 'Ô'], + ['31', 'K_O', 'a5', '2', 'Ô'], + ['32', 'K_U', 'a6', '1', 'Û'], + ['32', 'K_U', 'a6', '2', 'Û'], + ['0', 'K_A', 'a9', '0', 'â'] + ]; + const b1_modifierKey_arr = [ + ['K_SPACE', 'a0', '0', 'NCAPS', 'ˆ'], + ['K_SPACE', 'a0', '1', 'SHIFT NCAPS', 'ˆ'], + ['K_SPACE', 'a0', '1', 'SHIFT CAPS', 'ˆ'], + ['K_SPACE', 'a0', '2', 'CAPS', 'ˆ'], + ['K_Z', 'a0', '4', 'SHIFT NCAPS RALT', 'ˆ'], + ['K_9', 'a0', '4', 'SHIFT NCAPS RALT', 'ˆ'], + ['K_COMMA', 'a0', '4', 'SHIFT NCAPS RALT', 'ˆ'], + ['K_SPACE', 'a0', '7', 'NCAPS CTRL', 'ˆ'], + ['K_SPACE', 'a0', '7', 'NCAPS RALT CTRL', 'ˆ'], + ['K_A', 'a1', '1', 'SHIFT NCAPS', 'Â'], + ['K_A', 'a1', '1', 'SHIFT CAPS', 'Â'], + ['K_A', 'a1', '2', 'CAPS', 'Â'], + ['K_E', 'a10', '0', 'NCAPS', 'ê'], + ['K_I', 'a11', '0', 'NCAPS', 'î'], + ['K_O', 'a13', '0', 'NCAPS', 'ô'], + ['K_U', 'a14', '0', 'NCAPS', 'û'], + ['K_E', 'a2', '1', 'SHIFT NCAPS', 'Ê'], + ['K_E', 'a2', '1', 'SHIFT CAPS', 'Ê'], + ['K_E', 'a2', '2', 'CAPS', 'Ê'], + ['K_I', 'a3', '1', 'SHIFT NCAPS', 'Î'], + ['K_I', 'a3', '1', 'SHIFT CAPS', 'Î'], + ['K_I', 'a3', '2', 'CAPS', 'Î'], + ['K_O', 'a5', '1', 'SHIFT NCAPS', 'Ô'], + ['K_O', 'a5', '1', 'SHIFT CAPS', 'Ô'], + ['K_O', 'a5', '2', 'CAPS', 'Ô'], + ['K_U', 'a6', '1', 'SHIFT NCAPS', 'Û'], + ['K_U', 'a6', '1', 'SHIFT CAPS', 'Û'], + ['K_U', 'a6', '2', 'CAPS', 'Û'], + ['K_A', 'a9', '0', 'NCAPS', 'â'] + ]; - - [ - [[['0', 'K_A', 'a9', '0', 'â']], true, [['K_A', 'a9', '0', 'NCAPS', 'â']]], - [[['0', 'K_A', 'xa9', '0', 'â']], true, [['K_A', 'xa9', '0', 'NCAPS', 'â']]], - + // isCaps_used === true; input defined + [[b1_keycode_arr, b1_modifierKey_arr], + [[['49', 'K_SPACE', 'a0', '0', 'ˆ']], [['K_SPACE', 'a0', '0', 'NCAPS', 'ˆ']]], + [[['49', 'K_SPACE', 'a0', '0', '']], [['K_SPACE', 'a0', '0', 'NCAPS', '']]], + [[['49', 'K_SPACE', 'a0', '', 'ˆ']], [['K_SPACE', 'a0', '', 'NCAPS', 'ˆ']]], + [[['49', 'K_SPACE', '', '0', 'ˆ']], [['K_SPACE', '', '0', 'NCAPS', 'ˆ']]], + [[['49', '', 'a0', '0', 'ˆ']], [['', 'a0', '0', 'NCAPS', 'ˆ']]], + [[['', 'K_SPACE', 'a0', '0', 'ˆ']], [['K_SPACE', 'a0', '0', 'NCAPS', 'ˆ']]], + [[['', 'K_SPACE', 'a0', '0', 'ˆ']], [['K_SPACE', 'a0', '0', 'NCAPS', 'ˆ']]], + [[['', '', '', '', '']], [['', '', '', 'NCAPS', '']]], ].forEach(function (values) { - /* const i = [['0', 'K_A', 'a9', '0', 'â']] - console.log("i[0][0] ", String(i[0][0])) - const all = [[['0', 'K_A', 'xa9', '0', 'â']], true, [['K_A', 'xa9', '0', 'NCAPS', 'â']]] - console.log("all", all) - console.log(" all[0", all[0]) - console.log(" values[0", values[0]) - - console.log(" all[1", all[1]) - console.log(" values[1", values[1]) - console.log(" all[2", all[2]) - console.log(" values[2", values[2]) - const new2 = JSON.stringify(values[2]) - console.log("new2 ", typeof (new2), new2) - console.log("new2[0] ", new2[0]) - console.log("new2[1] ", new2[1]) - console.log("new2[0][0] ", new2[0][0]) - - - - - console.log("values_values ", values) - console.log("values[0] ", values[0]) - // console.log("values[0][0] ", String(values[0][0])) - console.log("values[1] ", values[1]) - console.log("values[2] ", values[2]) - console.log(" ",)*/ - - - - /* let outstring = "[ "; - for (let i = 0; i < values[1].length; i++) { - outstring = outstring + "[ '" + values[1][i][0] + "', " + values[1][i][1].toString() + "], " - }*/ - // it("'" + values[0] + "'" + ' should return ' + outstring.substring(0, outstring.lastIndexOf(']') + 2) + " ]", async function () { - it("'" + values[0] + "'" + ' should return ' + values[1], async function () { - //const result = converter.get_KeyMapModiKeyArray__from__array(read, values[0], values[1]); - //assert.equal(JSON.stringify(result), JSON.stringify(values[1])); - assert.equal(0, 0); - }); - }) - }) - + const isCaps_used = true + const string_in = "get_KeyMapModiKeyArray__from__array(['" + "', '" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "', '" + values[0][0][3] + "', '" + values[0][0][4] + "'])" + const string_out = "['" + "', '" + values[1][0][0] + "', '" + values[1][0][1] + "', '" + values[1][0][2] + "', '" + values[1][0][3] + "', '" + values[1][0][4] + "']" + it((JSON.stringify(values[1]).length > 60) ? 'an array of objects should return an array of objectss' : + string_in.padEnd(74, " ") + ' should return ' + string_out, async function () { + const result = sut.get_KeyMapModiKeyArray__from__array(read, values[0], isCaps_used); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); + // isCaps_used === false; input defined + [[[['49', 'K_SPACE', 'a0', '0', 'ˆ']], [['K_SPACE', 'a0', '0', '', 'ˆ']]], + [[['49', 'K_SPACE', 'a0', '0', '']], [['K_SPACE', 'a0', '0', '', '']]], + [[['', 'K_SPACE', 'a0', '0', 'ˆ']], [['K_SPACE', 'a0', '0', '', 'ˆ']]], + [[['', '', '', '', '']], [['', '', '', '', '']]], + ].forEach(function (values) { - //----------------------------------------------------------------------------------------------------------------------- - // OK test writeData_Stores - describe("writeData_Stores() ", function () { + const isCaps_used = false + const string_in = "get_KeyMapModiKeyArray__from__array(['" + "', '" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "', '" + values[0][0][3] + "', '" + values[0][0][4] + "'])" + const string_out = "['" + "', '" + values[1][0][0] + "', '" + values[1][0][1] + "', '" + values[1][0][2] + "', '" + values[1][0][3] + "', '" + values[1][0][4] + "']" - const written_correct = converter.writeData_Stores(converted) + it(string_in.padEnd(74, " ") + ' should return ' + string_out, async function () { + const result = sut.get_KeyMapModiKeyArray__from__array(read, values[0], isCaps_used); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); - const converted_empty = converter.convert(converter.read("")); - const written_empty = converter.writeData_Stores(converted_empty) + // isCaps_used === true; input undefined/null/empty + [[[], []], + [undefined, []], + [null, []], + ].forEach(function (values) { + const isCaps = true + it(("get_KeyMapModiKeyArray__from__array([" + values[0] + "])").padEnd(74, " ") + ' should return ' + "[" + values[1] + "]", async function () { + const result = sut.get_KeyMapModiKeyArray__from__array(read, values[0], isCaps); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); + }) - const converted_onlyName = converter.convert(converter.read("")); - converted_onlyName.keylayout_filename = "X.keylayout" - const written_onlyName = converter.writeData_Stores(converted_onlyName) + describe("writeData_Stores() ", function () { const out_expected_first: string = "c ......................................................................\n" @@ -566,69 +534,63 @@ describe('KeylayoutToKmnConverter', function () { + "group(main) using keys\n\n" + "\n" - - - - - it('should return store text with filename on correct input', async function () { - assert.equal(written_correct, (out_expected_first + converted.keylayout_filename + out_expected_last)); + it(('writeData_Stores should return store text with filename ').padEnd(62, " ") + 'on correct input', async function () { + const written_correctName = sut.writeData_Stores(converted) + assert.equal(written_correctName, (out_expected_first + converted.keylayout_filename + out_expected_last)); }); - it('should return store text without filename on empty input', async function () { - assert.equal(written_empty, (out_expected_first + out_expected_last)); + it(('writeData_Stores should return store text without filename ').padEnd(62, " ") + 'on empty input', async function () { + const written_emptyName = sut.writeData_Stores(converted_empty) + assert.equal(written_emptyName, (out_expected_first + out_expected_last)); }); - it('should return store text without filename on only filename as input', async function () { - assert.equal(written_onlyName, (out_expected_first + converted_onlyName.keylayout_filename + out_expected_last)); + it(('writeData_Stores should return store text without filename ').padEnd(62, " ") + 'on only filename as input', async function () { + const written_onlyName = sut.writeData_Stores(converted_unavailable) + assert.equal(written_onlyName, (out_expected_first + converted_unavailable.keylayout_filename + out_expected_last)); }); }) - //---------------------------------------------------------------------------------------------------------------------- - // test get_ActionID_Output_array__From__ActionID_State describe("get_ActionID_Output_array__From__ActionID_State ", function () { - [ - ["1", [ - ['a0', '1', 'ˆ'], - ['a1', '1', 'Â'], - ['a10', '1', 'ê'], - ['a11', '1', 'î'], - ['a13', '1', 'ô'], - ['a14', '1', 'û'], - ['a2', '1', 'Ê'], - ['a3', '1', 'Î'], - ['a5', '1', 'Ô'], - ['a6', '1', 'Û'], - ['a9', '1', 'â']],], - ["2", [ - ['a0', '2', '`'], - ['a1', '2', 'À'], - ['a10', '2', 'è'], - ['a11', '2', 'ì'], - ['a13', '2', 'ò'], - ['a14', '2', 'ù'], - ['a2', '2', 'È'], - ['a3', '2', 'Ì'], - ['a5', '2', 'Ò'], - ['a6', '2', 'Ù'], - ['a9', '2', 'à']],], - ["789", [],], - ["", [],], - [" ", [],], - [123, [],], - [null, [],], - [undefined, [],], + [["1", [ + ['a0', '1', 'ˆ'], + ['a1', '1', 'Â'], + ['a10', '1', 'ê'], + ['a11', '1', 'î'], + ['a13', '1', 'ô'], + ['a14', '1', 'û'], + ['a2', '1', 'Ê'], + ['a3', '1', 'Î'], + ['a5', '1', 'Ô'], + ['a6', '1', 'Û'], + ['a9', '1', 'â']],], + ["2", [ + ['a0', '2', '`'], + ['a1', '2', 'À'], + ['a10', '2', 'è'], + ['a11', '2', 'ì'], + ['a13', '2', 'ò'], + ['a14', '2', 'ù'], + ['a2', '2', 'È'], + ['a3', '2', 'Ì'], + ['a5', '2', 'Ò'], + ['a6', '2', 'Ù'], + ['a9', '2', 'à']],], + ["789", [],], + ["", [],], + [" ", [],], + [123, [],], + [null, [],], + [undefined, [],], ].forEach(function (values) { it((JSON.stringify(values[1]).length > 30) ? - ("'" + values[0] + "'").padEnd(11, " ") + ' should return an array of object' : - ("'" + values[0] + "'").padEnd(11, " ") + ' should return ' + "'" + JSON.stringify(values[1]) + "'", async function () { - const result = converter.get_ActionID_Output_array__From__ActionID_State(read, String(values[0])); + ("get_ActionID_Output_array__From__ActionID_State('" + values[0] + "')").padEnd(60, " ") + ' should return an array of objects' : + ("get_ActionID_Output_array__From__ActionID_State('" + values[0] + "')").padEnd(60, " ") + ' should return ' + "'" + JSON.stringify(values[1]) + "'", async function () { + const result = sut.get_ActionID_Output_array__From__ActionID_State(read, String(values[0])); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }) }) - //----------------------------------------------------------------------------------------------------------------------- - // test get_Datat_array2D__From__ActionID_stateOutput describe("get_Datat_array2D__From__ActionID_stateOutput ", function () { [ ["a1", "A", true, [ @@ -652,25 +614,14 @@ describe('KeylayoutToKmnConverter', function () { ].forEach(function (values) { it((JSON.stringify(values[3]).length > 35) ? - ("get_Datat_array2D__From__ActionID_stateOutput('" + values[0] + "', '" + values[1] + "', " + values[2] + ")").padEnd(67, " ") + ' should return an array of object' : + ("get_Datat_array2D__From__ActionID_stateOutput('" + values[0] + "', '" + values[1] + "', " + values[2] + ")").padEnd(67, " ") + ' should return an array of objects' : ("get_Datat_array2D__From__ActionID_stateOutput('" + values[0] + "', '" + values[1] + "', " + values[2] + ")").padEnd(67, " ") + ' should return ' + "'" + JSON.stringify(values[3]) + "'", async function () { - const result = converter.get_Datat_array2D__From__ActionID_stateOutput(read, converted.arrayOf_Modifiers, String(values[0]), String(values[1]), Boolean(values[2])) + const result = sut.get_Datat_array2D__From__ActionID_stateOutput(read, converted.arrayOf_Modifiers, String(values[0]), String(values[1]), Boolean(values[2])) assert.equal(JSON.stringify(result), JSON.stringify(values[3])); }); }) }) - //----------------------------------------------------------------------------------------------------------------------- - /*const inputFilename9 = makePathToFixture('../data/Italian_copy.keylayout'); - const converter9 = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - //const sut9 = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const read9 = converter9.read(inputFilename9); - const converted9 = converter9.convert(read9); - console.log("converted9 ", typeof (converted9))*/ - - - - // test get_KeyMap_Code_array__From__KeyMap_Action_array2D describe("get_KeyMap_Code_array__From__KeyMap_Action_array2D ", function () { const b6_actionId_arr = [ @@ -710,67 +661,66 @@ describe('KeylayoutToKmnConverter', function () { ['32', 'K_U', 'a6', '2', 'Û'], ['0', 'K_A', 'a9', '0', 'â'] ]; - const oneEntryResult = - [["49", "K_SPACE", "a0", "0", "ˆ"], + + [[b6_actionId_arr, b1_keycode_arr], + ].forEach(function (values) { + it(("get_KeyMap_Code_array__From__KeyMap_Action_array2D([['" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "'],..])").padEnd(73, " ") + ' should return an array of objects', async function () { + const result = sut.get_KeyMap_Code_array__From__KeyMap_Action_array2D(read, values[0]) + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); + + //----------------- + const oneEntryResult = [ + ["49", "K_SPACE", "a0", "0", "ˆ"], ["49", "K_SPACE", "a0", "1", "ˆ"], ["49", "K_SPACE", "a0", "2", "ˆ"], ["6", "K_Z", "a0", "4", "ˆ"], ["25", "K_9", "a0", "4", "ˆ"], ["43", "K_COMMA", "a0", "4", "ˆ"], ["49", "K_SPACE", "a0", "7", "ˆ"] - ]; - const oneEntryResultNoOutput = - [["49", "K_SPACE", "a0", "0", ""], + ]; + const oneEntryResultNoOutput = [ + ["49", "K_SPACE", "a0", "0", ""], ["49", "K_SPACE", "a0", "1", ""], ["49", "K_SPACE", "a0", "2", ""], ["6", "K_Z", "a0", "4", ""], ["25", "K_9", "a0", "4", ""], ["43", "K_COMMA", "a0", "4", ""], ["49", "K_SPACE", "a0", "7", ""] - ]; + ]; - [ - [b6_actionId_arr, b1_keycode_arr], - [[['a0', '1', 'ˆ']], oneEntryResult], - [[['a0', '1', '']], oneEntryResultNoOutput], - [[['a0', '', 'ˆ']], oneEntryResult], - [[['', '1', 'ˆ']], []], - [[['', '', '']], []], - [[[' ', ' ', '']], []], - [[], []], - [undefined, []], - [null, []], + [[[['a0', '1', 'ˆ']], oneEntryResult], + [[['a0', '1', '']], oneEntryResultNoOutput], + [[['a0', '', 'ˆ']], oneEntryResult], ].forEach(function (values) { - it(((values[0] === undefined) || (values.some(function (value) { return value === null })) || (values[0].length === 0)) ? - ("get_KeyMap_Code_array__From__KeyMap_Action_array2D(" + values[0] + ")").padEnd(73, " ") + ' should return ' + "'[" + values[1] + "]'" - : (JSON.stringify(values[1]).length > 35) ? - (values[0].length > 0) ? - ("get_KeyMap_Code_array__From__KeyMap_Action_array2D([['" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "'],..])").padEnd(73, " ") + ' should return an array of object' - : ("get_KeyMap_Code_array__From__KeyMap_Action_array2D(['" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "'])").padEnd(73, " ") + ' should return an array of object' - : ("get_KeyMap_Code_array__From__KeyMap_Action_array2D(['" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "'])").padEnd(73, " ") + ' should return ' + "'[" + values[1] + "]'", async function () { - const result = converter.get_KeyMap_Code_array__From__KeyMap_Action_array2D(read, values[0]) - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); - }); - }) - }) - - //----------------------------------------------------------------------------------------------------------------------- + it(("get_KeyMap_Code_array__From__KeyMap_Action_array2D(['" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "'])").padEnd(73, " ") + ' should return an array of objects', async function () { + const result = sut.get_KeyMap_Code_array__From__KeyMap_Action_array2D(read, values[0]) + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); - // todo test for all public func for all "return paths" - // todo check input null + //----------------- + [[[['', '1', 'ˆ']], []], + [[['', '', '']], []], + [[[' ', ' ', '']], []], + ].forEach(function (values) { + it(("get_KeyMap_Code_array__From__KeyMap_Action_array2D(['" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "'])").padEnd(73, " ") + ' should return ' + "'[" + values[1] + "]'", async function () { + const result = sut.get_KeyMap_Code_array__From__KeyMap_Action_array2D(read, values[0]) + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); - // test createRuleData - // test reviewRules - // test writeData_Rules - //----------------------------------------------------------------------------------------------------------------------- - // ToDo remove - describe("END ", function () { - it('################################################## TESTs DONE ####################################################################################################', async function () { - assert.equal(0, 0); + //----------------- + [[[], []], + [undefined, []], + [null, []], + ].forEach(function (values) { + it(("get_KeyMap_Code_array__From__KeyMap_Action_array2D(" + values[0] + ")").padEnd(73, " ") + ' should return ' + "'[" + values[1] + "]'", async function () { + const result = sut.get_KeyMap_Code_array__From__KeyMap_Action_array2D(read, values[0]) + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); }); }) - - - }); From 794db98409a74f00d07563675fab8c02e34116df Mon Sep 17 00:00:00 2001 From: Sabine Date: Mon, 17 Mar 2025 11:04:13 +0100 Subject: [PATCH 064/251] feat(developer): comment out first occurance+write out later occurance of a rule MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit if a rule is ambiguous i.e. if it is a C0/C1 rule and has an abiguous C2 or C3 rule we comment out the C0/C1 rule and only use the C2 or C3 rule c WARNING + [CAPS K_EQUAL] > 'ì' (C0/C1) + [CAPS K_EQUAL] > dk(A3) (C2 or C3) --- .../keylayout-to-kmn-converter.ts | 113 ++++++++++++++---- .../test/test-keylayout-to-kmn-converter.ts | 4 +- 2 files changed, 94 insertions(+), 23 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 1987f0d3038..1f8a90417fa 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -812,18 +812,20 @@ export class KeylayoutToKmnConverter { public get_KeyMapModiKeyArray__from__array(data: any, search: (boolean | string)[][], isCAPSused: boolean): string[][] { const returnarray: string[][] = [] - for (let i = 0; i < search.length; i++) { - const behaviour: number = Number(search[i][3]) - - for (let j = 0; j < data.keyboard.modifierMap.keyMapSelect[behaviour].modifier.length; j++) { - const returnarray1D: string[] = [] - returnarray1D.push(String(search[i][1])) /* KeyName*/ - returnarray1D.push(String(search[i][2])) /* actionId*/ - returnarray1D.push(String(search[i][3])) /* behaviour*/ - returnarray1D.push(String(this.create_kmn_modifier(data.keyboard.modifierMap.keyMapSelect[behaviour].modifier[j]['@_keys'], isCAPSused))) /* modifier */ - returnarray1D.push(String(search[i][4])) /* char*/ - if (returnarray1D.length > 0) { - returnarray.push(returnarray1D) + if (!((search === undefined) || (search === null) || (search.length === 0))) { + for (let i = 0; i < search.length; i++) { + const behaviour: number = Number(search[i][3]) + + for (let j = 0; j < data.keyboard.modifierMap.keyMapSelect[behaviour].modifier.length; j++) { + const returnarray1D: string[] = [] + returnarray1D.push(String(search[i][1])) /* KeyName*/ + returnarray1D.push(String(search[i][2])) /* actionId*/ + returnarray1D.push(String(search[i][3])) /* behaviour*/ + returnarray1D.push(String(this.create_kmn_modifier(data.keyboard.modifierMap.keyMapSelect[behaviour].modifier[j]['@_keys'], isCAPSused))) /* modifier */ + returnarray1D.push(String(search[i][4])) /* char*/ + if (returnarray1D.length > 0) { + returnarray.push(returnarray1D) + } } } } @@ -993,7 +995,7 @@ export class KeylayoutToKmnConverter { add_modifier = "RCTRL "; } else if ((modifier_state[i].toUpperCase() === "LEFTOPTION") || (modifier_state[i].toUpperCase() === "LOPTION")) { - add_modifier = "RALT "; + add_modifier = "LALT "; } else if ((modifier_state[i].toUpperCase() === "RIGHTOPTION") || (modifier_state[i].toUpperCase() === "ROPTION")) { add_modifier = "RALT "; @@ -1133,6 +1135,52 @@ export class KeylayoutToKmnConverter { && idx < index ); + // 4-1 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > 'Ñ' + const amb_4_1 = rule.filter((curr, idx) => + ((curr.rule_type === "C3")) + && curr.modifier_prev_deadkey === rule[index].modifier_key + && curr.prev_deadkey === rule[index].key + ); + if (amb_4_1.length > 0) { + this.writeDataset(amb_4_1) + + if (amb_4_1.length > 0) { + warningTextArray[2] = warningTextArray[2] + + ("XXXXX NEW C01 ThirdTEXT " + + "ambiguous 4-1 rule: later: [" + + amb_4_1[0].modifier_prev_deadkey + + " " + + amb_4_1[0].prev_deadkey + + "] > dk(C" + + amb_4_1[0].unique_prev_deadkey + + ") here: ") + } + console.log("warningTextArray ", warningTextArray); + } + + // 2-1 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > 'Ñ' + const amb_2_1 = rule.filter((curr, idx) => + ((curr.rule_type === "C2")) + && curr.modifier_deadkey === rule[index].modifier_key + && curr.deadkey === rule[index].key + ); + if (amb_2_1.length > 0) { + this.writeDataset(amb_2_1) + + if (amb_2_1.length > 0) { + warningTextArray[2] = warningTextArray[2] + + ("XXXXX NEW C01 ThirdTEXT " + + "ambiguous 2-1 rule: later: [" + + amb_2_1[0].modifier_deadkey + + " " + + amb_2_1[0].deadkey + + "] > dk(A" + + amb_2_1[0].unique_deadkey + + ") here: ") + } + console.log("warningTextArray ", warningTextArray); + } +// Todo 1-1 text [ if (amb_1_1.length > 0) { warningTextArray[2] = warningTextArray[2] + ("C1 ambiguous 1-1 rule: earlier: [" @@ -1198,15 +1246,38 @@ export class KeylayoutToKmnConverter { && idx < index ); - //1-2 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > 'Ñ' + /* //1-2 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > 'Ñ' const amb_1_2 = rule.filter((curr, idx) => ((curr.rule_type === "C0") || (curr.rule_type === "C1")) && curr.modifier_key === rule[index].modifier_deadkey && curr.key === rule[index].deadkey //&& rule[index].unique_deadkey === 0 // include and the first occurance will be printed //&& (idx < index) // include and the first occurance will be printed + );*/ + + // 4-2 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(B11) + const amb_4_2 = rule.filter((curr, idx) => + ((curr.rule_type === "C3")) + && curr.modifier_prev_deadkey === rule[index].modifier_deadkey + && curr.prev_deadkey === rule[index].deadkey + && curr.id_prev_deadkey === rule[index].id_deadkey + // && rule[index].unique_prev_deadkey === 0 // include and the first occurance will be printed + // && (idx < index) ); + if (amb_4_2.length > 0) { + warningTextArray[0] = warningTextArray[0] + + ("C2 XXX FIRSTTEXT " + + "ambiguous 4-2 rule: later: [" + + amb_4_2[0].modifier_prev_deadkey + + " " + + amb_4_2[0].prev_deadkey + + "] > dk(C" + + amb_4_2[0].id_prev_deadkey + + ") here: ") + } + + if (amb_2_2.length > 0) { warningTextArray[1] = warningTextArray[1] + ("C2 SECONDTEXT " @@ -1255,7 +1326,7 @@ export class KeylayoutToKmnConverter { + new TextDecoder().decode(dup_3_3[0].output) + "\' here: ") } - if (amb_1_2.length > 0) { + /* if (amb_1_2.length > 0) { warningTextArray[1] = warningTextArray[1] + ("C2 SECONDTEXT " + "ambiguous 1-2 rule: earlier: [" @@ -1265,19 +1336,19 @@ export class KeylayoutToKmnConverter { + "] > \'" + new TextDecoder().decode(amb_1_2[0].output) + "\' here: ") - } + }*/ } if (rule[index].rule_type === "C3") { - // 1-4 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > 'Ñ' + /* // 1-4 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > 'Ñ' const amb_1_4 = rule.filter((curr, idx) => ((curr.rule_type === "C0") || (curr.rule_type === "C1")) && curr.modifier_key === rule[index].modifier_prev_deadkey && curr.key === rule[index].prev_deadkey //&& rule[index].unique_prev_deadkey === 0 // include and the first occurance will be printed //&& (idx < index) - ); + );*/ // 2-4 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(B11) const amb_2_4 = rule.filter((curr, idx) => @@ -1375,7 +1446,7 @@ export class KeylayoutToKmnConverter { //&& idx < index ); - if (amb_1_4.length > 0) { + /*if (amb_1_4.length > 0) { warningTextArray[0] = warningTextArray[0] + ("C3 FIRSTTEXT " + "ambiguous 1-4 rule: earlier(Todo check if print out or not): [" @@ -1385,7 +1456,7 @@ export class KeylayoutToKmnConverter { + "] > \'" + new TextDecoder().decode(amb_1_4[0].output) + "\' here: ") - } + }*/ if (amb_2_4.length > 0) { warningTextArray[0] = warningTextArray[0] @@ -1745,7 +1816,7 @@ export class KeylayoutToKmnConverter { ) { data += warn_text[0] - + " [" + + "+ [" + (unique_data_Rules[k].modifier_prev_deadkey + " " + unique_data_Rules[k].prev_deadkey).trim() //+ "] > dk(A" + "] > dk(C" diff --git a/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts index e9f1b2dd075..dfef040ddf7 100644 --- a/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts @@ -210,8 +210,8 @@ describe('KeylayoutToKmnConverter', function () { ['riGhtsHift', true, 'NCAPS SHIFT'], ['LEFTCONTROL', true, 'NCAPS LCTRL'], ['RCONTROL', true, 'NCAPS RCTRL'], - ['leftoption', true, 'NCAPS RALT'], - ['loption', true, 'NCAPS RALT'], + ['leftoption', true, 'NCAPS LALT'], + ['loption', true, 'NCAPS LALT'], ].forEach(function (values) { it(('should convert "' + values[0] + '"').padEnd(36, " ") + 'to "' + values[2] + '"', async function () { const result = sut.create_kmn_modifier(values[0] as string, values[1] as boolean); From 454b0359cb17bbe5f03dbed26542458e3a4b9f1f Mon Sep 17 00:00:00 2001 From: Sabine Date: Mon, 17 Mar 2025 16:25:32 +0100 Subject: [PATCH 065/251] feat(developer): add semicolon where needed; function names --- .../keylayout-to-kmn-converter.ts | 732 +++++++++--------- .../test/test-keylayout-to-kmn-converter.ts | 94 +-- 2 files changed, 412 insertions(+), 414 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 1f8a90417fa..16095bdcb39 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -88,15 +88,15 @@ import { ConverterToKmnArtifacts } from "../converter-artifacts.js"; // OK test write // test createRuleData // OK test get_KeyMap_Code_array__From__KeyMap_Action -// OK test get_KeyMap_Code_array__From__KeyMap_Action_array2D -// OK test get_ActionID_Index__From__ActionID_Id -// OK test get_ActionID_Id__From__ActionID_next -// OK test get_ActionID_Output_array__From__ActionID_State -// OK test get_Action2ID_NoneOutput__From__ActionID_Id -// OK test get_KeyMapModiKeyArray__from__array -// OK test get_Datat_array2D__From__ActionID_stateOutput -// OK test get_KeyMap_Code_array__From__ActionID_Action -// OK test get_KeyMap_Modifier_array__From__behaviour_arr +// OK test get_KeyActionOutput_array__From__ActionStateOutput_array +// OK test get_ActionIndex__From__ActionId +// OK test get_ActionID__From__ActionNext +// OK test get_ActionStateOutput_array__From__ActionState +// OK test get_Output__From__ActionId_None +// OK test get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array +// OK test get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput +// OK test get_KeyModifier_array__From__ActionID +// OK test get_Modifier_array__From__KeyModifier_array // OK test create_kmn_modifier // OK test checkIfCapsIsUsed // OK test isAcceptableKeymanModifier @@ -126,6 +126,7 @@ function boxArrays(source: any) { boxXmlArray(source?.actions, 'action'); for (const action of source?.actions?.action) { boxXmlArray(action, 'when'); + } return source; } @@ -159,14 +160,14 @@ export class KeylayoutToKmnConverter { static readonly INPUT_FILE_EXTENSION = '.keylayout'; static readonly OUTPUT_FILE_EXTENSION = '.kmn'; - static readonly USED_KEYS_COUNT = 51 + static readonly USED_KEYS_COUNT = 51; // TODO use callbacks what about /*private*/ for options //constructor(/*private*/ _callbacks: CompilerCallbacks, /*private*/ _options: CompilerOptions) { constructor(private callbacks: CompilerCallbacks, options: CompilerOptions) { // TODO: if these are needed, uncomment /*private*/ and remove _, and they will then // be available as class properties - } + }; /** * @brief member function to run read/convert/write @@ -181,7 +182,7 @@ export class KeylayoutToKmnConverter { } console.log(' _S2 first READ file ........................................in:', inputFilename); - const jsonO: object = this.read(inputFilename) + const jsonO: object = this.read(inputFilename); if (!jsonO) { throw new Error('read() not OK'); // new SAB @@ -198,7 +199,7 @@ export class KeylayoutToKmnConverter { console.log(' _S2 then WRITE to kmn .....................................'); - const out_text: boolean = this.write(outArray) + const out_text: boolean = this.write(outArray); if (!out_text) { throw new Error('write() not OK'); // new SAB return null; @@ -207,7 +208,7 @@ export class KeylayoutToKmnConverter { // TODO throws console.log(';;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; FINISHED OK ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;'); //throw new Error('Not finished yet'); // new SAB - return null // new SAB + return null; // new SAB } /** @@ -216,8 +217,8 @@ export class KeylayoutToKmnConverter { * @param filename the ukelele .keylayout-file to be converted * @return in case of success Uint8Array keys_all_Layers; else null */ public read(filename: string): Object { - let xmlFile - let jsonObj = [] + let xmlFile; + let jsonObj = []; const options = { ignoreAttributes: false, @@ -233,9 +234,9 @@ export class KeylayoutToKmnConverter { } catch { // Todo how to break correctly; return what?? - console.log(" FILE NOT FOUND") + console.log(" FILE NOT FOUND"); } - return jsonObj + return jsonObj; } @@ -248,9 +249,9 @@ export class KeylayoutToKmnConverter { */ public convert(jsonObj: any): convert_object { - const modifierBehavior: string[][] = [] // modifier for each keymapselect - const rule_object: rule_object[] = [] // an array of objects which hold data for a kmn rule - const jsonObj_any: any = jsonObj + const modifierBehavior: string[][] = []; // modifier for each keymapselect + const rule_object: rule_object[] = []; // an array of objects which hold data for a kmn rule + const jsonObj_any: any = jsonObj; const data_object: convert_object = { keylayout_filename: "", @@ -260,22 +261,22 @@ export class KeylayoutToKmnConverter { if (jsonObj_any.hasOwnProperty("keyboard")) { - data_object.keylayout_filename = jsonObj_any.keyboard['@_name'] + ".keylayout" - data_object.arrayOf_Modifiers = modifierBehavior // ukelele uses behaviours e.g. 18 modifiersCombinations in 8 KeyMapSelect(behaviors) - data_object.arrayOf_Rules = rule_object + data_object.keylayout_filename = jsonObj_any.keyboard['@_name'] + ".keylayout"; + data_object.arrayOf_Modifiers = modifierBehavior; // ukelele uses behaviours e.g. 18 modifiersCombinations in 8 KeyMapSelect(behaviors) + data_object.arrayOf_Rules = rule_object; // create an array of modifier combinations (e.g. shift? leftShift caps? ) and store in data_object for (let j = 0; j < jsonObj.keyboard.modifierMap.keyMapSelect.length; j++) { - const singleModifierSet: string[] = [] + const singleModifierSet: string[] = []; for (let k = 0; k < jsonObj.keyboard.modifierMap.keyMapSelect[j].modifier.length; k++) { - singleModifierSet.push(jsonObj.keyboard.modifierMap.keyMapSelect[j].modifier[k]['@_keys']) + singleModifierSet.push(jsonObj.keyboard.modifierMap.keyMapSelect[j].modifier[k]['@_keys']); } - modifierBehavior.push(singleModifierSet) + modifierBehavior.push(singleModifierSet); } // fill rules into arrayOf_Rules of data_object - return this.createRuleData(data_object, jsonObj) + return this.createRuleData(data_object, jsonObj); } - return data_object + return data_object; } /** @@ -286,24 +287,24 @@ export class KeylayoutToKmnConverter { //TODO need to use export const USVirtualKeyCodes here public write(data_ukelele: convert_object): boolean { - let data: string = "\n" + let data: string = "\n"; // TODO use path also // const savename = "data//" + data_ukelele.keylayout_filename.substring(0, data_ukelele.keylayout_filename.lastIndexOf(".")) + ".kmn" // add top part of kmn file: STORES - data += this.writeData_Stores(data_ukelele) + data += this.writeData_Stores(data_ukelele); // add bottom part of kmn file: RULES - data += this.writeData_Rules(data_ukelele) + data += this.writeData_Rules(data_ukelele); try { - this.callbacks.fs.writeFileSync("data/MyResult.kmn", new TextEncoder().encode(data)) + this.callbacks.fs.writeFileSync("data/MyResult.kmn", new TextEncoder().encode(data)); //this.callbacks.fs.writeFileSync(savename, new TextEncoder().encode(data)) return true; } catch (err) { - console.log('Error writing kmn file:' + err.message) - return false + console.log('Error writing kmn file:' + err.message); + return false; } } @@ -313,13 +314,13 @@ export class KeylayoutToKmnConverter { // for more info about mapping and cases C0-C4 see https://docs.google.com/document/d/12J3NGO6RxIthCpZDTR8FYSRjiMgXJDLwPY2z9xqKzJ0/edit?tab=t.0#heading=h.g7jwx3lx0ydd public createRuleData(data_ukelele: convert_object, jsonObj: any): convert_object { - const object_array: rule_object[] = [] - let dk_counter_C3_A: number = 0 - let dk_counter_C2: number = 0 - let action_id: string + const object_array: rule_object[] = []; + let dk_counter_C3_A: number = 0; + let dk_counter_C2: number = 0; + let action_id: string; // check if we use CAPS in a modifier. In this case we need to add NCAPS - const isCapsused: boolean = this.checkIfCapsIsUsed(data_ukelele.arrayOf_Modifiers) + const isCapsused: boolean = this.checkIfCapsIsUsed(data_ukelele.arrayOf_Modifiers); // loop keys 0-50 (= all keys we use) for (let j = 0; j < KeylayoutToKmnConverter.USED_KEYS_COUNT; j++) { @@ -327,7 +328,7 @@ export class KeylayoutToKmnConverter { // loop behaviors (in ukelele it is possible to define multiple modifier combinations that behave in the same way) for (let i = 0; i < jsonObj.keyboard.keyMapSet[0].keyMap.length; i++) { - let rule_obj: rule_object + let rule_obj: rule_object; // ............................................................................................................................... // case C0: output ............................................................................................................... @@ -359,9 +360,9 @@ export class KeylayoutToKmnConverter { /* modifier_key*/ this.create_kmn_modifier(data_ukelele.arrayOf_Modifiers[i][l], isCapsused), /* key */ this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), /* output */ new TextEncoder().encode(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output']), - ) + ); if (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] !== "") { - object_array.push(rule_obj) + object_array.push(rule_obj); } } } @@ -369,7 +370,7 @@ export class KeylayoutToKmnConverter { } else if (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] !== undefined) { - action_id = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] + action_id = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action']; // ............................................................................................................................... // case C1: action + state none + output ......................................................................................... // C1 see: https://docs.google.com/document/d/12J3NGO6RxIthCpZDTR8FYSRjiMgXJDLwPY2z9xqKzJ0/edit?tab=t.0#heading=h.g7jwx3lx0ydd ... @@ -380,12 +381,12 @@ export class KeylayoutToKmnConverter { for (let l = 0; l < data_ukelele.arrayOf_Modifiers[i].length; l++) { - if ((this.get_Action2ID_NoneOutput__From__ActionID_Id(jsonObj, action_id) !== undefined) - && (this.get_Action2ID_NoneOutput__From__ActionID_Id(jsonObj, action_id) !== "")) { + if ((this.get_Output__From__ActionId_None(jsonObj, action_id) !== undefined) + && (this.get_Output__From__ActionId_None(jsonObj, action_id) !== "")) { - const outputchar: string = this.get_Action2ID_NoneOutput__From__ActionID_Id(jsonObj, action_id) + const outputchar: string = this.get_Output__From__ActionId_None(jsonObj, action_id); const b1_modifierKey_arr: string[][] = - this.get_Datat_array2D__From__ActionID_stateOutput(jsonObj, data_ukelele.arrayOf_Modifiers, action_id, outputchar, isCapsused) + this.get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput(jsonObj, data_ukelele.arrayOf_Modifiers, action_id, outputchar, isCapsused); for (let m = 0; m < b1_modifierKey_arr.length; m++) { @@ -405,10 +406,10 @@ export class KeylayoutToKmnConverter { /* modifier_key*/ b1_modifierKey_arr[m][5], /* key */ b1_modifierKey_arr[m][4], /* output */ new TextEncoder().encode(outputchar) - ) + ); // ToDo "undefined" or undefined ???? // if (b1_modifierKey_arr[n4][4] !== "undefined") { - object_array.push(rule_obj) + object_array.push(rule_obj); } } } @@ -422,7 +423,7 @@ export class KeylayoutToKmnConverter { // https://docs.google.com/document/d/12J3NGO6RxIthCpZDTR8FYSRjiMgXJDLwPY2z9xqKzJ0/edit?tab=t.0#heading=h.g7jwx3lx0ydd ......... // ............................................................................................................................... - const b1_actionIndex: number = this.get_ActionID_Index__From__ActionID_Id(jsonObj, action_id) + const b1_actionIndex: number = this.get_ActionIndex__From__ActionId(jsonObj, action_id); // with action_id from above loop all 'action' and search for a state(none)-next-pair ............................................................................................................ // e.g. in Block 5: find for action id a18 ...................................................................................................................... @@ -432,28 +433,28 @@ export class KeylayoutToKmnConverter { // Data of Block Nr 5 ..................................................................................................................................................................... // of this state(none)-next-pair get value of next (next="1") ............................................................................................................................. - /* eg: 1 */ const b5_value_next: string = jsonObj.keyboard.actions.action[b1_actionIndex].when[l]['@_next'] + /* eg: 1 */ const b5_value_next: string = jsonObj.keyboard.actions.action[b1_actionIndex].when[l]['@_next']; // ........................................................................................................................................................................................ // Data of Block Nr 4 ..................................................................................................................................................................... // with present action_id (a18) find all keycode-behaviour-pairs that use this action (a18) => (keymapIndex 0/keycode 24 and keymapIndex 3/keycode 24) .................................... // from these create an array of modifier combinations e.g. [['','caps?'], ['Caps']] ..................................................................................................... - /* eg: [['24', 0], ['24', 3]] */ const b4_deadkey_arr: number[][] = this.get_KeyMap_Code_array__From__ActionID_Action(jsonObj, action_id) - /* e.g. [['','caps?'], ['Caps']]*/ const b4_deadkeyModifier_arr: string[] = this.get_KeyMap_Modifier_array__From__behaviour_arr(data_ukelele.arrayOf_Modifiers, b4_deadkey_arr) + /* eg: [['24', 0], ['24', 3]] */ const b4_deadkey_arr: number[][] = this.get_KeyModifier_array__From__ActionID(jsonObj, action_id); + /* e.g. [['','caps?'], ['Caps']]*/ const b4_deadkeyModifier_arr: string[] = this.get_Modifier_array__From__KeyModifier_array(data_ukelele.arrayOf_Modifiers, b4_deadkey_arr); // ........................................................................................................................................................................................ // Data of Block Nr 6 ..................................................................................................................................................................... // create an array[action id,state,output] from all state-output-pairs that use state = b5_value_next (e.g. use 1 in ) ...................................... - /* eg: [ 'a9','1','â'] */ const b6_actionId_arr: string[][] = this.get_ActionID_Output_array__From__ActionID_State(jsonObj, b5_value_next) + /* eg: [ 'a9','1','â'] */ const b6_actionId_arr: string[][] = this.get_ActionStateOutput_array__From__ActionState(jsonObj, b5_value_next); // ........................................................................................................................................................................................ // Data of Block Nr 1 .................................................................................................................................................................... // create array[Keycode,Keyname,action id,actionIndex,output] and array[Keyname,action id,behaviour,modifier,output] ...................................................................... - /* eg: ['0','K_A','a9','0','â'] */ const b1_keycode_arr: string[][] = this.get_KeyMap_Code_array__From__KeyMap_Action_array2D(jsonObj, b6_actionId_arr) - /* eg: ['K_A','a9','0','NCAPS','â']*/ const b1_modifierKey_arr: string[][] = this.get_KeyMapModiKeyArray__from__array(jsonObj, b1_keycode_arr, isCapsused) + /* eg: ['0','K_A','a9','0','â'] */ const b1_keycode_arr: string[][] = this.get_KeyActionOutput_array__From__ActionStateOutput_array(jsonObj, b6_actionId_arr); + /* eg: ['K_A','a9','0','NCAPS','â']*/ const b1_modifierKey_arr: string[][] = this.get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(jsonObj, b1_keycode_arr, isCapsused); // ....................................................................................................................................................................................... for (let n1 = 0; n1 < b4_deadkeyModifier_arr.length; n1++) { @@ -477,11 +478,11 @@ export class KeylayoutToKmnConverter { /* modifier_key*/ b1_modifierKey_arr[n4][3], /* key */ b1_modifierKey_arr[n4][0], /* output */ new TextEncoder().encode(b1_modifierKey_arr[n4][4]), - ) + ); // ToDo "undefined" or undefined ???? if (b1_modifierKey_arr[n4][4] !== "undefined") { //if (b1_modifierKey_arr[n4][4] !== undefined) { - object_array.push(rule_obj) + object_array.push(rule_obj); } } } @@ -509,37 +510,37 @@ export class KeylayoutToKmnConverter { // Data of Block Nr 5 ........................................................................................................................................................................ // of this state-next-pair get value of next (next="1") and state="3" ........................................................................................................................ - /* e.g. state = 3 */ const b5_value_state: string = jsonObj.keyboard.actions.action[b1_actionIndex].when[l]['@_state'] - /* e.g. next = 1 */ const b5_value_next: string = jsonObj.keyboard.actions.action[b1_actionIndex].when[l]['@_next'] + /* e.g. state = 3 */ const b5_value_state: string = jsonObj.keyboard.actions.action[b1_actionIndex].when[l]['@_state']; + /* e.g. next = 1 */ const b5_value_next: string = jsonObj.keyboard.actions.action[b1_actionIndex].when[l]['@_next']; // ........................................................................................................................................................................................... // Data of Block Nr 4 ........................................................................................................................................................................ // with present action_id (a16) find all keycode-behaviour-pairs that use this action (a16) => (keymapIndex 3/keycode 32) .................................................................... // from these create an array of modifier combinations e.g. [ [ 'anyOption', 'Caps' ] ] ..................................................................................................... - /* e.g. [['32', 3]] */ const b4_deadkey_arr: number[][] = this.get_KeyMap_Code_array__From__ActionID_Action(jsonObj, action_id) - /* e.g. [ [ 'anyOption', 'Caps' ] ]*/ const b4_deadkeyModifier_arr: string[] = this.get_KeyMap_Modifier_array__From__behaviour_arr(data_ukelele.arrayOf_Modifiers, b4_deadkey_arr) + /* e.g. [['32', 3]] */ const b4_deadkey_arr: number[][] = this.get_KeyModifier_array__From__ActionID(jsonObj, action_id); + /* e.g. [ [ 'anyOption', 'Caps' ] ]*/ const b4_deadkeyModifier_arr: string[] = this.get_Modifier_array__From__KeyModifier_array(data_ukelele.arrayOf_Modifiers, b4_deadkey_arr); // ........................................................................................................................................................................................... // Data of Block Nr 3 ........................................................................................................................................................................ // get an action id from a state-output-pair that use state = b5_value_state (e.g. use 3 in ) ................................................................. - /* e.g. actioniD = a17 */ const b3_actionId: string = this.get_ActionID_Id__From__ActionID_next(jsonObj, b5_value_state) + /* e.g. actioniD = a17 */ const b3_actionId: string = this.get_ActionID__From__ActionNext(jsonObj, b5_value_state); // ........................................................................................................................................................................................... // Data of Block Nr 2 ....................................................................................................................................................................... // with present action_id (a17) find all keynames and behaviours that use this action (a17) => (keymapIndex 3/keycode 28) .................................................................... // from these create an array of modifier combinations e.g. [ [ 'anyOption', 'Caps' ] ] ..................................................................................................... - /* eg: index=3 */ const b2_prev_deadkey_arr: number[][] = this.get_KeyMap_Code_array__From__ActionID_Action(jsonObj, String(b3_actionId)) // concersion not neccessary - /* e.g. [ [ 'anyOption', 'Caps' ] ] */ const b2_prev_deadkeyModifier_arr: string[] = this.get_KeyMap_Modifier_array__From__behaviour_arr(data_ukelele.arrayOf_Modifiers, b2_prev_deadkey_arr) + /* eg: index=3 */ const b2_prev_deadkey_arr: number[][] = this.get_KeyModifier_array__From__ActionID(jsonObj, String(b3_actionId)); // concersion not neccessary + /* e.g. [ [ 'anyOption', 'Caps' ] ] */ const b2_prev_deadkeyModifier_arr: string[] = this.get_Modifier_array__From__KeyModifier_array(data_ukelele.arrayOf_Modifiers, b2_prev_deadkey_arr); // ........................................................................................................................................................................................... // Data of Block Nr 6 ........................................................................................................................................................................ // create an array[action id,state,output] from all state-output-pairs that use state = b5_value_next (e.g. use 1 in ) ......................................... - /* eg:[ [ 'a9','1','â'] ]*/ const b6_actionId_arr: string[][] = this.get_ActionID_Output_array__From__ActionID_State(jsonObj, b5_value_next) + /* eg:[ [ 'a9','1','â'] ]*/ const b6_actionId_arr: string[][] = this.get_ActionStateOutput_array__From__ActionState(jsonObj, b5_value_next); // ........................................................................................................................................................................................... // Data of Block Nr 1 ....................................................................................................................................................................... // create array[Keycode,Keyname,action id,actionIndex,output] and array[Keyname,action id,behaviour,modifier,output] ......................................................................... - /* eg: ['49','K_SPACE','a0','0','Â'] */ const b1_keycode_arr: string[][] = this.get_KeyMap_Code_array__From__KeyMap_Action_array2D(jsonObj, b6_actionId_arr) - /* eg: ['K_SPACE','a0','0','NCAPS','Â'] */ const b1_modifierKey_arr: string[][] = this.get_KeyMapModiKeyArray__from__array(jsonObj, b1_keycode_arr, isCapsused) + /* eg: ['49','K_SPACE','a0','0','Â'] */ const b1_keycode_arr: string[][] = this.get_KeyActionOutput_array__From__ActionStateOutput_array(jsonObj, b6_actionId_arr); + /* eg: ['K_SPACE','a0','0','NCAPS','Â'] */ const b1_modifierKey_arr: string[][] = this.get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(jsonObj, b1_keycode_arr, isCapsused); // ........................................................................................................................................................................................... for (let n1 = 0; n1 < b2_prev_deadkeyModifier_arr.length; n1++) { @@ -565,11 +566,11 @@ export class KeylayoutToKmnConverter { /* modifier_key*/ b1_modifierKey_arr[n7][3], /* key */ b1_modifierKey_arr[n7][0], /* output */ new TextEncoder().encode(b1_modifierKey_arr[n7][4]), - ) + ); // ToDo "undefined" or undefined ???? if (b1_modifierKey_arr[n7][4] !== undefined) { - object_array.push(rule_obj) + object_array.push(rule_obj); } } } @@ -581,7 +582,7 @@ export class KeylayoutToKmnConverter { } } } else { - console.log("ERROR : some entries are not available") + console.log("ERROR : some entries are not available"); } } } @@ -592,79 +593,79 @@ export class KeylayoutToKmnConverter { // then compare to object_array and mark first occurance of a rule in object_array // -------------------------------------------------------------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------------------------------------------------------------- - let unique_dkB_count = 0 - const list_of_unique_Text2_rules: string[][] = [] + let unique_dkB_count = 0; + const list_of_unique_Text2_rules: string[][] = []; //this.writeDataset(object_array) //------------------------------------ C2: dk ---------------------------------- // first rule is always unique - object_array[0].unique_deadkey = unique_dkB_count - object_array[0].id_deadkey = unique_dkB_count - unique_dkB_count++ + object_array[0].unique_deadkey = unique_dkB_count; + object_array[0].id_deadkey = unique_dkB_count; + unique_dkB_count++; for (let i = 0; i < object_array.length; i++) { if ((object_array[i].modifier_deadkey !== "") && (object_array[i].deadkey !== "")) { - let isFirstUsedHere_dk: boolean = true + let isFirstUsedHere_dk: boolean = true; // check if not used before for (let j = 0; j < i; j++) { if ((object_array[i].modifier_deadkey === object_array[j].modifier_deadkey) && (object_array[i].deadkey === object_array[j].deadkey)) { - isFirstUsedHere_dk = isFirstUsedHere_dk && false + isFirstUsedHere_dk = isFirstUsedHere_dk && false; } } if (isFirstUsedHere_dk) { - const ruleArray: string[] = [] - object_array[i].unique_deadkey = unique_dkB_count - ruleArray.push(object_array[i].modifier_deadkey) - ruleArray.push(object_array[i].deadkey) - ruleArray.push(String(unique_dkB_count)) - unique_dkB_count++ - list_of_unique_Text2_rules.push(ruleArray) + const ruleArray: string[] = []; + object_array[i].unique_deadkey = unique_dkB_count; + ruleArray.push(object_array[i].modifier_deadkey); + ruleArray.push(object_array[i].deadkey); + ruleArray.push(String(unique_dkB_count)); + unique_dkB_count++; + list_of_unique_Text2_rules.push(ruleArray); } } } //----------------------------------- C3: prev-dk ---------------------------------- - let unique_dkA_count = 0 + let unique_dkA_count = 0; // first rule is always unique - object_array[0].unique_prev_deadkey = unique_dkA_count - unique_dkA_count++ + object_array[0].unique_prev_deadkey = unique_dkA_count; + unique_dkA_count++; for (let i = 0; i < object_array.length; i++) { if ((object_array[i].modifier_prev_deadkey !== "") && (object_array[i].prev_deadkey !== "")) { - let isFirstUsedHere_prev_dk: boolean = true + let isFirstUsedHere_prev_dk: boolean = true; // check if not used before for (let j = 0; j < i; j++) { if ((object_array[i].modifier_prev_deadkey === object_array[j].modifier_prev_deadkey) && (object_array[i].prev_deadkey === object_array[j].prev_deadkey)) { - isFirstUsedHere_prev_dk = isFirstUsedHere_prev_dk && false + isFirstUsedHere_prev_dk = isFirstUsedHere_prev_dk && false; } } // check if first part of C3 rule contains already defined rule of C2 if (isFirstUsedHere_prev_dk) { - object_array[i].unique_prev_deadkey = unique_dkA_count - unique_dkA_count++ + object_array[i].unique_prev_deadkey = unique_dkA_count; + unique_dkA_count++; for (let k = 0; k < list_of_unique_Text2_rules.length; k++) { if ((list_of_unique_Text2_rules[k][0] === object_array[i].modifier_deadkey) && ((list_of_unique_Text2_rules[k][1] === object_array[i].deadkey))) { - object_array[i].unique_deadkey = Number(list_of_unique_Text2_rules[k][2]) + object_array[i].unique_deadkey = Number(list_of_unique_Text2_rules[k][2]); } } } if (isFirstUsedHere_prev_dk) { - const ruleArray: string[] = [] - object_array[i].unique_deadkey = unique_dkB_count - ruleArray.push(object_array[i].modifier_prev_deadkey) - ruleArray.push(object_array[i].prev_deadkey) - ruleArray.push(String(unique_dkB_count)) - unique_dkB_count++ - list_of_unique_Text2_rules.push(ruleArray) + const ruleArray: string[] = []; + object_array[i].unique_deadkey = unique_dkB_count; + ruleArray.push(object_array[i].modifier_prev_deadkey); + ruleArray.push(object_array[i].prev_deadkey); + ruleArray.push(String(unique_dkB_count)); + unique_dkB_count++; + list_of_unique_Text2_rules.push(ruleArray); } } @@ -674,15 +675,15 @@ export class KeylayoutToKmnConverter { for (let i = 0; i < object_array.length; i++) { for (let j = 0; j < list_of_unique_Text2_rules.length; j++) { if ((object_array[i].modifier_prev_deadkey === list_of_unique_Text2_rules[j][0]) && (object_array[i].prev_deadkey === list_of_unique_Text2_rules[j][1])) { - object_array[i].id_prev_deadkey = Number(list_of_unique_Text2_rules[j][2]) + object_array[i].id_prev_deadkey = Number(list_of_unique_Text2_rules[j][2]); } if ((object_array[i].modifier_deadkey === list_of_unique_Text2_rules[j][0]) && (object_array[i].deadkey === list_of_unique_Text2_rules[j][1])) { - object_array[i].id_deadkey = Number(list_of_unique_Text2_rules[j][2]) + object_array[i].id_deadkey = Number(list_of_unique_Text2_rules[j][2]); } } } - data_ukelele.arrayOf_Rules = object_array - return data_ukelele + data_ukelele.arrayOf_Rules = object_array; + return data_ukelele; } @@ -690,36 +691,36 @@ export class KeylayoutToKmnConverter { // --------------------------------------------------------------------------------------------------------------------- /** - * @brief loop through data, find the actionID in search and and return array of [Keycode,Keyname,actionId,actionIDIndex, output] + * @brief loop through data and and return array of [Keycode,Keyname,actionId,actionIDIndex, output] for a given actionID * @param data :any - an object containing all data read from a .keylayout file * @param search :string[][] - array of [ actionID,state,output] * @return a string[][] containing [Keycode,Keyname,actionId,actionIDIndex, output] */ - public get_KeyMap_Code_array__From__KeyMap_Action_array2D(data: any, search: string[][]): string[][] { + public get_KeyActionOutput_array__From__ActionStateOutput_array(data: any, search: string[][]): string[][] { if ((search === undefined) || (search === null)) - return [] + return []; - const returnarray2D: string[][] = [] + const returnarray2D: string[][] = []; for (let k = 0; k < search.length; k++) { for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { - const returnarray: string[] = [] + const returnarray: string[] = []; if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search[k][0] && data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'] < KeylayoutToKmnConverter.USED_KEYS_COUNT) { - returnarray.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']) - returnarray.push(this.map_UkeleleKC_To_VK(Number(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']))) - returnarray.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action']) - returnarray.push(data.keyboard.keyMapSet[0].keyMap[i]['@_index']) - returnarray.push(search[k][2]) + returnarray.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']); + returnarray.push(this.map_UkeleleKC_To_VK(Number(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']))); + returnarray.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action']); + returnarray.push(data.keyboard.keyMapSet[0].keyMap[i]['@_index']); + returnarray.push(search[k][2]); } if (returnarray.length > 0) { - returnarray2D.push(returnarray) + returnarray2D.push(returnarray); } } } } - return returnarray2D + return returnarray2D; } /** @@ -728,13 +729,13 @@ export class KeylayoutToKmnConverter { * @param search :string - value next to be found * @return a number containing the index of an actionId */ - public get_ActionID_Index__From__ActionID_Id(data: any, search: string): number { + public get_ActionIndex__From__ActionId(data: any, search: string): number { for (let i = 0; i < data.keyboard.actions.action.length; i++) { if (data.keyboard.actions.action[i]['@_id'] === search) { - return i + return i; } } - return 0 + return 0; } /** @@ -743,17 +744,17 @@ export class KeylayoutToKmnConverter { * @param search :string value next to be found * @return a string containing the actionId of a certain state-next pair */ - public get_ActionID_Id__From__ActionID_next(data: any, search: string): string { + public get_ActionID__From__ActionNext(data: any, search: string): string { if (search !== "none") { for (let i = 0; i < data.keyboard.actions.action.length; i++) { for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { if (data.keyboard.actions.action[i].when[j]['@_next'] === search) { - return data.keyboard.actions.action[i]['@_id'] + return data.keyboard.actions.action[i]['@_id']; } } } } - return "" + return ""; } /** @@ -762,23 +763,23 @@ export class KeylayoutToKmnConverter { * @param search : string a state to be found * @return an array: string[][] containing all [actionId, state, output] for a certain state */ - public get_ActionID_Output_array__From__ActionID_State(data: any, search: string): string[][] { - const returnarray2D: string[][] = [] + public get_ActionStateOutput_array__From__ActionState(data: any, search: string): string[][] { + const returnarray2D: string[][] = []; for (let i = 0; i < data.keyboard.actions.action.length; i++) { for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { - const returnarray: string[] = [] + const returnarray: string[] = []; if ((data.keyboard.actions.action[i].when[j]['@_state'] === search)) { - returnarray.push(data.keyboard.actions.action[i]['@_id']) - returnarray.push(data.keyboard.actions.action[i].when[j]['@_state']) - returnarray.push(data.keyboard.actions.action[i].when[j]['@_output']) + returnarray.push(data.keyboard.actions.action[i]['@_id']); + returnarray.push(data.keyboard.actions.action[i].when[j]['@_state']); + returnarray.push(data.keyboard.actions.action[i].when[j]['@_output']); } if (returnarray.length > 0) { - returnarray2D.push(returnarray) + returnarray2D.push(returnarray); } } } - return returnarray2D + return returnarray2D; } /** @@ -787,19 +788,19 @@ export class KeylayoutToKmnConverter { * @param search :string an actionId to be found * @return a string containing the output character */ - public get_Action2ID_NoneOutput__From__ActionID_Id(data: any, search: string): string { - let OutputValue: string = "" + public get_Output__From__ActionId_None(data: any, search: string): string { + let OutputValue: string = ""; for (let i = 0; i < data.keyboard.actions.action.length; i++) { if (data.keyboard.actions.action[i]['@_id'] === search) { for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { if (data.keyboard.actions.action[i].when[j]['@_state'] === "none") { - OutputValue = data.keyboard.actions.action[i].when[j]['@_output'] + OutputValue = data.keyboard.actions.action[i].when[j]['@_output']; } } } } - return OutputValue + return OutputValue; } /** @@ -809,22 +810,22 @@ export class KeylayoutToKmnConverter { * @param isCAPSused : boolean flag to indicate if CAPS is used in a keylayout file or not * @return an array: string[][] containing [KeyName,actionId,behaviour,modifier,output] */ - public get_KeyMapModiKeyArray__from__array(data: any, search: (boolean | string)[][], isCAPSused: boolean): string[][] { - const returnarray: string[][] = [] + public get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(data: any, search: (boolean | string)[][], isCAPSused: boolean): string[][] { + const returnarray: string[][] = []; if (!((search === undefined) || (search === null) || (search.length === 0))) { for (let i = 0; i < search.length; i++) { - const behaviour: number = Number(search[i][3]) + const behaviour: number = Number(search[i][3]); for (let j = 0; j < data.keyboard.modifierMap.keyMapSelect[behaviour].modifier.length; j++) { - const returnarray1D: string[] = [] - returnarray1D.push(String(search[i][1])) /* KeyName*/ - returnarray1D.push(String(search[i][2])) /* actionId*/ - returnarray1D.push(String(search[i][3])) /* behaviour*/ - returnarray1D.push(String(this.create_kmn_modifier(data.keyboard.modifierMap.keyMapSelect[behaviour].modifier[j]['@_keys'], isCAPSused))) /* modifier */ - returnarray1D.push(String(search[i][4])) /* char*/ + const returnarray1D: string[] = []; + returnarray1D.push(String(search[i][1])); /* KeyName*/ + returnarray1D.push(String(search[i][2])); /* actionId*/ + returnarray1D.push(String(search[i][3])); /* behaviour*/ + returnarray1D.push(String(this.create_kmn_modifier(data.keyboard.modifierMap.keyMapSelect[behaviour].modifier[j]['@_keys'], isCAPSused))); /* modifier */ + returnarray1D.push(String(search[i][4])); /* char*/ if (returnarray1D.length > 0) { - returnarray.push(returnarray1D) + returnarray.push(returnarray1D); } } } @@ -840,11 +841,11 @@ export class KeylayoutToKmnConverter { }, [[], new Set()], ); - return unique_returnarray + return unique_returnarray; } /** - * @brief loop through data and create an array of [actionID,output,actionID, behaviour,keyname,modifier] for a given actionId + * @brief loop through data and create an array of [actionID, output, behaviour,keyname,modifier] for a given actionId * @param data : any - an object containing all data read from a .keylayout file * @param modi : any - an array of modifiers * @param search : string - an actionId to be found @@ -852,11 +853,11 @@ export class KeylayoutToKmnConverter { * @param isCAPSused : boolean - flag to indicate if CAPS is used in a keylayout file or not * @return an array: string[][] containing [actionID,output,actionID, behaviour,keyname,modifier] */ - public get_Datat_array2D__From__ActionID_stateOutput(data: any, modi: any, search: string, outchar: string, isCapsused: boolean): string[][] { - const returnarray2D: string[][] = [] + public get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput(data: any, modi: any, search: string, outchar: string, isCapsused: boolean): string[][] { + const returnarray2D: string[][] = []; if ((search === "") || (search === undefined) || !((isCapsused === true) || (isCapsused === false))) { - return [] + return []; } // loop behaviors ( in ukelele it is possible to define multiple modifier combinations that behave in the same) @@ -864,20 +865,20 @@ export class KeylayoutToKmnConverter { for (let j = 0; j < KeylayoutToKmnConverter.USED_KEYS_COUNT; j++) { if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { for (let k = 0; k < modi[data.keyboard.keyMapSet[0].keyMap[i]['@_index']].length; k++) { - const returnarray: string[] = [] - const behaviour: string = data.keyboard.keyMapSet[0].keyMap[i]['@_index'] - const modifierkmn: string = this.create_kmn_modifier(modi[behaviour][k], isCapsused) - const keyName: string = this.map_UkeleleKC_To_VK(Number(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])) - - returnarray.push(search) - returnarray.push(outchar) - returnarray.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action']) - returnarray.push(behaviour) - returnarray.push(keyName) - returnarray.push(modifierkmn) + const returnarray: string[] = []; + const behaviour: string = data.keyboard.keyMapSet[0].keyMap[i]['@_index']; + const modifierkmn: string = this.create_kmn_modifier(modi[behaviour][k], isCapsused); + const keyName: string = this.map_UkeleleKC_To_VK(Number(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])); + + returnarray.push(search); + returnarray.push(outchar); + returnarray.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action']); + returnarray.push(behaviour); + returnarray.push(keyName); + returnarray.push(modifierkmn); if (returnarray.length > 0) { - returnarray2D.push(returnarray) + returnarray2D.push(returnarray); } } } @@ -895,30 +896,30 @@ export class KeylayoutToKmnConverter { [[], new Set()], ); - return unique_returnarray + return unique_returnarray; } /** - * @brief loop through data and create an array of [keycode,modifier] for a given actionId + * @brief loop through data and create an array of [keycode,behaviour] for a given actionId * @param data : any - an object containing all data read from a .keylayout file * @param search : string - an actionId to be found - * @return an array: number[][] containing [keycode,modifier] + * @return an array: number[][] containing [keycode,behaviour] */ - public get_KeyMap_Code_array__From__ActionID_Action(data: any, search: string): number[][] { - const mapIndexArray_2D: number[][] = [] + public get_KeyModifier_array__From__ActionID(data: any, search: string): number[][] { + const mapIndexArray_2D: number[][] = []; for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { for (let j = 0; j < KeylayoutToKmnConverter.USED_KEYS_COUNT; j++) { - const mapIndexArrayperKey: number[] = [] + const mapIndexArrayperKey: number[] = []; if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { - mapIndexArrayperKey.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']) - mapIndexArrayperKey.push(i) + mapIndexArrayperKey.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']); + mapIndexArrayperKey.push(i); } if (mapIndexArrayperKey.length > 0) { - mapIndexArray_2D.push(mapIndexArrayperKey) + mapIndexArray_2D.push(mapIndexArrayperKey); } } } - return mapIndexArray_2D + return mapIndexArray_2D; } /** @@ -927,12 +928,12 @@ export class KeylayoutToKmnConverter { * @param search : number[][] - an array[keycode,modifier] to be found * @return an array: string[] containing modifiers */ - public get_KeyMap_Modifier_array__From__behaviour_arr(data: any, search: (string | number)[][]): string[] { - const mapIndexArray_2D: string[] = [] + public get_Modifier_array__From__KeyModifier_array(data: any, search: (string | number)[][]): string[] { + const mapIndexArray_2D: string[] = []; for (let i = 0; i < search.length; i++) { - mapIndexArray_2D.push(data[search[i][1]]) + mapIndexArray_2D.push(data[search[i][1]]); } - return mapIndexArray_2D + return mapIndexArray_2D; } /** @@ -942,9 +943,9 @@ export class KeylayoutToKmnConverter { * @return string - a modifier value suitable to use in a .kmn-file */ public create_kmn_modifier(keylayout_modifier: string, isCAPSused: boolean): string { - let add_modifier: string = "" - let kmn_modifier: string = "" - let kmn_ncaps: string = "" + let add_modifier: string = ""; + let kmn_modifier: string = ""; + let kmn_ncaps: string = ""; // copy each modifier seperate element of array const modifier_state: string[] = keylayout_modifier.split(" "); @@ -952,7 +953,7 @@ export class KeylayoutToKmnConverter { for (let i = 0; i < modifier_state.length; i++) { if (isCAPSused && (keylayout_modifier).toUpperCase().indexOf("CAPS") === -1) { - kmn_ncaps = " NCAPS " + kmn_ncaps = " NCAPS "; } // if we find a modifier containing a '?' e.g. SHIFT?: => SHIFT is not neccessary. If it is not neccessary we don`t write this modifier @@ -1004,17 +1005,17 @@ export class KeylayoutToKmnConverter { add_modifier = "RALT "; } else { - add_modifier = String(modifier_state[i]) + " " + add_modifier = String(modifier_state[i]) + " "; } - kmn_modifier += kmn_ncaps + add_modifier + kmn_modifier += kmn_ncaps + add_modifier; } // remove duplicate and empty entries - const duplicate_modifier_array: string[] = kmn_modifier.split(" ").filter(item => item) + const duplicate_modifier_array: string[] = kmn_modifier.split(" ").filter(item => item); const unique_modifier: string[] = duplicate_modifier_array.filter(function (item, pos, self) { return self.indexOf(item) === pos; - }) - return unique_modifier.flat().toString().replace(/,/g, " ") + }); + return unique_modifier.flat().toString().replace(/,/g, " "); } /** @@ -1024,7 +1025,7 @@ export class KeylayoutToKmnConverter { */ // TODO caps <-> Caps <-> cAPs,... public checkIfCapsIsUsed(keylayout_modifier: string[][]): boolean { - return JSON.stringify(keylayout_modifier).includes("caps") + return JSON.stringify(keylayout_modifier).includes("caps"); } /** @@ -1035,9 +1036,9 @@ export class KeylayoutToKmnConverter { */ public isAcceptableKeymanModifier(keylayout_modifier: string): boolean { if (keylayout_modifier === null) - return false + return false; - let iskKeymanModifier: boolean = true + let iskKeymanModifier: boolean = true; const modifier_single: string[] = keylayout_modifier.split(" "); for (let i = 0; i < modifier_single.length; i++) { @@ -1053,12 +1054,12 @@ export class KeylayoutToKmnConverter { || (modifier_single[i].toUpperCase() === "RCTRL") || (modifier_single[i].toUpperCase() === "") ) { - iskKeymanModifier &&= true + iskKeymanModifier &&= true; } else { - iskKeymanModifier &&= false + iskKeymanModifier &&= false; } } - return iskKeymanModifier + return iskKeymanModifier; } /** @@ -1079,28 +1080,28 @@ export class KeylayoutToKmnConverter { // Todo remoce C1-C3's and other markers if ((rule[index].rule_type === "C0") || (rule[index].rule_type === "C1")) { if (!this.isAcceptableKeymanModifier(rule[index].modifier_key)) { - warningTextArray[2] = "C1 unavailable modifier : " + warningTextArray[2] = "C1 unavailable modifier : "; } } else if (rule[index].rule_type === "C2") { if (!this.isAcceptableKeymanModifier(rule[index].modifier_deadkey)) { - warningTextArray[1] = "C2 unavailable modifier : " + warningTextArray[1] = "C2 unavailable modifier : "; } if (!this.isAcceptableKeymanModifier(rule[index].modifier_key)) { - warningTextArray[2] = "C2 unavailable modifier : " + warningTextArray[2] = "C2 unavailable modifier : "; } } else if (rule[index].rule_type === "C3") { if (!this.isAcceptableKeymanModifier(rule[index].modifier_prev_deadkey)) { - warningTextArray[2] = "C3 unavailable modifier : " + warningTextArray[2] = "C3 unavailable modifier : "; } if (!this.isAcceptableKeymanModifier(rule[index].modifier_deadkey)) { - warningTextArray[1] = "C3 unavailable modifier : " + warningTextArray[1] = "C3 unavailable modifier : "; } if (!this.isAcceptableKeymanModifier(rule[index].modifier_key)) { - warningTextArray[0] = "C3 unavailable modifier : " + warningTextArray[0] = "C3 unavailable modifier : "; } } @@ -1141,9 +1142,6 @@ export class KeylayoutToKmnConverter { && curr.modifier_prev_deadkey === rule[index].modifier_key && curr.prev_deadkey === rule[index].key ); - if (amb_4_1.length > 0) { - this.writeDataset(amb_4_1) - if (amb_4_1.length > 0) { warningTextArray[2] = warningTextArray[2] + ("XXXXX NEW C01 ThirdTEXT " @@ -1153,34 +1151,28 @@ export class KeylayoutToKmnConverter { + amb_4_1[0].prev_deadkey + "] > dk(C" + amb_4_1[0].unique_prev_deadkey - + ") here: ") + + ") here: "); } - console.log("warningTextArray ", warningTextArray); - } - - // 2-1 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > 'Ñ' - const amb_2_1 = rule.filter((curr, idx) => - ((curr.rule_type === "C2")) - && curr.modifier_deadkey === rule[index].modifier_key - && curr.deadkey === rule[index].key - ); - if (amb_2_1.length > 0) { - this.writeDataset(amb_2_1) - - if (amb_2_1.length > 0) { - warningTextArray[2] = warningTextArray[2] - + ("XXXXX NEW C01 ThirdTEXT " - + "ambiguous 2-1 rule: later: [" - + amb_2_1[0].modifier_deadkey - + " " - + amb_2_1[0].deadkey - + "] > dk(A" - + amb_2_1[0].unique_deadkey - + ") here: ") - } - console.log("warningTextArray ", warningTextArray); - } -// Todo 1-1 text [ + + // 2-1 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > 'Ñ' + const amb_2_1 = rule.filter((curr, idx) => + ((curr.rule_type === "C2")) + && curr.modifier_deadkey === rule[index].modifier_key + && curr.deadkey === rule[index].key + ); + if (amb_2_1.length > 0) { + warningTextArray[2] = warningTextArray[2] + + ("XXXXX NEW C01 ThirdTEXT " + + "ambiguous 2-1 rule: later: [" + + amb_2_1[0].modifier_deadkey + + " " + + amb_2_1[0].deadkey + + "] > dk(A" + + amb_2_1[0].unique_deadkey + + ") here: "); + } + + // Todo 1-1 text [ if (amb_1_1.length > 0) { warningTextArray[2] = warningTextArray[2] + ("C1 ambiguous 1-1 rule: earlier: [" @@ -1189,7 +1181,7 @@ export class KeylayoutToKmnConverter { + amb_1_1[0].key + "] > \'" + new TextDecoder().decode(amb_1_1[0].output) - + "\' here: [") + + "\' here: ["); } if (dup_1_1.length > 0) { @@ -1200,7 +1192,7 @@ export class KeylayoutToKmnConverter { + dup_1_1[0].key + "] > \'" + new TextDecoder().decode(dup_1_1[0].output) - + "\' here: [") + + "\' here: ["); } } @@ -1246,14 +1238,14 @@ export class KeylayoutToKmnConverter { && idx < index ); - /* //1-2 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > 'Ñ' - const amb_1_2 = rule.filter((curr, idx) => - ((curr.rule_type === "C0") || (curr.rule_type === "C1")) - && curr.modifier_key === rule[index].modifier_deadkey - && curr.key === rule[index].deadkey - //&& rule[index].unique_deadkey === 0 // include and the first occurance will be printed - //&& (idx < index) // include and the first occurance will be printed - );*/ + /* //1-2 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > 'Ñ' + const amb_1_2 = rule.filter((curr, idx) => + ((curr.rule_type === "C0") || (curr.rule_type === "C1")) + && curr.modifier_key === rule[index].modifier_deadkey + && curr.key === rule[index].deadkey + //&& rule[index].unique_deadkey === 0 // include and the first occurance will be printed + //&& (idx < index) // include and the first occurance will be printed + );*/ // 4-2 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(B11) const amb_4_2 = rule.filter((curr, idx) => @@ -1274,7 +1266,7 @@ export class KeylayoutToKmnConverter { + amb_4_2[0].prev_deadkey + "] > dk(C" + amb_4_2[0].id_prev_deadkey - + ") here: ") + + ") here: "); } @@ -1287,7 +1279,7 @@ export class KeylayoutToKmnConverter { + amb_2_2[0].deadkey + "] > dk(C" + amb_2_2[0].id_deadkey - + ") here: ") + + ") here: "); } if (dup_2_2.length > 0) { warningTextArray[1] = warningTextArray[1] @@ -1298,7 +1290,7 @@ export class KeylayoutToKmnConverter { + dup_2_2[0].deadkey + "] > dk(C" + dup_2_2[0].id_deadkey - + ") here: ") + + ") here: "); } if (amb_3_3.length > 0) { warningTextArray[2] = warningTextArray[2] @@ -1311,7 +1303,7 @@ export class KeylayoutToKmnConverter { + amb_3_3[0].key + "] > \'" + new TextDecoder().decode(amb_3_3[0].output) - + "\' here: ") + + "\' here: "); } if (dup_3_3.length > 0) { warningTextArray[2] = warningTextArray[2] @@ -1324,31 +1316,31 @@ export class KeylayoutToKmnConverter { + dup_3_3[0].key + "] > \'" + new TextDecoder().decode(dup_3_3[0].output) - + "\' here: ") + + "\' here: "); } - /* if (amb_1_2.length > 0) { - warningTextArray[1] = warningTextArray[1] - + ("C2 SECONDTEXT " - + "ambiguous 1-2 rule: earlier: [" - + amb_1_2[0].modifier_key - + " " - + amb_1_2[0].key - + "] > \'" - + new TextDecoder().decode(amb_1_2[0].output) - + "\' here: ") - }*/ + /* if (amb_1_2.length > 0) { + warningTextArray[1] = warningTextArray[1] + + ("C2 SECONDTEXT " + + "ambiguous 1-2 rule: earlier: [" + + amb_1_2[0].modifier_key + + " " + + amb_1_2[0].key + + "] > \'" + + new TextDecoder().decode(amb_1_2[0].output) + + "\' here: ") + }*/ } if (rule[index].rule_type === "C3") { - /* // 1-4 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > 'Ñ' - const amb_1_4 = rule.filter((curr, idx) => - ((curr.rule_type === "C0") || (curr.rule_type === "C1")) - && curr.modifier_key === rule[index].modifier_prev_deadkey - && curr.key === rule[index].prev_deadkey - //&& rule[index].unique_prev_deadkey === 0 // include and the first occurance will be printed - //&& (idx < index) - );*/ + /* // 1-4 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > 'Ñ' + const amb_1_4 = rule.filter((curr, idx) => + ((curr.rule_type === "C0") || (curr.rule_type === "C1")) + && curr.modifier_key === rule[index].modifier_prev_deadkey + && curr.key === rule[index].prev_deadkey + //&& rule[index].unique_prev_deadkey === 0 // include and the first occurance will be printed + //&& (idx < index) + );*/ // 2-4 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(B11) const amb_2_4 = rule.filter((curr, idx) => @@ -1467,7 +1459,7 @@ export class KeylayoutToKmnConverter { + amb_2_4[0].deadkey + "] > dk(C" + amb_2_4[0].id_deadkey - + ") here: ") + + ") here: "); } if (amb_6_3.length > 0) { @@ -1481,7 +1473,7 @@ export class KeylayoutToKmnConverter { + amb_6_3[0].key + "] > \'" + new TextDecoder().decode(amb_6_3[0].output) - + "\' here: ") + + "\' here: "); } if (dup_6_3.length > 0) { @@ -1495,7 +1487,7 @@ export class KeylayoutToKmnConverter { + dup_6_3[0].key + "] > \'" + new TextDecoder().decode(dup_6_3[0].output) - + "\' here: ") + + "\' here: "); } if (amb_4_4.length > 0) { @@ -1507,7 +1499,7 @@ export class KeylayoutToKmnConverter { + amb_4_4[0].prev_deadkey + "] > dk(C" + amb_4_4[0].id_prev_deadkey - + ") here: ") + + ") here: "); } if (dup_4_4.length > 0) { @@ -1519,7 +1511,7 @@ export class KeylayoutToKmnConverter { + dup_4_4[0].prev_deadkey + "] > dk(C" + dup_4_4[0].id_prev_deadkey - + ") here: ") + + ") here: "); } if (amb_5_5.length > 0) { @@ -1533,7 +1525,7 @@ export class KeylayoutToKmnConverter { + amb_5_5[0].deadkey + "] > dk(B" + amb_5_5[0].id_deadkey - + ") here: ") + + ") here: "); } if (dup_5_5.length > 0) { @@ -1547,7 +1539,7 @@ export class KeylayoutToKmnConverter { + dup_5_5[0].deadkey + "] > dk(B" + dup_5_5[0].id_deadkey - + ") here: ") + + ") here: "); } if (amb_6_6.length > 0) { @@ -1561,7 +1553,7 @@ export class KeylayoutToKmnConverter { + amb_6_6[0].key + "] > \'" + new TextDecoder().decode(amb_6_6[0].output) - + "\' here: ") + + "\' here: "); } if (dup_6_6.length > 0) { @@ -1576,21 +1568,21 @@ export class KeylayoutToKmnConverter { + dup_6_6[0].key + "] > \'" + new TextDecoder().decode(dup_6_6[0].output) - + "\' here: ") + + "\' here: "); } } if (warningTextArray[0] !== "") { - warningTextArray[0] = "c WARNING: " + warningTextArray[0] + warningTextArray[0] = "c WARNING: " + warningTextArray[0]; } if (warningTextArray[1] !== "") { - warningTextArray[1] = "c WARNING: " + warningTextArray[1] + warningTextArray[1] = "c WARNING: " + warningTextArray[1]; } if (warningTextArray[2] !== "") { - warningTextArray[2] = "c WARNING: " + warningTextArray[2] + warningTextArray[2] = "c WARNING: " + warningTextArray[2]; } - return warningTextArray + return warningTextArray; } /** @@ -1601,62 +1593,62 @@ export class KeylayoutToKmnConverter { public map_UkeleleKC_To_VK(pos: number): string { // ukelele KC --> // VK_US - if (pos === 0x0A) return "K_BKQUOTE" /* ^ */ - else if (pos === 0x12) return "K_1" /* 1 */ - else if (pos === 0x13) return "K_2" /* 2 */ - else if (pos === 0x14) return "K_3" /* 3 */ - else if (pos === 0x15) return "K_4" /* 4 */ - else if (pos === 0x17) return "K_5" /* 5 */ - else if (pos === 0x16) return "K_6" /* 6 */ - else if (pos === 0x1A) return "K_7" /* 7 */ - else if (pos === 0x1C) return "K_8" /* 8 */ - else if (pos === 0x19) return "K_9" /* 9 */ - else if (pos === 0x1D) return "K_0" /* 0 */ - else if (pos === 0x1B) return "K_HYPHEN" /* ß */ - else if (pos === 0x18) return "K_EQUAL" /* ´ */ - - else if (pos === 0x0C) return "K_Q" /* Q */ - else if (pos === 0x0D) return "K_W" /* W */ - else if (pos === 0x0E) return "K_E" /* E */ - else if (pos === 0x0F) return "K_R" /* R */ - else if (pos === 0x11) return "K_T" /* T */ - else if (pos === 0x10) return "K_Y" /* Y */ - else if (pos === 0x20) return "K_U" /* U */ - else if (pos === 0x22) return "K_I" /* I */ - else if (pos === 0x1F) return "K_O" /* O */ - else if (pos === 0x23) return "K_P" /* P */ - else if (pos === 0x21) return "K_LBRKT" /* [ */ - else if (pos === 0x1E) return "K_RBRKT" /* ] */ - else if (pos === 0x31) return "K_SPACE" /* \ */ - else if (pos === 0x2A) return "K_BKSLASH" /* \ */ // 42 for ISO correct?? + if (pos === 0x0A) return "K_BKQUOTE"; /* ^ */ + else if (pos === 0x12) return "K_1"; /* 1 */ + else if (pos === 0x13) return "K_2"; /* 2 */ + else if (pos === 0x14) return "K_3"; /* 3 */ + else if (pos === 0x15) return "K_4"; /* 4 */ + else if (pos === 0x17) return "K_5"; /* 5 */ + else if (pos === 0x16) return "K_6"; /* 6 */ + else if (pos === 0x1A) return "K_7"; /* 7 */ + else if (pos === 0x1C) return "K_8"; /* 8 */ + else if (pos === 0x19) return "K_9"; /* 9 */ + else if (pos === 0x1D) return "K_0"; /* 0 */ + else if (pos === 0x1B) return "K_HYPHEN"; /* ß */ + else if (pos === 0x18) return "K_EQUAL"; /* ´ */ + + else if (pos === 0x0C) return "K_Q"; /* Q */ + else if (pos === 0x0D) return "K_W"; /* W */ + else if (pos === 0x0E) return "K_E"; /* E */ + else if (pos === 0x0F) return "K_R"; /* R */ + else if (pos === 0x11) return "K_T"; /* T */ + else if (pos === 0x10) return "K_Y"; /* Y */ + else if (pos === 0x20) return "K_U"; /* U */ + else if (pos === 0x22) return "K_I"; /* I */ + else if (pos === 0x1F) return "K_O"; /* O */ + else if (pos === 0x23) return "K_P"; /* P */ + else if (pos === 0x21) return "K_LBRKT"; /* [ */ + else if (pos === 0x1E) return "K_RBRKT"; /* ] */ + else if (pos === 0x31) return "K_SPACE"; /* \ */ + else if (pos === 0x2A) return "K_BKSLASH"; /* \ */ // 42 for ISO correct?? // else if (pos === 0x30) return "K_?C1" /* \ */ // 48 for ANSI correct?? - else if (pos === 0x00) return "K_A" /* A */ - else if (pos === 0x01) return "K_S" /* S */ - else if (pos === 0x02) return "K_D" /* D */ - else if (pos === 0x03) return "K_F" /* F */ - else if (pos === 0x05) return "K_G" /* G */ - else if (pos === 0x04) return "K_H" /* H */ - else if (pos === 0x26) return "K_J" /* J */ - else if (pos === 0x28) return "K_K" /* K */ - else if (pos === 0x25) return "K_L" /* L */ - else if (pos === 0x29) return "K_COLON" /* : */ - else if (pos === 0x27) return "K_QUOTE" /* " */ - - else if (pos === 0x23) return "K_oE2" /* | */ - else if (pos === 0x06) return "K_Z" /* Z */ - else if (pos === 0x07) return "K_X" /* X */ - else if (pos === 0x08) return "K_C" /* C */ - else if (pos === 0x09) return "K_V" /* V */ - else if (pos === 0x0B) return "K_B" /* B */ - else if (pos === 0x2D) return "K_N" /* N */ - else if (pos === 0x2E) return "K_M" /* M */ - else if (pos === 0x2B) return "K_COMMA" /* , */ - else if (pos === 0x2F) return "K_PERIOD" /* . */ - else if (pos === 0x2C) return "K_SLASH" /* / */ - - else if (pos === 0x24) return "K_ENTER" - else return "" + else if (pos === 0x00) return "K_A"; /* A */ + else if (pos === 0x01) return "K_S"; /* S */ + else if (pos === 0x02) return "K_D"; /* D */ + else if (pos === 0x03) return "K_F"; /* F */ + else if (pos === 0x05) return "K_G"; /* G */ + else if (pos === 0x04) return "K_H"; /* H */ + else if (pos === 0x26) return "K_J"; /* J */ + else if (pos === 0x28) return "K_K"; /* K */ + else if (pos === 0x25) return "K_L"; /* L */ + else if (pos === 0x29) return "K_COLON"; /* : */ + else if (pos === 0x27) return "K_QUOTE"; /* " */ + + else if (pos === 0x23) return "K_oE2"; /* | */ + else if (pos === 0x06) return "K_Z"; /* Z */ + else if (pos === 0x07) return "K_X"; /* X */ + else if (pos === 0x08) return "K_C"; /* C */ + else if (pos === 0x09) return "K_V"; /* V */ + else if (pos === 0x0B) return "K_B"; /* B */ + else if (pos === 0x2D) return "K_N"; /* N */ + else if (pos === 0x2E) return "K_M"; /* M */ + else if (pos === 0x2B) return "K_COMMA"; /* , */ + else if (pos === 0x2F) return "K_PERIOD"; /* . */ + else if (pos === 0x2C) return "K_SLASH"; /* / */ + + else if (pos === 0x24) return "K_ENTER"; + else return ""; } //---------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------- @@ -1670,13 +1662,13 @@ export class KeylayoutToKmnConverter { */ public writeData_Rules(data_ukelele: convert_object): string { - let data: string = "" + let data: string = ""; // filter array of all rules and remove duplicates const unique_data_Rules: rule_object[] = data_ukelele.arrayOf_Rules.filter((curr) => { return ((curr.output !== new TextEncoder().encode("") || curr.output !== undefined) - && (curr.rule_type === "C0") || (curr.rule_type === "C1") || (curr.rule_type === "C2") || (curr.rule_type === "C3")) + && (curr.rule_type === "C0") || (curr.rule_type === "C1") || (curr.rule_type === "C2") || (curr.rule_type === "C3")); }).reduce((unique, o) => { if (!unique.some((obj: { modifier_prev_deadkey: string; prev_deadkey: string; @@ -1720,24 +1712,24 @@ export class KeylayoutToKmnConverter { let keyNr: number = 0; for (let j = 0; j < KeylayoutToKmnConverter.USED_KEYS_COUNT; j++) { if (this.map_UkeleleKC_To_VK(j) === unique_data_Rules[k].key) { - keyNr = j - break + keyNr = j; + break; } } // skip keyNr 48 (K_TAB) and 36 (K_ENTER) if ((keyNr === 48) || (keyNr === 36)) { - continue + continue; } //--------------------------------------------------------------------------------------------- // add a line after rules of each key if ((k > 1) && (unique_data_Rules[k - 1].key !== unique_data_Rules[k].key) && (unique_data_Rules[k - 1].rule_type === unique_data_Rules[k].rule_type)) { - data += '\n' + data += '\n'; } - const warn_text = this.reviewRules(unique_data_Rules, k) + const warn_text = this.reviewRules(unique_data_Rules, k); // add a warning in front of rules that use unavailable modifiers or ambiguous rules // if warning contains duplicate rules we do not write out this rule (even if there are other warnings for the same rule) since that rule had been written before @@ -1750,13 +1742,13 @@ export class KeylayoutToKmnConverter { + (unique_data_Rules[k].modifier_key + ' ' + unique_data_Rules[k].key).trim() + `] > \'` + new TextDecoder().decode(unique_data_Rules[k].output) - + '\'\n' + + '\'\n'; } } } // Todo remove this marker - data += "\n c ########## C2 #################################################################\n" + data += "\n c ########## C2 #################################################################\n"; //................................................ C2 ................................................................... //................................................ C2 ................................................................... @@ -1765,7 +1757,7 @@ export class KeylayoutToKmnConverter { if (unique_data_Rules[k].rule_type === "C2") { - const warn_text = this.reviewRules(unique_data_Rules, k) + const warn_text = this.reviewRules(unique_data_Rules, k); //SECONDTEXT print // ToDo include condition again @@ -1776,7 +1768,7 @@ export class KeylayoutToKmnConverter { // + "] > dk(C" + "] > dk(A" + String(unique_data_Rules[k].id_deadkey) - + ")\n" + + ")\n"; } // THIRDTEXT print OK @@ -1790,9 +1782,9 @@ export class KeylayoutToKmnConverter { + " " + unique_data_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_data_Rules[k].output) - + "\'\n" + + "\'\n"; - data += "\n" + data += "\n"; } } } @@ -1801,12 +1793,12 @@ export class KeylayoutToKmnConverter { //................................................ C3 ................................................................... //................................................ C3 ................................................................... - data += "\nc ########## C3 #################################################################\n" + data += "\nc ########## C3 #################################################################\n"; for (let k = 0; k < unique_data_Rules.length; k++) { if (unique_data_Rules[k].rule_type === "C3") { - const warn_text = this.reviewRules(unique_data_Rules, k) + const warn_text = this.reviewRules(unique_data_Rules, k); // Todo somewhere (A12) <-> (C12) // ToDo include condition again // FIRSTTEXT print @@ -1820,7 +1812,7 @@ export class KeylayoutToKmnConverter { + (unique_data_Rules[k].modifier_prev_deadkey + " " + unique_data_Rules[k].prev_deadkey).trim() //+ "] > dk(A" + "] > dk(C" - + String(unique_data_Rules[k].id_prev_deadkey) + ")\n" + + String(unique_data_Rules[k].id_prev_deadkey) + ")\n"; } // ToDo include condition again @@ -1838,7 +1830,7 @@ export class KeylayoutToKmnConverter { + unique_data_Rules[k].deadkey + "] > dk(B" + String(unique_data_Rules[k].id_deadkey) - + ")\n" + + ")\n"; } // ToDo include condition again @@ -1854,17 +1846,17 @@ export class KeylayoutToKmnConverter { + unique_data_Rules[k].key + "] > \'" + new TextDecoder().decode(unique_data_Rules[k].output) - + "\'\n" + + "\'\n"; } // if ((warn_text[0].indexOf("duplicate") < 0) || (warn_text[1].indexOf("duplicate") < 0) || (warn_text[2].indexOf("duplicate") < 0)) { - data += "\n" + data += "\n"; // } } } - return data + return data; } /** @@ -1874,26 +1866,26 @@ export class KeylayoutToKmnConverter { */ public writeData_Stores(data_ukelele: convert_object): string { - let data: string = "" - data += "c ......................................................................\n" - data += "c ......................................................................\n" - data += "c Keyman keyboard generated by kmn-convert\n" - data += "c from Ukelele file: " + data_ukelele.keylayout_filename + "\n" - data += "c ......................................................................\n" - data += "c ......................................................................\n" - data += "\n" - - data += "store(&VERSION) \'10.0\'\n" - data += "store(&TARGETS) \'any\'\n" - data += "store(&KEYBOARDVERSION) \'1.0\'\n" - data += "store(©RIGHT) '© 2024 SIL International\'\n" - - data += "\n" - data += "begin Unicode > use(main)\n\n" - data += "group(main) using keys\n\n" - - data += "\n" - return data + let data: string = ""; + data += "c ......................................................................\n"; + data += "c ......................................................................\n"; + data += "c Keyman keyboard generated by kmn-convert\n"; + data += "c from Ukelele file: " + data_ukelele.keylayout_filename + "\n"; + data += "c ......................................................................\n"; + data += "c ......................................................................\n"; + data += "\n"; + + data += "store(&VERSION) \'10.0\'\n"; + data += "store(&TARGETS) \'any\'\n"; + data += "store(&KEYBOARDVERSION) \'1.0\'\n"; + data += "store(©RIGHT) '© 2024 SIL International\'\n"; + + data += "\n"; + data += "begin Unicode > use(main)\n\n"; + data += "group(main) using keys\n\n"; + + data += "\n"; + return data; } /// console log all entries C3 TODO remove @@ -1920,7 +1912,7 @@ export class KeylayoutToKmnConverter { (dataRules[i].key !== "" ? dataRules[i].key.padEnd(8, " ") : "--".padEnd(8, " ")), (new TextDecoder().decode(dataRules[i].output) !== "" ? new TextDecoder().decode(dataRules[i].output).padEnd(10, " ") : ("--" + dataRules[i].output) + "--"), - "| °°") + "| °°"); } } @@ -1946,7 +1938,7 @@ export class KeylayoutToKmnConverter { (dataRules.key !== "" ? dataRules.key.padEnd(8, " ") : "--".padEnd(8, " ")), (new TextDecoder().decode(dataRules.output) !== "" ? new TextDecoder().decode(dataRules.output).padEnd(10, " ") : ("--" + dataRules.output) + "--"), - "| °°") + "| °°"); } } diff --git a/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts index dfef040ddf7..0bf3ef02b87 100644 --- a/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts @@ -283,7 +283,7 @@ describe('KeylayoutToKmnConverter', function () { }); }) - describe("get_KeyMap_Modifier_array__From__behaviour_arr ", function () { + describe("get_Modifier_array__From__KeyModifier_array ", function () { [[[['0', 0]], [['', 'shift? caps? ']]], [[['0', 1]], [['anyShift caps?', 'shift? rightShift caps? ', 'shift? leftShift caps? ', 'shift leftShift caps ']]], [[['0', 999]], [null]], @@ -292,9 +292,9 @@ describe('KeylayoutToKmnConverter', function () { [[['0']], [null]], ].forEach(function (values) { it((values[1][0] !== null) ? - ("get_KeyMap_Modifier_array__From__behaviour_arr(['" + values[0][0][0] + "', '" + values[0][0][1] + "'])").padEnd(68, " ") + " should return ['" + values[1][0][0] + "', '" + values[1][0][1] + "']" : - ("get_KeyMap_Modifier_array__From__behaviour_arr(['" + values[0][0][0] + "', '" + values[0][0][1] + "'])").padEnd(68, " ") + " should return ['" + values[1][0] + "']", async function () { - const result = sut.get_KeyMap_Modifier_array__From__behaviour_arr(converted.arrayOf_Modifiers, values[0]) + ("get_Modifier_array__From__KeyModifier_array(['" + values[0][0][0] + "', '" + values[0][0][1] + "'])").padEnd(68, " ") + " should return ['" + values[1][0][0] + "', '" + values[1][0][1] + "']" : + ("get_Modifier_array__From__KeyModifier_array(['" + values[0][0][0] + "', '" + values[0][0][1] + "'])").padEnd(68, " ") + " should return ['" + values[1][0] + "']", async function () { + const result = sut.get_Modifier_array__From__KeyModifier_array(converted.arrayOf_Modifiers, values[0]) assert.deepStrictEqual(JSON.stringify(result), JSON.stringify(values[1])); }); }); @@ -303,14 +303,14 @@ describe('KeylayoutToKmnConverter', function () { [[[undefined]], [null]], [[[]], [null]], ].forEach(function (values) { - it(("get_KeyMap_Modifier_array__From__behaviour_arr([" + values[0][0] + "])").padEnd(68, " ") + " should return ['" + values[1][0] + "']", async function () { - const result = sut.get_KeyMap_Modifier_array__From__behaviour_arr(converted.arrayOf_Modifiers, values[0]) + it(("get_Modifier_array__From__KeyModifier_array([" + values[0][0] + "])").padEnd(68, " ") + " should return ['" + values[1][0] + "']", async function () { + const result = sut.get_Modifier_array__From__KeyModifier_array(converted.arrayOf_Modifiers, values[0]) assert.deepStrictEqual(JSON.stringify(result), JSON.stringify(values[1])); }); }) }) - describe("get_KeyMap_Code_array__From__ActionID_Action ", function () { + describe("get_KeyModifier_array__From__ActionID ", function () { [ ["a16", [['32', 3]]], ["a19", [['45', 3]]], @@ -327,14 +327,14 @@ describe('KeylayoutToKmnConverter', function () { outstring = outstring + "[ '" + values[1][i][0] + "', " + values[1][i][1].toString() + "], " } - it(("get_KeyMap_Code_array__From__ActionID_Action('" + values[0] + "')").padEnd(57, " ") + ' should return ' + outstring.substring(0, outstring.lastIndexOf(']') + 2) + " ]", async function () { - const result = sut.get_KeyMap_Code_array__From__ActionID_Action(read, String(values[0])); + it(("get_KeyModifier_array__From__ActionID('" + values[0] + "')").padEnd(57, " ") + ' should return ' + outstring.substring(0, outstring.lastIndexOf(']') + 2) + " ]", async function () { + const result = sut.get_KeyModifier_array__From__ActionID(read, String(values[0])); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }) }) - describe("get_ActionID_Id__From__ActionID_next ", function () { + describe("get_ActionID__From__ActionNext ", function () { [ ["none", ""], ["a18", ""], @@ -349,14 +349,14 @@ describe('KeylayoutToKmnConverter', function () { [undefined, ""], ["unknown", ""], ].forEach(function (values) { - it(("get_ActionID_Id__From__ActionID_next('" + values[0] + "')").padEnd(49, " ") + ' should return ' + "'" + values[1] + "'", async function () { - const result = sut.get_ActionID_Id__From__ActionID_next(read, String(values[0])); + it(("get_ActionID__From__ActionNext('" + values[0] + "')").padEnd(49, " ") + ' should return ' + "'" + values[1] + "'", async function () { + const result = sut.get_ActionID__From__ActionNext(read, String(values[0])); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }) }) - describe("get_ActionID_Index__From__ActionID_Id ", function () { + describe("get_ActionIndex__From__ActionId ", function () { [ ["none", 0], ["a16", 8], @@ -369,14 +369,14 @@ describe('KeylayoutToKmnConverter', function () { [undefined, 0], ["unknown", 0], ].forEach(function (values) { - it(("get_ActionID_Index__From__ActionID_Id('" + values[0] + "')").padEnd(50, " ") + ' should return ' + values[1], async function () { - const result = sut.get_ActionID_Index__From__ActionID_Id(read, String(values[0])); + it(("get_ActionIndex__From__ActionId('" + values[0] + "')").padEnd(50, " ") + ' should return ' + values[1], async function () { + const result = sut.get_ActionIndex__From__ActionId(read, String(values[0])); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }) }) - describe("get_Action2ID_NoneOutput__From__ActionID_Id ", function () { + describe("get_Output__From__ActionId_None ", function () { [["a14", "u"], ["", ""], [" ", ""], @@ -384,8 +384,8 @@ describe('KeylayoutToKmnConverter', function () { ["unknown", ""], ].forEach(function (values) { it( - ("get_Action2ID_NoneOutput__From__ActionID_Id('" + values[0] + "')").padEnd(56, " ") + ' should return ' + "'" + values[1] + "'", async function () { - const result = sut.get_Action2ID_NoneOutput__From__ActionID_Id(read, String(values[0])); + ("get_Output__From__ActionId_None('" + values[0] + "')").padEnd(56, " ") + ' should return ' + "'" + values[1] + "'", async function () { + const result = sut.get_Output__From__ActionId_None(read, String(values[0])); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); @@ -394,14 +394,14 @@ describe('KeylayoutToKmnConverter', function () { [undefined, ""], [99, ""], ].forEach(function (values) { - it(("get_Action2ID_NoneOutput__From__ActionID_Id('" + values[0] + "')").padEnd(56, " ") + ' should return ' + values[1], async function () { - const result = sut.get_Action2ID_NoneOutput__From__ActionID_Id(read, String(values[0])); + it(("get_Output__From__ActionId_None('" + values[0] + "')").padEnd(56, " ") + ' should return ' + values[1], async function () { + const result = sut.get_Output__From__ActionId_None(read, String(values[0])); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }) }) - describe("get_KeyMapModiKeyArray__from__array ", function () { + describe("get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array ", function () { const b1_keycode_arr = [ ['49', 'K_SPACE', 'a0', '0', 'ˆ'], @@ -472,12 +472,12 @@ describe('KeylayoutToKmnConverter', function () { ].forEach(function (values) { const isCaps_used = true - const string_in = "get_KeyMapModiKeyArray__from__array(['" + "', '" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "', '" + values[0][0][3] + "', '" + values[0][0][4] + "'])" + const string_in = "get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(['" + "', '" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "', '" + values[0][0][3] + "', '" + values[0][0][4] + "'])" const string_out = "['" + "', '" + values[1][0][0] + "', '" + values[1][0][1] + "', '" + values[1][0][2] + "', '" + values[1][0][3] + "', '" + values[1][0][4] + "']" it((JSON.stringify(values[1]).length > 60) ? 'an array of objects should return an array of objectss' : string_in.padEnd(74, " ") + ' should return ' + string_out, async function () { - const result = sut.get_KeyMapModiKeyArray__from__array(read, values[0], isCaps_used); + const result = sut.get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(read, values[0], isCaps_used); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); @@ -490,11 +490,11 @@ describe('KeylayoutToKmnConverter', function () { ].forEach(function (values) { const isCaps_used = false - const string_in = "get_KeyMapModiKeyArray__from__array(['" + "', '" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "', '" + values[0][0][3] + "', '" + values[0][0][4] + "'])" + const string_in = "get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(['" + "', '" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "', '" + values[0][0][3] + "', '" + values[0][0][4] + "'])" const string_out = "['" + "', '" + values[1][0][0] + "', '" + values[1][0][1] + "', '" + values[1][0][2] + "', '" + values[1][0][3] + "', '" + values[1][0][4] + "']" it(string_in.padEnd(74, " ") + ' should return ' + string_out, async function () { - const result = sut.get_KeyMapModiKeyArray__from__array(read, values[0], isCaps_used); + const result = sut.get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(read, values[0], isCaps_used); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); @@ -505,8 +505,8 @@ describe('KeylayoutToKmnConverter', function () { [null, []], ].forEach(function (values) { const isCaps = true - it(("get_KeyMapModiKeyArray__from__array([" + values[0] + "])").padEnd(74, " ") + ' should return ' + "[" + values[1] + "]", async function () { - const result = sut.get_KeyMapModiKeyArray__from__array(read, values[0], isCaps); + it(("get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array([" + values[0] + "])").padEnd(74, " ") + ' should return ' + "[" + values[1] + "]", async function () { + const result = sut.get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(read, values[0], isCaps); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); @@ -550,7 +550,7 @@ describe('KeylayoutToKmnConverter', function () { }); }) - describe("get_ActionID_Output_array__From__ActionID_State ", function () { + describe("get_ActionStateOutput_array__From__ActionState ", function () { [["1", [ ['a0', '1', 'ˆ'], ['a1', '1', 'Â'], @@ -583,15 +583,15 @@ describe('KeylayoutToKmnConverter', function () { [undefined, [],], ].forEach(function (values) { it((JSON.stringify(values[1]).length > 30) ? - ("get_ActionID_Output_array__From__ActionID_State('" + values[0] + "')").padEnd(60, " ") + ' should return an array of objects' : - ("get_ActionID_Output_array__From__ActionID_State('" + values[0] + "')").padEnd(60, " ") + ' should return ' + "'" + JSON.stringify(values[1]) + "'", async function () { - const result = sut.get_ActionID_Output_array__From__ActionID_State(read, String(values[0])); + ("get_ActionStateOutput_array__From__ActionState('" + values[0] + "')").padEnd(60, " ") + ' should return an array of objects' : + ("get_ActionStateOutput_array__From__ActionState('" + values[0] + "')").padEnd(60, " ") + ' should return ' + "'" + JSON.stringify(values[1]) + "'", async function () { + const result = sut.get_ActionStateOutput_array__From__ActionState(read, String(values[0])); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }) }) - describe("get_Datat_array2D__From__ActionID_stateOutput ", function () { + describe("get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput ", function () { [ ["a1", "A", true, [ ['a1', 'A', 'a1', '1', 'K_A', 'SHIFT NCAPS'], @@ -614,15 +614,15 @@ describe('KeylayoutToKmnConverter', function () { ].forEach(function (values) { it((JSON.stringify(values[3]).length > 35) ? - ("get_Datat_array2D__From__ActionID_stateOutput('" + values[0] + "', '" + values[1] + "', " + values[2] + ")").padEnd(67, " ") + ' should return an array of objects' : - ("get_Datat_array2D__From__ActionID_stateOutput('" + values[0] + "', '" + values[1] + "', " + values[2] + ")").padEnd(67, " ") + ' should return ' + "'" + JSON.stringify(values[3]) + "'", async function () { - const result = sut.get_Datat_array2D__From__ActionID_stateOutput(read, converted.arrayOf_Modifiers, String(values[0]), String(values[1]), Boolean(values[2])) + ("get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput('" + values[0] + "', '" + values[1] + "', " + values[2] + ")").padEnd(67, " ") + ' should return an array of objects' : + ("get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput('" + values[0] + "', '" + values[1] + "', " + values[2] + ")").padEnd(67, " ") + ' should return ' + "'" + JSON.stringify(values[3]) + "'", async function () { + const result = sut.get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput(read, converted.arrayOf_Modifiers, String(values[0]), String(values[1]), Boolean(values[2])) assert.equal(JSON.stringify(result), JSON.stringify(values[3])); }); }) }) - describe("get_KeyMap_Code_array__From__KeyMap_Action_array2D ", function () { + describe("get_KeyActionOutput_array__From__ActionStateOutput_array ", function () { const b6_actionId_arr = [ ['a0', '1', 'ˆ'], @@ -664,8 +664,8 @@ describe('KeylayoutToKmnConverter', function () { [[b6_actionId_arr, b1_keycode_arr], ].forEach(function (values) { - it(("get_KeyMap_Code_array__From__KeyMap_Action_array2D([['" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "'],..])").padEnd(73, " ") + ' should return an array of objects', async function () { - const result = sut.get_KeyMap_Code_array__From__KeyMap_Action_array2D(read, values[0]) + it(("get_KeyActionOutput_array__From__ActionStateOutput_array([['" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "'],..])").padEnd(73, " ") + ' should return an array of objects', async function () { + const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0]) assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); @@ -694,8 +694,8 @@ describe('KeylayoutToKmnConverter', function () { [[['a0', '1', '']], oneEntryResultNoOutput], [[['a0', '', 'ˆ']], oneEntryResult], ].forEach(function (values) { - it(("get_KeyMap_Code_array__From__KeyMap_Action_array2D(['" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "'])").padEnd(73, " ") + ' should return an array of objects', async function () { - const result = sut.get_KeyMap_Code_array__From__KeyMap_Action_array2D(read, values[0]) + it(("get_KeyActionOutput_array__From__ActionStateOutput_array(['" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "'])").padEnd(73, " ") + ' should return an array of objects', async function () { + const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0]) assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); @@ -705,8 +705,8 @@ describe('KeylayoutToKmnConverter', function () { [[['', '', '']], []], [[[' ', ' ', '']], []], ].forEach(function (values) { - it(("get_KeyMap_Code_array__From__KeyMap_Action_array2D(['" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "'])").padEnd(73, " ") + ' should return ' + "'[" + values[1] + "]'", async function () { - const result = sut.get_KeyMap_Code_array__From__KeyMap_Action_array2D(read, values[0]) + it(("get_KeyActionOutput_array__From__ActionStateOutput_array(['" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "'])").padEnd(73, " ") + ' should return ' + "'[" + values[1] + "]'", async function () { + const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0]) assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); @@ -716,11 +716,17 @@ describe('KeylayoutToKmnConverter', function () { [undefined, []], [null, []], ].forEach(function (values) { - it(("get_KeyMap_Code_array__From__KeyMap_Action_array2D(" + values[0] + ")").padEnd(73, " ") + ' should return ' + "'[" + values[1] + "]'", async function () { - const result = sut.get_KeyMap_Code_array__From__KeyMap_Action_array2D(read, values[0]) + it(("get_KeyActionOutput_array__From__ActionStateOutput_array(" + values[0] + ")").padEnd(73, " ") + ' should return ' + "'[" + values[1] + "]'", async function () { + const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0]) assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); }) + + // Todo remove + after(function () { + console.log("\nTESTS OK ##########################################################################") + }); + }); From 169cad76b1f22a1901344fab03bcb5b059a6c78b Mon Sep 17 00:00:00 2001 From: Sabine Date: Tue, 18 Mar 2025 14:17:36 +0100 Subject: [PATCH 066/251] feat(developer): print codepoints instead of numeric character ref. and check for control characters --- .../keylayout-to-kmn-converter.ts | 108 +++++++++++-- .../test/test-keylayout-to-kmn-converter.ts | 151 ++++++++++++------ 2 files changed, 193 insertions(+), 66 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 16095bdcb39..ea7de57e1bd 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -161,6 +161,7 @@ export class KeylayoutToKmnConverter { static readonly INPUT_FILE_EXTENSION = '.keylayout'; static readonly OUTPUT_FILE_EXTENSION = '.kmn'; static readonly USED_KEYS_COUNT = 51; + static readonly MAX_CTRL_CHARACTER = 32; // TODO use callbacks what about /*private*/ for options //constructor(/*private*/ _callbacks: CompilerCallbacks, /*private*/ _options: CompilerOptions) { @@ -259,6 +260,7 @@ export class KeylayoutToKmnConverter { arrayOf_Rules: [] }; + // todo check for tags if (jsonObj_any.hasOwnProperty("keyboard")) { data_object.keylayout_filename = jsonObj_any.keyboard['@_name'] + ".keylayout"; @@ -975,8 +977,6 @@ export class KeylayoutToKmnConverter { add_modifier = "NCAPS "; } - // Keyman does not use the right or left version of a modifier (e.g. rightshift, leftshift). If those are used in keylayout files - // they will not be changed but written to the kmn as they are with a warning placed in front of them else if ((modifier_state[i].toUpperCase() === 'ANYSHIFT') || (modifier_state[i].toUpperCase() === 'SHIFT')) { add_modifier = "SHIFT "; } @@ -986,6 +986,7 @@ export class KeylayoutToKmnConverter { else if ((modifier_state[i].toUpperCase() === "RIGHTSHIFT") || (modifier_state[i].toUpperCase() === "RSHIFT")) { add_modifier = "SHIFT "; } + else if ((modifier_state[i].toUpperCase() === 'ANYCONTROL') || (modifier_state[i].toUpperCase() === 'CONTROL')) { add_modifier = "CTRL "; } @@ -995,6 +996,7 @@ export class KeylayoutToKmnConverter { else if ((modifier_state[i].toUpperCase() === "RIGHTCONTROL") || (modifier_state[i].toUpperCase() === "RCONTROL")) { add_modifier = "RCTRL "; } + else if ((modifier_state[i].toUpperCase() === "LEFTOPTION") || (modifier_state[i].toUpperCase() === "LOPTION")) { add_modifier = "LALT "; } @@ -1004,6 +1006,7 @@ export class KeylayoutToKmnConverter { else if ((modifier_state[i].toUpperCase() === 'ANYOPTION') || (modifier_state[i].toUpperCase() === 'OPTION')) { add_modifier = "RALT "; } + else { add_modifier = String(modifier_state[i]) + " "; } @@ -1181,7 +1184,7 @@ export class KeylayoutToKmnConverter { + amb_1_1[0].key + "] > \'" + new TextDecoder().decode(amb_1_1[0].output) - + "\' here: ["); + + "\' here: "); } if (dup_1_1.length > 0) { @@ -1192,7 +1195,7 @@ export class KeylayoutToKmnConverter { + dup_1_1[0].key + "] > \'" + new TextDecoder().decode(dup_1_1[0].output) - + "\' here: ["); + + "\' here: "); } } @@ -1650,6 +1653,40 @@ export class KeylayoutToKmnConverter { else if (pos === 0x24) return "K_ENTER"; else return ""; } + + /** + * @brief member function to return the unicode value + * @param instr the string that will converted + * @return headecimal value of a character + */ + public getHexFromString(instr: string): string { + return Number(instr).toString(16).slice(-6).toUpperCase().padStart(4, "0"); + } + + /** + * @brief member function to convert a numeric character reference to a unicode codepoint + * @param instr the value that will converted + * @return a unicode codepoint if instr is a numeric character reference + * else instr if instr is not a numeric character reference + */ + public checkOutputChar(instr: string): string { + + if (instr.substring(0, 3) === "&#x") { + const num_length = instr.length - instr.indexOf("x") - 1; + const num_str = instr.substring(instr.indexOf("x") + 1, instr.length - 1); + return ("U+" + num_str.slice(-num_length).padStart(4, "0")); + } + + // if not hex: convert to hex + if ((instr.substring(0, 2) === "&#")) { + const num_length = instr.length - instr.indexOf("#") - 1; + const num_str = instr.substring(instr.indexOf("#") + 1, instr.length - 1); + return ("U+" + this.getHexFromString(num_str.slice(-num_length)).padStart(4, "0")); + } + + else + return instr; + } //---------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------- @@ -1665,7 +1702,6 @@ export class KeylayoutToKmnConverter { let data: string = ""; // filter array of all rules and remove duplicates - const unique_data_Rules: rule_object[] = data_ukelele.arrayOf_Rules.filter((curr) => { return ((curr.output !== new TextEncoder().encode("") || curr.output !== undefined) && (curr.rule_type === "C0") || (curr.rule_type === "C1") || (curr.rule_type === "C2") || (curr.rule_type === "C3")); @@ -1731,6 +1767,19 @@ export class KeylayoutToKmnConverter { const warn_text = this.reviewRules(unique_data_Rules, k); + const output_character = new TextDecoder().decode(unique_data_Rules[k].output); + const output_character_unicode = this.checkOutputChar(output_character); + + // if we are about to print a unicode codepoint instead of a single character we need to check if a control character is to be used + if ((output_character_unicode.length > 1) + && (Number("0x" + output_character_unicode.substring(2, output_character_unicode.length)) < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER)) { + if (warn_text[2] == "") + warn_text[2] = warn_text[2] + "c WARNING: use of a control character "; + else + warn_text[2] = warn_text[2] + "; Use of a control character "; + } + + // add a warning in front of rules that use unavailable modifiers or ambiguous rules // if warning contains duplicate rules we do not write out this rule (even if there are other warnings for the same rule) since that rule had been written before @@ -1741,7 +1790,7 @@ export class KeylayoutToKmnConverter { + "+ [" + (unique_data_Rules[k].modifier_key + ' ' + unique_data_Rules[k].key).trim() + `] > \'` - + new TextDecoder().decode(unique_data_Rules[k].output) + + output_character_unicode + '\'\n'; } } @@ -1759,6 +1808,18 @@ export class KeylayoutToKmnConverter { const warn_text = this.reviewRules(unique_data_Rules, k); + const output_character = new TextDecoder().decode(unique_data_Rules[k].output); + const output_character_unicode = this.checkOutputChar(output_character); + + // if we are about to print a unicode codepoint instead of a single character we need to check if a control character is to be used + if ((output_character_unicode.length > 1) + && (Number("0x" + output_character_unicode.substring(2, output_character_unicode.length)) < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER)) { + if (warn_text[2] == "") + warn_text[2] = warn_text[2] + "c WARNING: use of a control character "; + else + warn_text[2] = warn_text[2] + "; Use of a control character "; + } + //SECONDTEXT print // ToDo include condition again if ((warn_text[1].indexOf("duplicate") < 0)) { @@ -1781,7 +1842,7 @@ export class KeylayoutToKmnConverter { + (String(unique_data_Rules[k].id_deadkey) + ") + [" + unique_data_Rules[k].modifier_key).trim() + " " + unique_data_Rules[k].key + "] > \'" - + new TextDecoder().decode(unique_data_Rules[k].output) + + output_character_unicode + "\'\n"; data += "\n"; @@ -1799,12 +1860,25 @@ export class KeylayoutToKmnConverter { if (unique_data_Rules[k].rule_type === "C3") { const warn_text = this.reviewRules(unique_data_Rules, k); + + const output_character = new TextDecoder().decode(unique_data_Rules[k].output); + const output_character_unicode = this.checkOutputChar(output_character); + + // if we are about to print a unicode codepoint instead of a single character we need to check if a control character is to be used + if ((output_character_unicode.length > 1) + && (Number("0x" + output_character_unicode.substring(2, output_character_unicode.length)) < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER)) { + if (warn_text[2] == "") + warn_text[2] = warn_text[2] + "c WARNING: use of a control character "; + else + warn_text[2] = warn_text[2] + "; Use of a control character "; + } + // Todo somewhere (A12) <-> (C12) // ToDo include condition again // FIRSTTEXT print if ((warn_text[0].indexOf("duplicate") < 0) - || ((warn_text[0].indexOf("duplicate") >= 0) && (warn_text[0].indexOf("ambiguous") >= 0)) - || ((warn_text[0].indexOf("duplicate") >= 0) && (warn_text[0].indexOf("unavailable") >= 0)) + // || ((warn_text[0].indexOf("duplicate") >= 0) && (warn_text[0].indexOf("ambiguous") >= 0)) + // || ((warn_text[0].indexOf("duplicate") >= 0) && (warn_text[0].indexOf("unavailable") >= 0)) ) { data += warn_text[0] @@ -1818,8 +1892,8 @@ export class KeylayoutToKmnConverter { // ToDo include condition again //SECONDTEXT print if ((warn_text[1].indexOf("duplicate") < 0) - || ((warn_text[1].indexOf("duplicate") >= 0) && (warn_text[1].indexOf("ambiguous") >= 0)) - || ((warn_text[1].indexOf("duplicate") >= 0) && (warn_text[1].indexOf("unavailable") >= 0)) + // || ((warn_text[1].indexOf("duplicate") >= 0) && (warn_text[1].indexOf("ambiguous") >= 0)) + // || ((warn_text[1].indexOf("duplicate") >= 0) && (warn_text[1].indexOf("unavailable") >= 0)) ) { data += warn_text[1] @@ -1836,8 +1910,8 @@ export class KeylayoutToKmnConverter { // ToDo include condition again // THIRDTEXT print OK if ((warn_text[2].indexOf("duplicate") < 0) - || ((warn_text[2].indexOf("duplicate") >= 0) && (warn_text[2].indexOf("ambiguous") >= 0)) - || ((warn_text[2].indexOf("duplicate") >= 0) && (warn_text[2].indexOf("unavailable") >= 0)) + // || ((warn_text[2].indexOf("duplicate") >= 0) && (warn_text[2].indexOf("ambiguous") >= 0)) + // || ((warn_text[2].indexOf("duplicate") >= 0) && (warn_text[2].indexOf("unavailable") >= 0)) ) { data += warn_text[2] + "dk(B" @@ -1845,13 +1919,13 @@ export class KeylayoutToKmnConverter { + " " + unique_data_Rules[k].key + "] > \'" - + new TextDecoder().decode(unique_data_Rules[k].output) + + output_character_unicode + "\'\n"; } - // if ((warn_text[0].indexOf("duplicate") < 0) || (warn_text[1].indexOf("duplicate") < 0) || (warn_text[2].indexOf("duplicate") < 0)) { - data += "\n"; - // } + if ((warn_text[0].indexOf("duplicate") < 0) || (warn_text[1].indexOf("duplicate") < 0) || (warn_text[2].indexOf("duplicate") < 0)) { + data += "\n"; + } } } diff --git a/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts index 0bf3ef02b87..de097ca0ab6 100644 --- a/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts @@ -102,7 +102,7 @@ describe('KeylayoutToKmnConverter', function () { } assert.isTrue(!threw); }); - }) + }); describe("read() ", function () { it('read() should return filled array on correct input', async function () { @@ -134,7 +134,7 @@ describe('KeylayoutToKmnConverter', function () { const result = sut.read('../data|Italian_copy.keylayout'); assert.isEmpty(result); }); - }) + }); describe("write() ", function () { it('write() should return true (no error) if no inputfile', async function () { @@ -146,7 +146,7 @@ describe('KeylayoutToKmnConverter', function () { const result = sut.write(converted); assert.isTrue(result); }); - }) + }); describe("convert() ", function () { @@ -190,7 +190,7 @@ describe('KeylayoutToKmnConverter', function () { && converted_rule.arrayOf_Modifiers.length === 0 && converted_rule.arrayOf_Rules.length === 0)); }); - }) + }); describe('create_kmn_modifier ', function () { [ @@ -217,8 +217,61 @@ describe('KeylayoutToKmnConverter', function () { const result = sut.create_kmn_modifier(values[0] as string, values[1] as boolean); assert.equal(result, values[2]); }); - }) - }) + }); + }); + + describe('getHexFromString ', function () { + [ + ['0009', '0009'], + ['000027', '001B'], + ['00027', '001B'], + ['0027', '001B'], + ['027', '001B'], + ['27', '001B'], + ['001C', '0NAN'], + ['0000', '0000'], + ['X', '0NAN'], + ['', '0000'], + [' ', '0000'], + [123, '007B'], + [null, '0000'], + ].forEach(function (values) { + it(('should convert "' + values[0] + '"').padEnd(25, " ") + 'to "' + values[1] + '"', async function () { + const result = sut.getHexFromString(values[0] as string); + assert.equal(result, values[1]); + }); + }); + }); + + describe('checkOutputChar ', function () { + [ + ["􏘁", 'U+10F601'], + ["😁", 'U+1F601'], + [" ", 'U+0009'], + ["™", 'U+0099'], + ["ঙ", 'U+0999'], + ["香", 'U+9999'], + ["򙦙", 'U+99999'], + ["􏘁", 'U+10F601'], + ["😁", 'U+1F601'], + [" ", 'U+0009'], + ["c", 'U+0063'], + ["ϧ", 'U+03E7'], + ["✏", 'U+270F'], + ["𘚟", 'U+1869F'], + ['0000;', '0000;'], + ['X;', 'X;'], + ['123;', '123;'], + [';', ';'], + [' ;', ' ;'] + ].forEach(function (values) { + it(('should convert "' + values[0] + '"').padEnd(25, " ") + 'to "' + values[1] + '"', async function () { + const result = sut.checkOutputChar(values[0] as string); + assert.equal(result, values[1]); + }); + }); + }); + describe("isAcceptableKeymanModifier ", function () { [ @@ -240,8 +293,8 @@ describe('KeylayoutToKmnConverter', function () { const result = sut.isAcceptableKeymanModifier(values[0] as string); assert.equal(result, values[1]); }); - }) - }) + }); + }); describe("map_UkeleleKC_To_VK ", function () { [ @@ -259,8 +312,8 @@ describe('KeylayoutToKmnConverter', function () { const result = sut.map_UkeleleKC_To_VK(values[0] as number); assert.equal(result, values[1]); }); - }) - }) + }); + }); describe("checkIfCapsIsUsed ", function () { @@ -281,7 +334,7 @@ describe('KeylayoutToKmnConverter', function () { const result = sut.checkIfCapsIsUsed([null]); assert.isFalse(result); }); - }) + }); describe("get_Modifier_array__From__KeyModifier_array ", function () { [[[['0', 0]], [['', 'shift? caps? ']]], @@ -294,7 +347,7 @@ describe('KeylayoutToKmnConverter', function () { it((values[1][0] !== null) ? ("get_Modifier_array__From__KeyModifier_array(['" + values[0][0][0] + "', '" + values[0][0][1] + "'])").padEnd(68, " ") + " should return ['" + values[1][0][0] + "', '" + values[1][0][1] + "']" : ("get_Modifier_array__From__KeyModifier_array(['" + values[0][0][0] + "', '" + values[0][0][1] + "'])").padEnd(68, " ") + " should return ['" + values[1][0] + "']", async function () { - const result = sut.get_Modifier_array__From__KeyModifier_array(converted.arrayOf_Modifiers, values[0]) + const result = sut.get_Modifier_array__From__KeyModifier_array(converted.arrayOf_Modifiers, values[0]); assert.deepStrictEqual(JSON.stringify(result), JSON.stringify(values[1])); }); }); @@ -304,11 +357,11 @@ describe('KeylayoutToKmnConverter', function () { [[[]], [null]], ].forEach(function (values) { it(("get_Modifier_array__From__KeyModifier_array([" + values[0][0] + "])").padEnd(68, " ") + " should return ['" + values[1][0] + "']", async function () { - const result = sut.get_Modifier_array__From__KeyModifier_array(converted.arrayOf_Modifiers, values[0]) + const result = sut.get_Modifier_array__From__KeyModifier_array(converted.arrayOf_Modifiers, values[0]); assert.deepStrictEqual(JSON.stringify(result), JSON.stringify(values[1])); }); - }) - }) + }); + }); describe("get_KeyModifier_array__From__ActionID ", function () { [ @@ -324,15 +377,15 @@ describe('KeylayoutToKmnConverter', function () { let outstring = "[ "; for (let i = 0; i < values[1].length; i++) { - outstring = outstring + "[ '" + values[1][i][0] + "', " + values[1][i][1].toString() + "], " + outstring = outstring + "[ '" + values[1][i][0] + "', " + values[1][i][1].toString() + "], "; } it(("get_KeyModifier_array__From__ActionID('" + values[0] + "')").padEnd(57, " ") + ' should return ' + outstring.substring(0, outstring.lastIndexOf(']') + 2) + " ]", async function () { const result = sut.get_KeyModifier_array__From__ActionID(read, String(values[0])); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); - }) - }) + }); + }); describe("get_ActionID__From__ActionNext ", function () { [ @@ -353,8 +406,8 @@ describe('KeylayoutToKmnConverter', function () { const result = sut.get_ActionID__From__ActionNext(read, String(values[0])); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); - }) - }) + }); + }); describe("get_ActionIndex__From__ActionId ", function () { [ @@ -373,8 +426,8 @@ describe('KeylayoutToKmnConverter', function () { const result = sut.get_ActionIndex__From__ActionId(read, String(values[0])); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); - }) - }) + }); + }); describe("get_Output__From__ActionId_None ", function () { [["a14", "u"], @@ -398,8 +451,8 @@ describe('KeylayoutToKmnConverter', function () { const result = sut.get_Output__From__ActionId_None(read, String(values[0])); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); - }) - }) + }); + }); describe("get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array ", function () { @@ -471,9 +524,9 @@ describe('KeylayoutToKmnConverter', function () { [[['', '', '', '', '']], [['', '', '', 'NCAPS', '']]], ].forEach(function (values) { - const isCaps_used = true - const string_in = "get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(['" + "', '" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "', '" + values[0][0][3] + "', '" + values[0][0][4] + "'])" - const string_out = "['" + "', '" + values[1][0][0] + "', '" + values[1][0][1] + "', '" + values[1][0][2] + "', '" + values[1][0][3] + "', '" + values[1][0][4] + "']" + const isCaps_used = true; + const string_in = "get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(['" + "', '" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "', '" + values[0][0][3] + "', '" + values[0][0][4] + "'])"; + const string_out = "['" + "', '" + values[1][0][0] + "', '" + values[1][0][1] + "', '" + values[1][0][2] + "', '" + values[1][0][3] + "', '" + values[1][0][4] + "']"; it((JSON.stringify(values[1]).length > 60) ? 'an array of objects should return an array of objectss' : string_in.padEnd(74, " ") + ' should return ' + string_out, async function () { @@ -489,9 +542,9 @@ describe('KeylayoutToKmnConverter', function () { [[['', '', '', '', '']], [['', '', '', '', '']]], ].forEach(function (values) { - const isCaps_used = false - const string_in = "get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(['" + "', '" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "', '" + values[0][0][3] + "', '" + values[0][0][4] + "'])" - const string_out = "['" + "', '" + values[1][0][0] + "', '" + values[1][0][1] + "', '" + values[1][0][2] + "', '" + values[1][0][3] + "', '" + values[1][0][4] + "']" + const isCaps_used = false; + const string_in = "get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(['" + "', '" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "', '" + values[0][0][3] + "', '" + values[0][0][4] + "'])"; + const string_out = "['" + "', '" + values[1][0][0] + "', '" + values[1][0][1] + "', '" + values[1][0][2] + "', '" + values[1][0][3] + "', '" + values[1][0][4] + "']"; it(string_in.padEnd(74, " ") + ' should return ' + string_out, async function () { const result = sut.get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(read, values[0], isCaps_used); @@ -504,13 +557,13 @@ describe('KeylayoutToKmnConverter', function () { [undefined, []], [null, []], ].forEach(function (values) { - const isCaps = true + const isCaps = true; it(("get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array([" + values[0] + "])").padEnd(74, " ") + ' should return ' + "[" + values[1] + "]", async function () { const result = sut.get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(read, values[0], isCaps); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); - }) + }); describe("writeData_Stores() ", function () { @@ -518,7 +571,7 @@ describe('KeylayoutToKmnConverter', function () { "c ......................................................................\n" + "c ......................................................................\n" + "c Keyman keyboard generated by kmn-convert\n" - + "c from Ukelele file: " + + "c from Ukelele file: "; const out_expected_last: string = "\n" @@ -532,23 +585,23 @@ describe('KeylayoutToKmnConverter', function () { + "\n" + "begin Unicode > use(main)\n\n" + "group(main) using keys\n\n" - + "\n" + + "\n"; it(('writeData_Stores should return store text with filename ').padEnd(62, " ") + 'on correct input', async function () { - const written_correctName = sut.writeData_Stores(converted) + const written_correctName = sut.writeData_Stores(converted); assert.equal(written_correctName, (out_expected_first + converted.keylayout_filename + out_expected_last)); }); it(('writeData_Stores should return store text without filename ').padEnd(62, " ") + 'on empty input', async function () { - const written_emptyName = sut.writeData_Stores(converted_empty) + const written_emptyName = sut.writeData_Stores(converted_empty); assert.equal(written_emptyName, (out_expected_first + out_expected_last)); }); it(('writeData_Stores should return store text without filename ').padEnd(62, " ") + 'on only filename as input', async function () { - const written_onlyName = sut.writeData_Stores(converted_unavailable) + const written_onlyName = sut.writeData_Stores(converted_unavailable); assert.equal(written_onlyName, (out_expected_first + converted_unavailable.keylayout_filename + out_expected_last)); }); - }) + }); describe("get_ActionStateOutput_array__From__ActionState ", function () { [["1", [ @@ -588,8 +641,8 @@ describe('KeylayoutToKmnConverter', function () { const result = sut.get_ActionStateOutput_array__From__ActionState(read, String(values[0])); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); - }) - }) + }); + }); describe("get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput ", function () { [ @@ -616,11 +669,11 @@ describe('KeylayoutToKmnConverter', function () { it((JSON.stringify(values[3]).length > 35) ? ("get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput('" + values[0] + "', '" + values[1] + "', " + values[2] + ")").padEnd(67, " ") + ' should return an array of objects' : ("get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput('" + values[0] + "', '" + values[1] + "', " + values[2] + ")").padEnd(67, " ") + ' should return ' + "'" + JSON.stringify(values[3]) + "'", async function () { - const result = sut.get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput(read, converted.arrayOf_Modifiers, String(values[0]), String(values[1]), Boolean(values[2])) + const result = sut.get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput(read, converted.arrayOf_Modifiers, String(values[0]), String(values[1]), Boolean(values[2])); assert.equal(JSON.stringify(result), JSON.stringify(values[3])); }); - }) - }) + }); + }); describe("get_KeyActionOutput_array__From__ActionStateOutput_array ", function () { @@ -665,7 +718,7 @@ describe('KeylayoutToKmnConverter', function () { [[b6_actionId_arr, b1_keycode_arr], ].forEach(function (values) { it(("get_KeyActionOutput_array__From__ActionStateOutput_array([['" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "'],..])").padEnd(73, " ") + ' should return an array of objects', async function () { - const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0]) + const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0]); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); @@ -695,7 +748,7 @@ describe('KeylayoutToKmnConverter', function () { [[['a0', '', 'ˆ']], oneEntryResult], ].forEach(function (values) { it(("get_KeyActionOutput_array__From__ActionStateOutput_array(['" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "'])").padEnd(73, " ") + ' should return an array of objects', async function () { - const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0]) + const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0]); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); @@ -706,7 +759,7 @@ describe('KeylayoutToKmnConverter', function () { [[[' ', ' ', '']], []], ].forEach(function (values) { it(("get_KeyActionOutput_array__From__ActionStateOutput_array(['" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "'])").padEnd(73, " ") + ' should return ' + "'[" + values[1] + "]'", async function () { - const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0]) + const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0]); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); @@ -717,16 +770,16 @@ describe('KeylayoutToKmnConverter', function () { [null, []], ].forEach(function (values) { it(("get_KeyActionOutput_array__From__ActionStateOutput_array(" + values[0] + ")").padEnd(73, " ") + ' should return ' + "'[" + values[1] + "]'", async function () { - const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0]) + const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0]); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); - }) + }); // Todo remove after(function () { - console.log("\nTESTS OK ##########################################################################") + console.log("\nTESTS OK ##########################################################################"); }); }); From cdada430eea89c2798cc7771da6185606ac925eb Mon Sep 17 00:00:00 2001 From: Sabine Date: Thu, 20 Mar 2025 18:01:25 +0100 Subject: [PATCH 067/251] feat(developer): review, tidy up --- .../keylayout-to-kmn-converter.ts | 383 +++++++----------- .../test/test-keylayout-to-kmn-converter.ts | 31 +- 2 files changed, 162 insertions(+), 252 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index ea7de57e1bd..3d4fecdcb93 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -17,7 +17,7 @@ import { ConverterToKmnArtifacts } from "../converter-artifacts.js"; // OK action/output:use filter etc to shorten func // OK deadkeyables:use filter etc to shorten func // OK dk-> for all action:use filter etc to shorten func -// OK remove unneccessary data from data_object +// OK remove unnecessary data from data_object // OK rename symbols // OK remove part using kmn_key_Name1 // OK remove unnecceaasry map_UkeleleKC_To_kmn_Key_Name_Array_Position_n etc @@ -77,16 +77,16 @@ import { ConverterToKmnArtifacts } from "../converter-artifacts.js"; // TODO what about using actions twice in a row??? -> error msg if chain >4 // what if keylayout file is not correct e.g missing '>' // read TODO which stores? -// does order of modifier matter ? +// OK does order of modifier matter ? -> NO // remove all markers c0, 1-1, #### C2 ###, ... -// better function names for get...... +// OK better function names for get...... // use cmdl parameters -// check semicolon everywhere +// OK check semicolon everywhere // OK test run // OK test read // OK test convert // OK test write -// test createRuleData +// OK test createRuleData // OK test get_KeyMap_Code_array__From__KeyMap_Action // OK test get_KeyActionOutput_array__From__ActionStateOutput_array // OK test get_ActionIndex__From__ActionId @@ -106,6 +106,8 @@ import { ConverterToKmnArtifacts } from "../converter-artifacts.js"; // OK test writeData_Stores // what if nodes in keylayout file do not exist/ diff name keyboard <-> keyboardA // separate createRuleData and check for duplicates/amb rules +// remove todos +// check warning text import { XMLParser } from 'fast-xml-parser'; // for reading an xml file import { readFileSync } from 'fs'; @@ -163,11 +165,7 @@ export class KeylayoutToKmnConverter { static readonly USED_KEYS_COUNT = 51; static readonly MAX_CTRL_CHARACTER = 32; - // TODO use callbacks what about /*private*/ for options - //constructor(/*private*/ _callbacks: CompilerCallbacks, /*private*/ _options: CompilerOptions) { constructor(private callbacks: CompilerCallbacks, options: CompilerOptions) { - // TODO: if these are needed, uncomment /*private*/ and remove _, and they will then - // be available as class properties }; /** @@ -181,12 +179,11 @@ export class KeylayoutToKmnConverter { if (!inputFilename || !outputFilename) { throw new Error('Invalid parameters'); } - console.log(' _S2 first READ file ........................................in:', inputFilename); const jsonO: object = this.read(inputFilename); if (!jsonO) { - throw new Error('read() not OK'); // new SAB + throw new Error('read() not OK'); return null; } @@ -194,7 +191,7 @@ export class KeylayoutToKmnConverter { const outArray: convert_object = await this.convert(jsonO); if (!outArray) { - throw new Error('convert() not OK'); // new SAB + throw new Error('convert() not OK'); return null; } @@ -202,14 +199,11 @@ export class KeylayoutToKmnConverter { const out_text: boolean = this.write(outArray); if (!out_text) { - throw new Error('write() not OK'); // new SAB + throw new Error('write() not OK'); return null; } - // TODO throws - console.log(';;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; FINISHED OK ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;'); - //throw new Error('Not finished yet'); // new SAB - return null; // new SAB + return null; } /** @@ -233,7 +227,7 @@ export class KeylayoutToKmnConverter { jsonObj = parser.parse(xmlFile); // get plain Object boxArrays(jsonObj.keyboard); // jsonObj now contains only arrays; no single fields } - catch { + catch (err) { // Todo how to break correctly; return what?? console.log(" FILE NOT FOUND"); } @@ -250,8 +244,8 @@ export class KeylayoutToKmnConverter { */ public convert(jsonObj: any): convert_object { - const modifierBehavior: string[][] = []; // modifier for each keymapselect - const rule_object: rule_object[] = []; // an array of objects which hold data for a kmn rule + const modifierBehavior: string[][] = []; // modifier for each behaviour + const rule_object: rule_object[] = []; // an array of data for a kmn rule const jsonObj_any: any = jsonObj; const data_object: convert_object = { @@ -267,7 +261,7 @@ export class KeylayoutToKmnConverter { data_object.arrayOf_Modifiers = modifierBehavior; // ukelele uses behaviours e.g. 18 modifiersCombinations in 8 KeyMapSelect(behaviors) data_object.arrayOf_Rules = rule_object; - // create an array of modifier combinations (e.g. shift? leftShift caps? ) and store in data_object + // create an array of modifier combinations and store in data_object for (let j = 0; j < jsonObj.keyboard.modifierMap.keyMapSelect.length; j++) { const singleModifierSet: string[] = []; for (let k = 0; k < jsonObj.keyboard.modifierMap.keyMapSelect[j].modifier.length; k++) { @@ -282,17 +276,14 @@ export class KeylayoutToKmnConverter { } /** - * @brief member function to write data fro object to file + * @brief member function to write data from object to file * @param data_ukelele the array holding keyboard data * @return true if data has been written; false if not */ - //TODO need to use export const USVirtualKeyCodes here public write(data_ukelele: convert_object): boolean { let data: string = "\n"; - - // TODO use path also - // const savename = "data//" + data_ukelele.keylayout_filename.substring(0, data_ukelele.keylayout_filename.lastIndexOf(".")) + ".kmn" + //const save_filename = "data//" + data_ukelele.keylayout_filename.substring(0, data_ukelele.keylayout_filename.lastIndexOf(".")) + ".kmn"; // add top part of kmn file: STORES data += this.writeData_Stores(data_ukelele); @@ -302,18 +293,14 @@ export class KeylayoutToKmnConverter { try { this.callbacks.fs.writeFileSync("data/MyResult.kmn", new TextEncoder().encode(data)); - //this.callbacks.fs.writeFileSync(savename, new TextEncoder().encode(data)) + //this.callbacks.fs.writeFileSync(save_filename, new TextEncoder().encode(data)); return true; } catch (err) { console.log('Error writing kmn file:' + err.message); return false; } - } - // TODO move outside of class? - // ToDo keep only uint8array-version - // for more info about mapping and cases C0-C4 see https://docs.google.com/document/d/12J3NGO6RxIthCpZDTR8FYSRjiMgXJDLwPY2z9xqKzJ0/edit?tab=t.0#heading=h.g7jwx3lx0ydd public createRuleData(data_ukelele: convert_object, jsonObj: any): convert_object { const object_array: rule_object[] = []; @@ -321,7 +308,7 @@ export class KeylayoutToKmnConverter { let dk_counter_C2: number = 0; let action_id: string; - // check if we use CAPS in a modifier. In this case we need to add NCAPS + // check if we use CAPS in a modifier throughout the .keylayout file. In this case we need to add NCAPS const isCapsused: boolean = this.checkIfCapsIsUsed(data_ukelele.arrayOf_Modifiers); // loop keys 0-50 (= all keys we use) @@ -335,7 +322,7 @@ export class KeylayoutToKmnConverter { // ............................................................................................................................... // case C0: output ............................................................................................................... // C0 see: https://docs.google.com/document/d/12J3NGO6RxIthCpZDTR8FYSRjiMgXJDLwPY2z9xqKzJ0/edit?tab=t.0#heading=h.g7jwx3lx0ydd ... - // a key is mapped to a character directly ( code-> output) ...................................................................... + // a key is mapped to a character directly ( code -> output) ..................................................................... // ...............e. g. ............................................................................... // ............................................................................................................................... @@ -377,7 +364,7 @@ export class KeylayoutToKmnConverter { // case C1: action + state none + output ......................................................................................... // C1 see: https://docs.google.com/document/d/12J3NGO6RxIthCpZDTR8FYSRjiMgXJDLwPY2z9xqKzJ0/edit?tab=t.0#heading=h.g7jwx3lx0ydd ... // a key is mapped to an action and then to an output ............................................................................ - // KeyMap:code->KeyMap:action->action:action_state(none)->action_output .......................................................... + // KeyMap:code -> KeyMap:action->action:action_state(none) -> action_output ...................................................... // ...............e. g. (keymapIndex 3/keycode 28) .................................................................... + // with present action_id (a17) find all key names and behaviours that use this action (a17) => (keymapIndex 3/keycode 28) .................................................................... // from these create an array of modifier combinations e.g. [ [ 'anyOption', 'Caps' ] ] ..................................................................................................... - /* eg: index=3 */ const b2_prev_deadkey_arr: number[][] = this.get_KeyModifier_array__From__ActionID(jsonObj, String(b3_actionId)); // concersion not neccessary + /* eg: index=3 */ const b2_prev_deadkey_arr: number[][] = this.get_KeyModifier_array__From__ActionID(jsonObj, String(b3_actionId)); // conversion not necessary /* e.g. [ [ 'anyOption', 'Caps' ] ] */ const b2_prev_deadkeyModifier_arr: string[] = this.get_Modifier_array__From__KeyModifier_array(data_ukelele.arrayOf_Modifiers, b2_prev_deadkey_arr); // ........................................................................................................................................................................................... // Data of Block Nr 6 ........................................................................................................................................................................ @@ -592,13 +580,12 @@ export class KeylayoutToKmnConverter { // -------------------------------------------------------------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------------------------------------------------------------- // check for duplicate C2 and C3 rules in object_array (e.g. [NCAPS RALT K_8] > dk(C12) ): create a separate array of unique rules, - // then compare to object_array and mark first occurance of a rule in object_array + // then compare to object_array and mark first occurrence of a rule in object_array // -------------------------------------------------------------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------------------------------------------------------------- let unique_dkB_count = 0; const list_of_unique_Text2_rules: string[][] = []; - //this.writeDataset(object_array) //------------------------------------ C2: dk ---------------------------------- // first rule is always unique object_array[0].unique_deadkey = unique_dkB_count; @@ -821,11 +808,17 @@ export class KeylayoutToKmnConverter { for (let j = 0; j < data.keyboard.modifierMap.keyMapSelect[behaviour].modifier.length; j++) { const returnarray1D: string[] = []; - returnarray1D.push(String(search[i][1])); /* KeyName*/ - returnarray1D.push(String(search[i][2])); /* actionId*/ - returnarray1D.push(String(search[i][3])); /* behaviour*/ - returnarray1D.push(String(this.create_kmn_modifier(data.keyboard.modifierMap.keyMapSelect[behaviour].modifier[j]['@_keys'], isCAPSused))); /* modifier */ - returnarray1D.push(String(search[i][4])); /* char*/ + // KeyName + returnarray1D.push(String(search[i][1])); + // actionId + returnarray1D.push(String(search[i][2])); + // behaviour + returnarray1D.push(String(search[i][3])); + // modifier + returnarray1D.push(String(this.create_kmn_modifier(data.keyboard.modifierMap.keyMapSelect[behaviour].modifier[j]['@_keys'], isCAPSused))); + // output + returnarray1D.push(String(search[i][4])); + if (returnarray1D.length > 0) { returnarray.push(returnarray1D); } @@ -862,7 +855,7 @@ export class KeylayoutToKmnConverter { return []; } - // loop behaviors ( in ukelele it is possible to define multiple modifier combinations that behave in the same) + // loop behaviors (in ukelele it is possible to define multiple modifier combinations that behave in the same) for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { for (let j = 0; j < KeylayoutToKmnConverter.USED_KEYS_COUNT; j++) { if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { @@ -949,7 +942,6 @@ export class KeylayoutToKmnConverter { let kmn_modifier: string = ""; let kmn_ncaps: string = ""; - // copy each modifier seperate element of array const modifier_state: string[] = keylayout_modifier.split(" "); for (let i = 0; i < modifier_state.length; i++) { @@ -958,12 +950,12 @@ export class KeylayoutToKmnConverter { kmn_ncaps = " NCAPS "; } - // if we find a modifier containing a '?' e.g. SHIFT?: => SHIFT is not neccessary. If it is not neccessary we don`t write this modifier + // if we find a modifier containing a '?' e.g. SHIFT? => SHIFT is not necessary. If it is not necessary we don't write this modifier if (modifier_state[i].toUpperCase().includes('?') && (!modifier_state[i].toUpperCase().includes('CAPS?'))) { add_modifier = ""; } - // TODO is this correct: caps? => caps is not neccessary. If its not neccessary and isCAPSused we need to write out NCAPS. Correct? + // if we find caps? => caps is not necessary. If caps is not necessary and isCAPSused we need to write out NCAPS. else if (isCAPSused && (modifier_state[i].toUpperCase().includes('CAPS?'))) { add_modifier = "NCAPS "; } @@ -1108,12 +1100,11 @@ export class KeylayoutToKmnConverter { } } - // +++++++++++++++++++++++++ check ambiguous/duplicate rules ++++++++++++++++++++++++++++++++++++++ if ((rule[index].rule_type === "C0") || (rule[index].rule_type === "C1")) { - // 1-1 + [CAPS K_N] > 'N' <-> + [CAPS K_N] > 'A' + // 1-1: + [CAPS K_N] > 'N' <-> + [CAPS K_N] > 'A' const amb_1_1 = rule.filter((curr, idx) => (curr.rule_type === "C0" || curr.rule_type === "C1") && curr.modifier_prev_deadkey === "" @@ -1126,7 +1117,7 @@ export class KeylayoutToKmnConverter { && idx < index ); - // 1-1 + [CAPS K_N] > 'N' <-> + [CAPS K_N] > 'N' + // 1-1: + [CAPS K_N] > 'N' <-> + [CAPS K_N] > 'N' const dup_1_1 = rule.filter((curr, idx) => (curr.rule_type === "C0" || curr.rule_type === "C1") && curr.modifier_prev_deadkey === "" @@ -1139,16 +1130,23 @@ export class KeylayoutToKmnConverter { && idx < index ); - // 4-1 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > 'Ñ' + // 4-1: + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > 'Ñ' const amb_4_1 = rule.filter((curr, idx) => ((curr.rule_type === "C3")) && curr.modifier_prev_deadkey === rule[index].modifier_key && curr.prev_deadkey === rule[index].key ); + + // 2-1: + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > 'Ñ' + const amb_2_1 = rule.filter((curr, idx) => + ((curr.rule_type === "C2")) + && curr.modifier_deadkey === rule[index].modifier_key + && curr.deadkey === rule[index].key + ); + if (amb_4_1.length > 0) { warningTextArray[2] = warningTextArray[2] - + ("XXXXX NEW C01 ThirdTEXT " - + "ambiguous 4-1 rule: later: [" + + ("ambiguous 4-1 rule: later: [" + amb_4_1[0].modifier_prev_deadkey + " " + amb_4_1[0].prev_deadkey @@ -1157,16 +1155,9 @@ export class KeylayoutToKmnConverter { + ") here: "); } - // 2-1 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > 'Ñ' - const amb_2_1 = rule.filter((curr, idx) => - ((curr.rule_type === "C2")) - && curr.modifier_deadkey === rule[index].modifier_key - && curr.deadkey === rule[index].key - ); - if (amb_2_1.length > 0) { + if (amb_2_1.length > 0) { warningTextArray[2] = warningTextArray[2] - + ("XXXXX NEW C01 ThirdTEXT " - + "ambiguous 2-1 rule: later: [" + + ("ambiguous 2-1 rule: later: [" + amb_2_1[0].modifier_deadkey + " " + amb_2_1[0].deadkey @@ -1175,8 +1166,7 @@ export class KeylayoutToKmnConverter { + ") here: "); } - // Todo 1-1 text [ - if (amb_1_1.length > 0) { + if (amb_1_1.length > 0) { warningTextArray[2] = warningTextArray[2] + ("C1 ambiguous 1-1 rule: earlier: [" + amb_1_1[0].modifier_key @@ -1187,7 +1177,7 @@ export class KeylayoutToKmnConverter { + "\' here: "); } - if (dup_1_1.length > 0) { + if (dup_1_1.length > 0) { warningTextArray[2] = warningTextArray[2] + ("C1 duplicate 1-1 rule: earlier: [" + dup_1_1[0].modifier_key @@ -1201,7 +1191,7 @@ export class KeylayoutToKmnConverter { if (rule[index].rule_type === "C2") { - // 2-2 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(C1) + // 2-2: + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(C3) const amb_2_2 = rule.filter((curr, idx) => curr.rule_type === "C2" && curr.modifier_deadkey === rule[index].modifier_deadkey @@ -1210,7 +1200,7 @@ export class KeylayoutToKmnConverter { && idx < index ); - //2-2 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(C11) + // 2-2: + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(C11) const dup_2_2 = rule.filter((curr, idx) => curr.rule_type === "C2" && curr.modifier_deadkey === rule[index].modifier_deadkey @@ -1219,7 +1209,7 @@ export class KeylayoutToKmnConverter { && idx < index ); - //3-3 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'B' + //3-3: dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'B' const amb_3_3 = rule.filter((curr, idx) => (curr.rule_type === "C2") && curr.id_deadkey === rule[index].id_deadkey @@ -1227,10 +1217,9 @@ export class KeylayoutToKmnConverter { && curr.key === rule[index].key && new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output) && idx < index - // && rule[index].unique_deadkey !== 0 ); - //3-3 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'Ã' + //3-3: dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'Ã' const dup_3_3 = rule.filter((curr, idx) => (curr.rule_type === "C2") && curr.id_deadkey === rule[index].id_deadkey @@ -1241,42 +1230,17 @@ export class KeylayoutToKmnConverter { && idx < index ); - /* //1-2 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > 'Ñ' - const amb_1_2 = rule.filter((curr, idx) => - ((curr.rule_type === "C0") || (curr.rule_type === "C1")) - && curr.modifier_key === rule[index].modifier_deadkey - && curr.key === rule[index].deadkey - //&& rule[index].unique_deadkey === 0 // include and the first occurance will be printed - //&& (idx < index) // include and the first occurance will be printed - );*/ - - // 4-2 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(B11) + // 4-2: + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(B11) const amb_4_2 = rule.filter((curr, idx) => ((curr.rule_type === "C3")) && curr.modifier_prev_deadkey === rule[index].modifier_deadkey && curr.prev_deadkey === rule[index].deadkey && curr.id_prev_deadkey === rule[index].id_deadkey - // && rule[index].unique_prev_deadkey === 0 // include and the first occurance will be printed - // && (idx < index) ); - if (amb_4_2.length > 0) { - warningTextArray[0] = warningTextArray[0] - + ("C2 XXX FIRSTTEXT " - + "ambiguous 4-2 rule: later: [" - + amb_4_2[0].modifier_prev_deadkey - + " " - + amb_4_2[0].prev_deadkey - + "] > dk(C" - + amb_4_2[0].id_prev_deadkey - + ") here: "); - } - - if (amb_2_2.length > 0) { warningTextArray[1] = warningTextArray[1] - + ("C2 SECONDTEXT " - + "ambiguous 2-2 rule: earlier: [" + + ("ambiguous 2-2 rule: earlier: [" + amb_2_2[0].modifier_deadkey + " " + amb_2_2[0].deadkey @@ -1284,10 +1248,10 @@ export class KeylayoutToKmnConverter { + amb_2_2[0].id_deadkey + ") here: "); } + if (dup_2_2.length > 0) { warningTextArray[1] = warningTextArray[1] - + ("C2 SECONDTEXT " - + "duplicate 2-2 rule: earlier: [" + + ("duplicate 2-2 rule: earlier: [" + dup_2_2[0].modifier_deadkey + " " + dup_2_2[0].deadkey @@ -1297,8 +1261,7 @@ export class KeylayoutToKmnConverter { } if (amb_3_3.length > 0) { warningTextArray[2] = warningTextArray[2] - + ("C2 THIRDTEXT " - + "ambiguous 3-3 rule: earlier: dk(C" + + ("ambiguous 3-3 rule: earlier: dk(C" + amb_3_3[0].id_deadkey + ") + [" + amb_3_3[0].modifier_key @@ -1310,8 +1273,7 @@ export class KeylayoutToKmnConverter { } if (dup_3_3.length > 0) { warningTextArray[2] = warningTextArray[2] - + ("C2 THIRDTEXT " - + "duplicate 3-3 rule: earlier: dk(C" + + ("duplicate 3-3 rule: earlier: dk(C" + dup_3_3[0].id_deadkey + ") + [" + dup_3_3[0].modifier_key @@ -1321,38 +1283,26 @@ export class KeylayoutToKmnConverter { + new TextDecoder().decode(dup_3_3[0].output) + "\' here: "); } - /* if (amb_1_2.length > 0) { - warningTextArray[1] = warningTextArray[1] - + ("C2 SECONDTEXT " - + "ambiguous 1-2 rule: earlier: [" - + amb_1_2[0].modifier_key - + " " - + amb_1_2[0].key - + "] > \'" - + new TextDecoder().decode(amb_1_2[0].output) - + "\' here: ") - }*/ + + if (amb_4_2.length > 0) { + warningTextArray[0] = warningTextArray[0] + + ("ambiguous 4-2 rule: later: [" + + amb_4_2[0].modifier_prev_deadkey + + " " + + amb_4_2[0].prev_deadkey + + "] > dk(C" + + amb_4_2[0].id_prev_deadkey + + ") here: "); + } } if (rule[index].rule_type === "C3") { - - /* // 1-4 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > 'Ñ' - const amb_1_4 = rule.filter((curr, idx) => - ((curr.rule_type === "C0") || (curr.rule_type === "C1")) - && curr.modifier_key === rule[index].modifier_prev_deadkey - && curr.key === rule[index].prev_deadkey - //&& rule[index].unique_prev_deadkey === 0 // include and the first occurance will be printed - //&& (idx < index) - );*/ - // 2-4 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(B11) const amb_2_4 = rule.filter((curr, idx) => ((curr.rule_type === "C2")) && curr.modifier_deadkey === rule[index].modifier_prev_deadkey && curr.deadkey === rule[index].prev_deadkey && curr.id_deadkey === rule[index].id_prev_deadkey - // && rule[index].unique_prev_deadkey === 0 // include and the first occurance will be printed - // && (idx < index) ); // 6-3 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'B' @@ -1362,8 +1312,6 @@ export class KeylayoutToKmnConverter { && curr.modifier_key === rule[index].modifier_key && curr.key === rule[index].key && (new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output)) - // && rule[index].unique_deadkey !== 0 - // && idx < index ); // 6-3 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'Ã' @@ -1373,8 +1321,6 @@ export class KeylayoutToKmnConverter { && curr.modifier_key === rule[index].modifier_key && curr.key === rule[index].key && new TextDecoder().decode(curr.output) === new TextDecoder().decode(rule[index].output) - // && rule[index].unique_deadkey === 0 - // && idx < index ); // 4-4 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > 'dk(C1)' @@ -1394,69 +1340,53 @@ export class KeylayoutToKmnConverter { && curr.prev_deadkey === rule[index].prev_deadkey && curr.id_prev_deadkey === rule[index].id_prev_deadkey && idx < index - // && rule[index].unique_prev_deadkey !== 0 ); - // 6-6 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'B' - const amb_6_6 = rule.filter((curr, idx) => + // 5-5 + const amb_5_5 = rule.filter((curr, idx) => (curr.rule_type === "C3") - && curr.id_deadkey === rule[index].id_deadkey - && rule[index].unique_prev_deadkey !== 0 && curr.modifier_key === rule[index].modifier_key && curr.key === rule[index].key + && curr.id_deadkey === rule[index].id_deadkey && (new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output)) - && idx < index ); - // 6-6 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'Ã' - const dup_6_6 = rule.filter((curr, idx) => + // 5-5 + const dup_5_5 = rule.filter((curr, idx) => (curr.rule_type === "C3") + && curr.modifier_deadkey === rule[index].modifier_deadkey + && curr.deadkey === rule[index].deadkey + && curr.id_prev_deadkey === rule[index].id_prev_deadkey && curr.id_deadkey === rule[index].id_deadkey - && curr.modifier_key === rule[index].modifier_key - && curr.key === rule[index].key - && (new TextDecoder().decode(curr.output) === new TextDecoder().decode(rule[index].output)) - && idx < index + && rule[index].unique_deadkey === 0 ); - // 5-5 - const amb_5_5 = rule.filter((curr, idx) => + // 6-6 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'B' + const amb_6_6 = rule.filter((curr, idx) => (curr.rule_type === "C3") + && curr.id_deadkey === rule[index].id_deadkey + && rule[index].unique_prev_deadkey !== 0 && curr.modifier_key === rule[index].modifier_key && curr.key === rule[index].key - && curr.id_deadkey === rule[index].id_deadkey && (new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output)) + && idx < index - //&& rule[index].unique_prev_deadkey !== 0 ); - // 5-5 - const dup_5_5 = rule.filter((curr, idx) => + // 6-6 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'Ã' + const dup_6_6 = rule.filter((curr, idx) => (curr.rule_type === "C3") - && curr.modifier_deadkey === rule[index].modifier_deadkey - && curr.deadkey === rule[index].deadkey - && curr.id_prev_deadkey === rule[index].id_prev_deadkey && curr.id_deadkey === rule[index].id_deadkey - && rule[index].unique_deadkey === 0 - //&& idx < index + && curr.modifier_key === rule[index].modifier_key + && curr.key === rule[index].key + && (new TextDecoder().decode(curr.output) === new TextDecoder().decode(rule[index].output)) + && idx < index ); - /*if (amb_1_4.length > 0) { - warningTextArray[0] = warningTextArray[0] - + ("C3 FIRSTTEXT " - + "ambiguous 1-4 rule: earlier(Todo check if print out or not): [" - + amb_1_4[0].modifier_key - + " " - + amb_1_4[0].key - + "] > \'" - + new TextDecoder().decode(amb_1_4[0].output) - + "\' here: ") - }*/ - if (amb_2_4.length > 0) { warningTextArray[0] = warningTextArray[0] - + ("C3 FIRSTTEXT " - + "ambiguous 2-4 rule: earlier(Todo check if print out or not): [" + + ("ambiguous 2-4 rule: earlier(Todo check if print out or not): [" + amb_2_4[0].modifier_deadkey + " " + amb_2_4[0].deadkey @@ -1467,8 +1397,7 @@ export class KeylayoutToKmnConverter { if (amb_6_3.length > 0) { warningTextArray[1] = warningTextArray[1] - + ("C3 SECONDTEXT " - + "ambiguous 6-3 rule: earlier: dk(C" + + ("ambiguous 6-3 rule: earlier: dk(C" + amb_6_3[0].id_deadkey + ") + [" + amb_6_3[0].modifier_key @@ -1481,8 +1410,7 @@ export class KeylayoutToKmnConverter { if (dup_6_3.length > 0) { warningTextArray[1] = warningTextArray[1] - + ("C3 SECONDTEXT " - + "duplicate 6-3 rule: earlier: dk(C" + + ("duplicate 6-3 rule: earlier: dk(C" + dup_6_3[0].id_deadkey + ") + [" + dup_6_3[0].modifier_key @@ -1495,8 +1423,7 @@ export class KeylayoutToKmnConverter { if (amb_4_4.length > 0) { warningTextArray[0] = warningTextArray[0] - + ("C3 FIRSTTEXT " - + "ambiguous 4-4 rule: earlier: [" + + ("ambiguous 4-4 rule: earlier: [" + amb_4_4[0].modifier_prev_deadkey + " " + amb_4_4[0].prev_deadkey @@ -1507,8 +1434,7 @@ export class KeylayoutToKmnConverter { if (dup_4_4.length > 0) { warningTextArray[0] = warningTextArray[0] - + ("C3 FIRSTTEXT " - + "duplicate 4-4 rule: earlier: [" + + ("duplicate 4-4 rule: earlier: [" + dup_4_4[0].modifier_prev_deadkey + " " + dup_4_4[0].prev_deadkey @@ -1519,8 +1445,7 @@ export class KeylayoutToKmnConverter { if (amb_5_5.length > 0) { warningTextArray[1] = warningTextArray[1] - + ("C3 SECONDTEXT " - + "ambiguous 5-5 rule: earlier: dk(B" + + ("ambiguous 5-5 rule: earlier: dk(B" + amb_5_5[0].id_prev_deadkey + ") + [" + amb_5_5[0].modifier_deadkey @@ -1533,8 +1458,7 @@ export class KeylayoutToKmnConverter { if (dup_5_5.length > 0) { warningTextArray[1] = warningTextArray[1] - + ("C3 SECONDTEXT " - + "duplicate 5-5 rule: earlier: dk(B" + + ("duplicate 5-5 rule: earlier: dk(B" + dup_5_5[0].id_prev_deadkey + ") + [" + dup_5_5[0].modifier_deadkey @@ -1547,8 +1471,7 @@ export class KeylayoutToKmnConverter { if (amb_6_6.length > 0) { warningTextArray[2] = warningTextArray[2] - + ("C3 THIRDTEXT " - + "ambiguous 6-6 rule: earlier: dk(B" + + ("ambiguous 6-6 rule: earlier: dk(B" + amb_6_6[0].id_deadkey + ") + [" + amb_6_6[0].modifier_key @@ -1561,9 +1484,7 @@ export class KeylayoutToKmnConverter { if (dup_6_6.length > 0) { warningTextArray[2] = warningTextArray[2] - - + ("C3 THIRDTEXT " - + "duplicate 6-6x rule: earlier: dk(B" + + ("duplicate 6-6x rule: earlier: dk(B" + dup_6_6[0].id_deadkey + ") + [" + dup_6_6[0].modifier_key @@ -1657,7 +1578,7 @@ export class KeylayoutToKmnConverter { /** * @brief member function to return the unicode value * @param instr the string that will converted - * @return headecimal value of a character + * @return hexadecimal value of a character */ public getHexFromString(instr: string): string { return Number(instr).toString(16).slice(-6).toUpperCase().padStart(4, "0"); @@ -1704,12 +1625,20 @@ export class KeylayoutToKmnConverter { // filter array of all rules and remove duplicates const unique_data_Rules: rule_object[] = data_ukelele.arrayOf_Rules.filter((curr) => { return ((curr.output !== new TextEncoder().encode("") || curr.output !== undefined) - && (curr.rule_type === "C0") || (curr.rule_type === "C1") || (curr.rule_type === "C2") || (curr.rule_type === "C3")); + && (curr.key !== "") + // && ((curr.rule_type === "C0") || (curr.rule_type === "C1") || (curr.rule_type === "C2" && (curr.deadkey !== "")) || (curr.rule_type === "C3" && (curr.prev_deadkey !== ""))) + && ((curr.rule_type === "C0") + || (curr.rule_type === "C1") + || (curr.rule_type === "C2" && (curr.deadkey !== "")) + || (curr.rule_type === "C3" && (curr.deadkey !== "") && (curr.prev_deadkey !== ""))) + + ); }).reduce((unique, o) => { if (!unique.some((obj: { modifier_prev_deadkey: string; prev_deadkey: string; modifier_deadkey: string; deadkey: string; - rule_type: string; modifier_key: string; key: string; + modifier_key: string; key: string; + rule_type: string; output: Uint8Array; }) => new TextDecoder().decode(obj.output) === new TextDecoder().decode(o.output) @@ -1729,13 +1658,6 @@ export class KeylayoutToKmnConverter { return unique; }, []); - // ToDo remove - //const unique_data_Rules: rule_object[] = data_ukelele.arrayOf_Rules - //console.log("xx data_ukelele.arrayOf_Rules", data_ukelele.arrayOf_Rules.length) - //console.log("xx data_ukelele.arrayOf_Rules", this.writeDataset(data_ukelele.arrayOf_Rules)) - // console.log("xx unique_data_Rules", unique_data_Rules.length) - //console.log("xx unique_data_Rules", this.writeDataset(unique_data_Rules)) - //................................................ C0 C1 ................................................................ //................................................ C0 C1 ................................................................ //................................................ C0 C1 ................................................................ @@ -1744,7 +1666,7 @@ export class KeylayoutToKmnConverter { if ((unique_data_Rules[k].rule_type === "C0") || (unique_data_Rules[k].rule_type === "C1")) { - // lookup key nr of the key that is being processed + // lookup key nr of the key which is being processed let keyNr: number = 0; for (let j = 0; j < KeylayoutToKmnConverter.USED_KEYS_COUNT; j++) { if (this.map_UkeleleKC_To_VK(j) === unique_data_Rules[k].key) { @@ -1770,7 +1692,7 @@ export class KeylayoutToKmnConverter { const output_character = new TextDecoder().decode(unique_data_Rules[k].output); const output_character_unicode = this.checkOutputChar(output_character); - // if we are about to print a unicode codepoint instead of a single character we need to check if a control character is to be used + // if we are about to print a unicode codepoint instead of a single character we need to check if it is a control character if ((output_character_unicode.length > 1) && (Number("0x" + output_character_unicode.substring(2, output_character_unicode.length)) < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER)) { if (warn_text[2] == "") @@ -1780,10 +1702,8 @@ export class KeylayoutToKmnConverter { } - // add a warning in front of rules that use unavailable modifiers or ambiguous rules + // add a warning in front of rules in case unavailable modifiers or ambiguous rules are used // if warning contains duplicate rules we do not write out this rule (even if there are other warnings for the same rule) since that rule had been written before - - // ToDo include condition again if ((warn_text[2].indexOf("duplicate") < 0)) { data += warn_text[2] @@ -1811,7 +1731,7 @@ export class KeylayoutToKmnConverter { const output_character = new TextDecoder().decode(unique_data_Rules[k].output); const output_character_unicode = this.checkOutputChar(output_character); - // if we are about to print a unicode codepoint instead of a single character we need to check if a control character is to be used + // if we are about to print a unicode codepoint instead of a single character we need to check if it is a control character if ((output_character_unicode.length > 1) && (Number("0x" + output_character_unicode.substring(2, output_character_unicode.length)) < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER)) { if (warn_text[2] == "") @@ -1820,24 +1740,20 @@ export class KeylayoutToKmnConverter { warn_text[2] = warn_text[2] + "; Use of a control character "; } - //SECONDTEXT print - // ToDo include condition again + // add a warning in front of rules in case unavailable modifiers or ambiguous rules are used + // if warning contains duplicate rules we do not write out this rule (even if there are other warnings for the same rule) since that rule had been written before if ((warn_text[1].indexOf("duplicate") < 0)) { data += warn_text[1] + "+ [" + (unique_data_Rules[k].modifier_deadkey + " " + unique_data_Rules[k].deadkey).trim() - // + "] > dk(C" + "] > dk(A" + String(unique_data_Rules[k].id_deadkey) + ")\n"; } - // THIRDTEXT print OK - // ToDo include condition again if ((warn_text[2].indexOf("duplicate") < 0)) { data += warn_text[2] - // + "dk(C" + "dk(A" + (String(unique_data_Rules[k].id_deadkey) + ") + [" + unique_data_Rules[k].modifier_key).trim() + " " @@ -1873,31 +1789,22 @@ export class KeylayoutToKmnConverter { warn_text[2] = warn_text[2] + "; Use of a control character "; } - // Todo somewhere (A12) <-> (C12) - // ToDo include condition again - // FIRSTTEXT print + // add a warning in front of rules in case unavailable modifiers or ambiguous rules are used + // if warning contains duplicate rules we do not write out this rule (even if there are other warnings for the same rule) since that rule had been written before if ((warn_text[0].indexOf("duplicate") < 0) - // || ((warn_text[0].indexOf("duplicate") >= 0) && (warn_text[0].indexOf("ambiguous") >= 0)) - // || ((warn_text[0].indexOf("duplicate") >= 0) && (warn_text[0].indexOf("unavailable") >= 0)) ) { data += warn_text[0] + "+ [" + (unique_data_Rules[k].modifier_prev_deadkey + " " + unique_data_Rules[k].prev_deadkey).trim() - //+ "] > dk(A" + "] > dk(C" + String(unique_data_Rules[k].id_prev_deadkey) + ")\n"; } - // ToDo include condition again - //SECONDTEXT print if ((warn_text[1].indexOf("duplicate") < 0) - // || ((warn_text[1].indexOf("duplicate") >= 0) && (warn_text[1].indexOf("ambiguous") >= 0)) - // || ((warn_text[1].indexOf("duplicate") >= 0) && (warn_text[1].indexOf("unavailable") >= 0)) ) { data += warn_text[1] - //+ "dk(A" + "dk(C" + (String(unique_data_Rules[k].id_prev_deadkey) + ") + [" + unique_data_Rules[k].modifier_deadkey).trim() + " " @@ -1907,11 +1814,7 @@ export class KeylayoutToKmnConverter { + ")\n"; } - // ToDo include condition again - // THIRDTEXT print OK if ((warn_text[2].indexOf("duplicate") < 0) - // || ((warn_text[2].indexOf("duplicate") >= 0) && (warn_text[2].indexOf("ambiguous") >= 0)) - // || ((warn_text[2].indexOf("duplicate") >= 0) && (warn_text[2].indexOf("unavailable") >= 0)) ) { data += warn_text[2] + "dk(B" @@ -1965,34 +1868,42 @@ export class KeylayoutToKmnConverter { /// console log all entries C3 TODO remove public writeDataset(dataRules: rule_object[]) { for (let i = 0; i < dataRules.length; i++) { + //if (dataRules[i].key === "") { + if (1 === 1) { + - console.log("dataRules ", i, + console.log("dataRules[i].key ", "..", dataRules[i].key, "..", dataRules[i].key === ""); - dataRules[i].rule_type !== "" ? dataRules[i].rule_type : "--".padEnd(4, " "), + console.log("dataRules ", i, - "| ", (dataRules[i].modifier_prev_deadkey !== "" ? dataRules[i].modifier_prev_deadkey.padEnd(33, " ") : "--".padEnd(33, " ")), - (dataRules[i].prev_deadkey !== "" ? dataRules[i].prev_deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), - (dataRules[i].id_prev_deadkey !== 0 ? ("dk(A" + String(dataRules[i].id_prev_deadkey) + ")").padEnd(11, " ") : "--".padEnd(11, " ")), - (dataRules[i].unique_prev_deadkey !== 0 ? ("unique(A" + String(dataRules[i].unique_prev_deadkey) + ")").padEnd(11, " ") : "--".padEnd(11, " ")), + dataRules[i].rule_type !== "" ? dataRules[i].rule_type : "--".padEnd(4, " "), - (dataRules[i].modifier_deadkey !== "" ? dataRules[i].modifier_deadkey.padEnd(30, " ") : "--".padEnd(30, " ")), - (dataRules[i].deadkey !== "" ? dataRules[i].deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), - dataRules[i].rule_type === "C2" ? (dataRules[i].unique_deadkey !== 0 ? ("unique(C" + String(dataRules[i].unique_deadkey) + ")").padEnd(9, " ") : "--".padEnd(9, " ")) : ((dataRules[i].unique_prev_deadkey !== 0 ? ("unique(B" + dataRules[i].id_deadkey + ")").padEnd(9, " ") : "--".padEnd(9, " "))), + "| ", (dataRules[i].modifier_prev_deadkey !== "" ? dataRules[i].modifier_prev_deadkey.padEnd(33, " ") : "--".padEnd(33, " ")), + (dataRules[i].prev_deadkey !== "" ? dataRules[i].prev_deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), + (dataRules[i].id_prev_deadkey !== 0 ? ("dk(A" + String(dataRules[i].id_prev_deadkey) + ")").padEnd(11, " ") : "--".padEnd(11, " ")), + (dataRules[i].unique_prev_deadkey !== 0 ? ("unique(A" + String(dataRules[i].unique_prev_deadkey) + ")").padEnd(11, " ") : "--".padEnd(11, " ")), - dataRules[i].id_prev_deadkey, - dataRules[i].id_deadkey, + (dataRules[i].modifier_deadkey !== "" ? dataRules[i].modifier_deadkey.padEnd(30, " ") : "--".padEnd(30, " ")), + (dataRules[i].deadkey !== "" ? dataRules[i].deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), + dataRules[i].rule_type === "C2" ? (dataRules[i].unique_deadkey !== 0 ? ("unique(C" + String(dataRules[i].unique_deadkey) + ")").padEnd(9, " ") : "--".padEnd(9, " ")) : ((dataRules[i].unique_prev_deadkey !== 0 ? ("unique(B" + dataRules[i].id_deadkey + ")").padEnd(9, " ") : "--".padEnd(9, " "))), - "| ", (dataRules[i].modifier_key !== "" ? dataRules[i].modifier_key.padEnd(40, " ") : "--".padEnd(40, " ")), - (dataRules[i].key !== "" ? dataRules[i].key.padEnd(8, " ") : "--".padEnd(8, " ")), - (new TextDecoder().decode(dataRules[i].output) !== "" ? new TextDecoder().decode(dataRules[i].output).padEnd(10, " ") : ("--" + dataRules[i].output) + "--"), + dataRules[i].id_prev_deadkey, + dataRules[i].id_deadkey, - "| °°"); + "| ", (dataRules[i].modifier_key !== "" ? dataRules[i].modifier_key.padEnd(40, " ") : "--".padEnd(40, " ")), + (dataRules[i].key !== "" ? dataRules[i].key.padEnd(8, " ") : "--".padEnd(8, " ")), + (new TextDecoder().decode(dataRules[i].output) !== "" ? new TextDecoder().decode(dataRules[i].output).padEnd(10, " ") : ("--" + dataRules[i].output) + "--"), + + "| °°"); + } } } // TODO remove public writeDatasetSingle(dataRules: rule_object) { + console.log("dataRules[i].key ", "..", dataRules.key, "..", dataRules.key === ""); + console.log("dataRules ", dataRules.rule_type !== "" ? dataRules.rule_type : "--".padEnd(4, " "), diff --git a/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts index de097ca0ab6..c5e9c9b97d4 100644 --- a/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts @@ -26,7 +26,21 @@ describe('KeylayoutToKmnConverter', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); // convert_object from usable file name - const inputFilename = makePathToFixture('../data/Italian_copy.keylayout'); + //copy into C:\Projects\keyman\keyman\developer\src\kmc-convert\test\DATA then they run OK + //const inputFilename = makePathToFixture('../data/US_complete.keylayout'); // OKOK + const inputFilename = makePathToFixture('../data/Italian_copy.keylayout'); // OKOK + //const inputFilename = makePathToFixture('../data/German_complete.keylayout'); // OK NO NCAPS SHIFT <-> SHIFT NCAPS + //const inputFilename = makePathToFixture('../data/German_Standard_copy.keylayout'); // OK NO NCAPS SHIFT <-> SHIFT NCAPS + //const inputFilename = makePathToFixture('../data/German_Standard2.keylayout'); // OKOK small + //const inputFilename = makePathToFixture('../data/Spanish_copy.keylayout'); // OKOK + //const inputFilename = makePathToFixture('../data/Latin_American_copy.keylayout'); // OKOK + //const inputFilename = makePathToFixture('../data/Swiss_French_copy.keylayout'); // OKOK + //const inputFilename = makePathToFixture('../data/Swiss_German_copy.keylayout'); // OKOK + //const inputFilename = makePathToFixture('../data/US_copy.keylayout'); // OKOK + + //const inputFilename = makePathToFixture('../data/My_dk_Keyboard.keylayout'); // No + //const inputFilename = makePathToFixture('../data/German_StandardTweaked.keylayout'); // NO C3 + const read = sut.read(inputFilename); const converted = sut.convert(read); @@ -76,20 +90,6 @@ describe('KeylayoutToKmnConverter', function () { it('run() should return true if ran OK', async function () { - //copy into C:\Projects\keyman\keyman\developer\src\kmc-convert\test\DATA then they run OK - //const inputFilename = makePathToFixture('../data/US_complete.keylayout'); // OK - //const inputFilename = makePathToFixture('../data/German_complete.keylayout'); // OK - const inputFilename = makePathToFixture('../data/Italian_copy.keylayout'); // OK - //const inputFilename = makePathToFixture('../data/German_Standard_copy.keylayout'); // OK - //const inputFilename = makePathToFixture('../data/German_Standard2.keylayout'); // OK - //const inputFilename = makePathToFixture('../data/German_StandardTweaked.keylayout'); // NO C3 - //const inputFilename = makePathToFixture('../data/Spanish_copy.keylayout'); // OK - //const inputFilename = makePathToFixture('../data/Latin_American_copy.keylayout'); // OK - //const inputFilename = makePathToFixture('../data/My_dk_Keyboard.keylayout'); // No - //const inputFilename = makePathToFixture('../data/Swiss_French_copy.keylayout'); // OK - //const inputFilename = makePathToFixture('../data/Swiss_German_copy.keylayout'); // OK - //const inputFilename = makePathToFixture('../data/US_copy.keylayout'); // OK - // TODO use path also // const outputFilename = "data//" +inputFilename.substring(0, inputFilename.lastIndexOf(".")) + ".kmn" const outputFilename = makePathToFixture('../data/MyResult.kmn'); @@ -272,7 +272,6 @@ describe('KeylayoutToKmnConverter', function () { }); }); - describe("isAcceptableKeymanModifier ", function () { [ ["NCAPS", true], From b36b0f6dc679cf37c279a0ed5637557cbad8d7cb Mon Sep 17 00:00:00 2001 From: Sabine Date: Fri, 21 Mar 2025 16:42:35 +0100 Subject: [PATCH 068/251] feat(developer): add test for converter --- developer/src/kmc-convert/src/converter.ts | 22 ++++++++-------- .../src/kmc-convert/test/test-converter.ts | 25 +++++++++++++++++++ 2 files changed, 36 insertions(+), 11 deletions(-) create mode 100644 developer/src/kmc-convert/test/test-converter.ts diff --git a/developer/src/kmc-convert/src/converter.ts b/developer/src/kmc-convert/src/converter.ts index 83cc6738ecb..0d886aab8fe 100644 --- a/developer/src/kmc-convert/src/converter.ts +++ b/developer/src/kmc-convert/src/converter.ts @@ -28,6 +28,8 @@ export interface ConverterResult extends KeymanCompilerResult { * compiler does not read or write from filesystem or network directly, but * relies on callbacks for all external IO. */ + +// _S2 this is Base class of all converters // _S2 method init: uses Interface CompilerCallbacks( loadfile,...) // _S2 method run: uses Interface CompilerCallbacks( loadfile,...) export class Converter implements KeymanCompiler { @@ -59,34 +61,32 @@ export class Converter implements KeymanCompiler { * {@link Converter.write}. * @returns Source artifacts on success, null on failure. */ - // _S2 this is Base class of all converters - // _S2 check for things( file available,...) then + // _S2 check for ( file available,...) then // _S2 finds converter e.g.keylayout->kmn ( uses converter-class-factory) - // _S2 factory uses/instanciates chiled class ( ~ in C++ virtual function in base class <-> use fun of derived class) + // _S2 factory uses/instanciates child class ( ~ in C++ virtual function in base class <-> use fun of derived class) // _S2 loads file // _S2 creates a new converter (-object) // _S2 runs conversion for this object ( run-method of this converter of keylayout-to-kmn-tonverter.ts ) async run(inputFilename: string, outputFilename?: string): Promise { -console.log('use run of converter.ts') const converterOptions: CompilerOptions = { ...defaultCompilerOptions, ...this.options, }; - if(!outputFilename) { + if (!outputFilename) { this.callbacks.reportMessage(ConverterMessages.Error_OutputFilenameIsRequired()); return null; } const ConverterClass = ConverterClassFactory.find(inputFilename, outputFilename); - if(!ConverterClass) { - this.callbacks.reportMessage(ConverterMessages.Error_NoConverterFound({inputFilename, outputFilename})); + if (!ConverterClass) { + this.callbacks.reportMessage(ConverterMessages.Error_NoConverterFound({ inputFilename, outputFilename })); return null; } const binaryData = this.callbacks.loadFile(inputFilename); - if(!binaryData) { - this.callbacks.reportMessage(ConverterMessages.Error_FileNotFound({inputFilename})); + if (!binaryData) { + this.callbacks.reportMessage(ConverterMessages.Error_FileNotFound({ inputFilename })); return null; } @@ -109,8 +109,8 @@ console.log('use run of converter.ts') * @returns true on success */ async write(artifacts: ConverterArtifacts): Promise { - for(const key of Object.keys(artifacts)) { - if(artifacts[key]) { + for (const key of Object.keys(artifacts)) { + if (artifacts[key]) { this.callbacks.fs.writeFileSync(artifacts[key].filename, artifacts[key].data); } } diff --git a/developer/src/kmc-convert/test/test-converter.ts b/developer/src/kmc-convert/test/test-converter.ts new file mode 100644 index 00000000000..a16c1767394 --- /dev/null +++ b/developer/src/kmc-convert/test/test-converter.ts @@ -0,0 +1,25 @@ +import 'mocha'; +import { assert } from 'chai'; +import { Converter } from '../src/main.js'; +import { CompilerOptions, } from "@keymanapp/developer-utils"; +import { TestCompilerCallbacks } from '@keymanapp/developer-test-helpers'; + +describe('converter class', function () { + it('should throw on failure', async function () { + const converter = new Converter(); + try { + await converter.init(null, null); + assert.fail('Expected exception'); + } catch (e) { + assert.ok(e); + } + }); + + it('should start', async function () { + const converter = new Converter(); + const callbacks = new TestCompilerCallbacks(); + const options: CompilerOptions = { saveDebug: true, shouldAddCompilerVersion: false }; + assert(await converter.init(callbacks, options)); + }); + +}); From 647fb0afcf6ffcd622a583c2d84766458b23beb2 Mon Sep 17 00:00:00 2001 From: Sabine Date: Mon, 24 Mar 2025 15:36:08 +0100 Subject: [PATCH 069/251] feat(developer): remove markers, checkIfCapsIsUsed for upper/lower/mixed case case --- .../keylayout-to-kmn-converter.ts | 386 +++++------------- .../test/test-keylayout-to-kmn-converter.ts | 120 ++++-- 2 files changed, 193 insertions(+), 313 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 3d4fecdcb93..9a99af55c05 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -8,106 +8,24 @@ import { ConverterToKmnArtifacts } from "../converter-artifacts.js"; // Todo remove these todos -// OK TODO keylayout->kmn -// OK modifiers: The identifier of the element to use for this range of hardware keyboard types. -// OK defaultIndex: The table number to use for modifier key combinations which are not explicitly specified by any element within the . -// OK write read, convert, write -// OK add data to object -// OK Use filter functions -// OK action/output:use filter etc to shorten func -// OK deadkeyables:use filter etc to shorten func -// OK dk-> for all action:use filter etc to shorten func -// OK remove unnecessary data from data_object -// OK rename symbols -// OK remove part using kmn_key_Name1 -// OK remove unnecceaasry map_UkeleleKC_To_kmn_Key_Name_Array_Position_n etc -// OK loop throught ANSI, JIS- at moment only use [keyMapSet_count] (keyMapSet_count=0) -// OK remove funcs at teh end -// OK import { makePathToFixture } from '../../test/helpers/index.js'; -// OK Mapping 0->30 or 0->K_A-> missing entries in mapping -// OK Replace any-types -// OK Several steps action-> action-> action->character ( not only action->character) -// OK Usable for all keylayout files -// OK Use callbacks as for writeFileSync -// OK objects contain only used stuff READ in: -- out: only read arrays / CONVERT in: only read arrays out: return only to write arrays -// OK Use catch blocks for file read -// OK read: answer : + [K_A] > 'a' is OK / TODO which format to use in output ? + [K_A] > 'a' (character code) or + [K_A] > U+0061 (virt Keycode) -// OK one entry vs several entry in tags -// OK no added NCAPS when first modifier in modifierMap does not contain "caps" or"caps?" -// OK naming of for-loop var i,j,k?... -// OK warning if contrADICTING RULES E:G: [ 'modifier_C0', 'SHIFT NCAPS', 'K_C', 'c'], vs [ 'modifier_C0', 'SHIFT NCAPS', 'K_C', 'C' ], -// OK print NCAPS as the first of the modifiers in create_kmn_modifier -// OK use boxXmlArray from codebase instead of my own -// OK where are rules for action+none ( a, e, u, etc) -// OK order of object member var -// OK readfilesync with paths better way? -// OK rearrange code to use read, convert, write -// OK TODO rewrite explanantion for object instead of array -// OK remove all any types -// OK public dk: number, //todo remove one -// OK todo use from elsewhere boxXmlArray_S -// OK prev_deadkeys_Ch: Uint8Array, /* Todo needed?*/ -// OK Todo remove print_draft -// OK Todo files/path !!! -// OK start Tests v ToDo remove...................................... -// OK TODO remove: test files: checkif kmn gets the same output as ukelele file(except for C3 t works well :)) -// OK ToDo needed methods -// OK where to put documentation -// OK dk <-> id_deadkey ??? -// OK check if we use the same algorithm to get Block1 data -// OK check unique_prev_deadkey, unique_deadkey, dk_prv, dk, id_deadkey -// OK check duplicate rule conditions which do I need; which can go -// OK when I run german with uniqueCAll why will there be [ ] without key anf modifier -// OK add links to HEADLINE of kmc-convert document -// OK TODO more Data stores to add ?? -// OK check for keys < 50 whern working with keys -// OK NO OUTPUT FOR SPACE in C0C1 !!! -// OK check code for code styles keyman -// check (string |number) <-> number -// tests for 3 functions read write convert -// Return conditions -// Tests throws -// Conditions NCAPS,OPT;... -// TODO move func outside of class -// Functions as object methods? -// use length to clear array instead of defining new every time (modifierMap_ONE_InKeymapSelect.length=0 + +// use cmdl parameters -> new issue/PR + +// TODO what about using actions twice in a row??? -> error msg if chain >4 -> new issue +// Todo prevent break for output ="" -> new issue + +// what if keylayout file is not correct e.g missing '>' -> new issue +// what if nodes in keylayout file do not exist/ diff name keyboard <-> keyboardA -> new issue +// --------------------------------------------------- + // Filter functions use the same type -// TODO need to use export const USVirtualKeyCodes here -// replace unique_prev_deadkey 0, >0 with true, false -// TODO what about using actions twice in a row??? -> error msg if chain >4 -// what if keylayout file is not correct e.g missing '>' -// read TODO which stores? -// OK does order of modifier matter ? -> NO -// remove all markers c0, 1-1, #### C2 ###, ... -// OK better function names for get...... -// use cmdl parameters -// OK check semicolon everywhere -// OK test run -// OK test read -// OK test convert -// OK test write -// OK test createRuleData -// OK test get_KeyMap_Code_array__From__KeyMap_Action -// OK test get_KeyActionOutput_array__From__ActionStateOutput_array -// OK test get_ActionIndex__From__ActionId -// OK test get_ActionID__From__ActionNext -// OK test get_ActionStateOutput_array__From__ActionState -// OK test get_Output__From__ActionId_None -// OK test get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array -// OK test get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput -// OK test get_KeyModifier_array__From__ActionID -// OK test get_Modifier_array__From__KeyModifier_array -// OK test create_kmn_modifier -// OK test checkIfCapsIsUsed -// OK test isAcceptableKeymanModifier -// test reviewRules -// OK test map_UkeleleKC_To_VK -// test writeData_Rules -// OK test writeData_Stores -// what if nodes in keylayout file do not exist/ diff name keyboard <-> keyboardA -// separate createRuleData and check for duplicates/amb rules -// remove todos -// check warning text +// check (string |number) <-> number + +// create NAME.kmn instead Myesult,kmn + +// ToDo "undefined" or undefined ???? + +// separate createRuleData and check for duplicates/amb rules import { XMLParser } from 'fast-xml-parser'; // for reading an xml file import { readFileSync } from 'fs'; @@ -128,7 +46,6 @@ function boxArrays(source: any) { boxXmlArray(source?.actions, 'action'); for (const action of source?.actions?.action) { boxXmlArray(action, 'when'); - } return source; } @@ -179,30 +96,25 @@ export class KeylayoutToKmnConverter { if (!inputFilename || !outputFilename) { throw new Error('Invalid parameters'); } - console.log(' _S2 first READ file ........................................in:', inputFilename); const jsonO: object = this.read(inputFilename); if (!jsonO) { - throw new Error('read() not OK'); + throw new Error('Error while processing read()'); return null; } - console.log(' _S2 then CONVERT ........................................'); const outArray: convert_object = await this.convert(jsonO); if (!outArray) { - throw new Error('convert() not OK'); + throw new Error('Error while processing convert()'); return null; } - console.log(' _S2 then WRITE to kmn .....................................'); - const out_text: boolean = this.write(outArray); if (!out_text) { - throw new Error('write() not OK'); + throw new Error('Error while processing write()'); return null; } - return null; } @@ -228,8 +140,7 @@ export class KeylayoutToKmnConverter { boxArrays(jsonObj.keyboard); // jsonObj now contains only arrays; no single fields } catch (err) { - // Todo how to break correctly; return what?? - console.log(" FILE NOT FOUND"); + console.log(err.message); } return jsonObj; } @@ -254,7 +165,7 @@ export class KeylayoutToKmnConverter { arrayOf_Rules: [] }; - // todo check for tags + // todo check tags if (jsonObj_any.hasOwnProperty("keyboard")) { data_object.keylayout_filename = jsonObj_any.keyboard['@_name'] + ".keylayout"; @@ -304,7 +215,7 @@ export class KeylayoutToKmnConverter { public createRuleData(data_ukelele: convert_object, jsonObj: any): convert_object { const object_array: rule_object[] = []; - let dk_counter_C3_A: number = 0; + let dk_counter_C3: number = 0; let dk_counter_C2: number = 0; let action_id: string; @@ -350,6 +261,8 @@ export class KeylayoutToKmnConverter { /* key */ this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), /* output */ new TextEncoder().encode(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output']), ); + + // ToDo "undefined" or undefined ???? if (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] !== "") { object_array.push(rule_obj); } @@ -545,7 +458,7 @@ export class KeylayoutToKmnConverter { /* rule_type */ "C3", /* modifier_prev_deadkey*/ this.create_kmn_modifier(b2_prev_deadkeyModifier_arr[n1][n2], isCapsused), /* prev_deadkey */ this.map_UkeleleKC_To_VK(Number(b2_prev_deadkey_arr[n3][0])), - /* id_prev_deadkey */ dk_counter_C3_A++, + /* id_prev_deadkey */ dk_counter_C3++, /* unique A */ 0, /* modifier_deadkey */ this.create_kmn_modifier(b4_deadkeyModifier_arr[n4][n5], isCapsused), @@ -573,6 +486,9 @@ export class KeylayoutToKmnConverter { } } else { console.log("ERROR : some entries are not available"); + // Todo prevent break for output ="" + console.log(" ", jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]); + } } } @@ -675,8 +591,6 @@ export class KeylayoutToKmnConverter { return data_ukelele; } - - // --------------------------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------------------------- /** @@ -1018,9 +932,8 @@ export class KeylayoutToKmnConverter { * @param keylayout_modifier the modifier value used in the .keylayout-file * @return kmn_modifier the modifier value used in the .kmn-file */ - // TODO caps <-> Caps <-> cAPs,... public checkIfCapsIsUsed(keylayout_modifier: string[][]): boolean { - return JSON.stringify(keylayout_modifier).includes("caps"); + return JSON.stringify(keylayout_modifier).toUpperCase().includes("CAPS"); } /** @@ -1065,7 +978,6 @@ export class KeylayoutToKmnConverter { * @param index the index of a rule in array[rule] * @return a string[] containing possible warnings for a rule */ - // todo remove comments in filters after check of several keylayout files public reviewRules(rule: rule_object[], index: number): string[] { const warningTextArray: string[] = Array(3).fill(""); @@ -1075,28 +987,28 @@ export class KeylayoutToKmnConverter { // Todo remoce C1-C3's and other markers if ((rule[index].rule_type === "C0") || (rule[index].rule_type === "C1")) { if (!this.isAcceptableKeymanModifier(rule[index].modifier_key)) { - warningTextArray[2] = "C1 unavailable modifier : "; + warningTextArray[2] = "unavailable modifier : "; } } else if (rule[index].rule_type === "C2") { if (!this.isAcceptableKeymanModifier(rule[index].modifier_deadkey)) { - warningTextArray[1] = "C2 unavailable modifier : "; + warningTextArray[1] = "unavailable modifier : "; } if (!this.isAcceptableKeymanModifier(rule[index].modifier_key)) { - warningTextArray[2] = "C2 unavailable modifier : "; + warningTextArray[2] = "unavailable modifier : "; } } else if (rule[index].rule_type === "C3") { if (!this.isAcceptableKeymanModifier(rule[index].modifier_prev_deadkey)) { - warningTextArray[2] = "C3 unavailable modifier : "; + warningTextArray[2] = "unavailable modifier : "; } if (!this.isAcceptableKeymanModifier(rule[index].modifier_deadkey)) { - warningTextArray[1] = "C3 unavailable modifier : "; + warningTextArray[1] = "unavailable modifier : "; } if (!this.isAcceptableKeymanModifier(rule[index].modifier_key)) { - warningTextArray[0] = "C3 unavailable modifier : "; + warningTextArray[0] = "unavailable modifier : "; } } @@ -1146,46 +1058,46 @@ export class KeylayoutToKmnConverter { if (amb_4_1.length > 0) { warningTextArray[2] = warningTextArray[2] - + ("ambiguous 4-1 rule: later: [" + + ("ambiguous rule: later: [" + amb_4_1[0].modifier_prev_deadkey + " " + amb_4_1[0].prev_deadkey + "] > dk(C" + amb_4_1[0].unique_prev_deadkey - + ") here: "); + + ") "); } - if (amb_2_1.length > 0) { + if (amb_2_1.length > 0) { warningTextArray[2] = warningTextArray[2] - + ("ambiguous 2-1 rule: later: [" + + ("ambiguous rule: later: [" + amb_2_1[0].modifier_deadkey + " " + amb_2_1[0].deadkey + "] > dk(A" + amb_2_1[0].unique_deadkey - + ") here: "); + + ") "); } - if (amb_1_1.length > 0) { + if (amb_1_1.length > 0) { warningTextArray[2] = warningTextArray[2] - + ("C1 ambiguous 1-1 rule: earlier: [" + + ("ambiguous rule: earlier: [" + amb_1_1[0].modifier_key + " " + amb_1_1[0].key + "] > \'" + new TextDecoder().decode(amb_1_1[0].output) - + "\' here: "); + + "\' "); } - if (dup_1_1.length > 0) { + if (dup_1_1.length > 0) { warningTextArray[2] = warningTextArray[2] - + ("C1 duplicate 1-1 rule: earlier: [" + + ("duplicate rule: earlier: [" + dup_1_1[0].modifier_key + " " + dup_1_1[0].key + "] > \'" + new TextDecoder().decode(dup_1_1[0].output) - + "\' here: "); + + "\' "); } } @@ -1240,28 +1152,29 @@ export class KeylayoutToKmnConverter { if (amb_2_2.length > 0) { warningTextArray[1] = warningTextArray[1] - + ("ambiguous 2-2 rule: earlier: [" + + ("ambiguous rule: earlier: [" + amb_2_2[0].modifier_deadkey + " " + amb_2_2[0].deadkey + "] > dk(C" + amb_2_2[0].id_deadkey - + ") here: "); + + ") "); } if (dup_2_2.length > 0) { warningTextArray[1] = warningTextArray[1] - + ("duplicate 2-2 rule: earlier: [" + + ("duplicate rule: earlier: [" + dup_2_2[0].modifier_deadkey + " " + dup_2_2[0].deadkey + "] > dk(C" + dup_2_2[0].id_deadkey - + ") here: "); + + ") "); } + if (amb_3_3.length > 0) { warningTextArray[2] = warningTextArray[2] - + ("ambiguous 3-3 rule: earlier: dk(C" + + ("ambiguous rule: earlier: dk(C" + amb_3_3[0].id_deadkey + ") + [" + amb_3_3[0].modifier_key @@ -1269,11 +1182,12 @@ export class KeylayoutToKmnConverter { + amb_3_3[0].key + "] > \'" + new TextDecoder().decode(amb_3_3[0].output) - + "\' here: "); + + "\' "); } + if (dup_3_3.length > 0) { warningTextArray[2] = warningTextArray[2] - + ("duplicate 3-3 rule: earlier: dk(C" + + ("duplicate rule: earlier: dk(C" + dup_3_3[0].id_deadkey + ") + [" + dup_3_3[0].modifier_key @@ -1281,18 +1195,18 @@ export class KeylayoutToKmnConverter { + dup_3_3[0].key + "] > \'" + new TextDecoder().decode(dup_3_3[0].output) - + "\' here: "); + + "\' "); } if (amb_4_2.length > 0) { warningTextArray[0] = warningTextArray[0] - + ("ambiguous 4-2 rule: later: [" + + ("ambiguous rule: later: [" + amb_4_2[0].modifier_prev_deadkey + " " + amb_4_2[0].prev_deadkey + "] > dk(C" + amb_4_2[0].id_prev_deadkey - + ") here: "); + + ") "); } } @@ -1386,18 +1300,18 @@ export class KeylayoutToKmnConverter { if (amb_2_4.length > 0) { warningTextArray[0] = warningTextArray[0] - + ("ambiguous 2-4 rule: earlier(Todo check if print out or not): [" + + ("ambiguous rule: earlier: [" + amb_2_4[0].modifier_deadkey + " " + amb_2_4[0].deadkey - + "] > dk(C" + + "] > dk(A" + amb_2_4[0].id_deadkey - + ") here: "); + + ") "); } if (amb_6_3.length > 0) { warningTextArray[1] = warningTextArray[1] - + ("ambiguous 6-3 rule: earlier: dk(C" + + ("ambiguous rule: earlier: dk(C" + amb_6_3[0].id_deadkey + ") + [" + amb_6_3[0].modifier_key @@ -1405,12 +1319,12 @@ export class KeylayoutToKmnConverter { + amb_6_3[0].key + "] > \'" + new TextDecoder().decode(amb_6_3[0].output) - + "\' here: "); + + "\' "); } if (dup_6_3.length > 0) { warningTextArray[1] = warningTextArray[1] - + ("duplicate 6-3 rule: earlier: dk(C" + + ("duplicate rule: earlier: dk(C" + dup_6_3[0].id_deadkey + ") + [" + dup_6_3[0].modifier_key @@ -1418,34 +1332,34 @@ export class KeylayoutToKmnConverter { + dup_6_3[0].key + "] > \'" + new TextDecoder().decode(dup_6_3[0].output) - + "\' here: "); + + "\' "); } if (amb_4_4.length > 0) { warningTextArray[0] = warningTextArray[0] - + ("ambiguous 4-4 rule: earlier: [" + + ("ambiguous rule: earlier: [" + amb_4_4[0].modifier_prev_deadkey + " " + amb_4_4[0].prev_deadkey + "] > dk(C" + amb_4_4[0].id_prev_deadkey - + ") here: "); + + ") "); } if (dup_4_4.length > 0) { warningTextArray[0] = warningTextArray[0] - + ("duplicate 4-4 rule: earlier: [" + + ("duplicate rule: earlier: [" + dup_4_4[0].modifier_prev_deadkey + " " + dup_4_4[0].prev_deadkey + "] > dk(C" + dup_4_4[0].id_prev_deadkey - + ") here: "); + + ") "); } if (amb_5_5.length > 0) { warningTextArray[1] = warningTextArray[1] - + ("ambiguous 5-5 rule: earlier: dk(B" + + ("ambiguous rule: earlier: dk(B" + amb_5_5[0].id_prev_deadkey + ") + [" + amb_5_5[0].modifier_deadkey @@ -1453,12 +1367,12 @@ export class KeylayoutToKmnConverter { + amb_5_5[0].deadkey + "] > dk(B" + amb_5_5[0].id_deadkey - + ") here: "); + + ") "); } if (dup_5_5.length > 0) { warningTextArray[1] = warningTextArray[1] - + ("duplicate 5-5 rule: earlier: dk(B" + + ("duplicate rule: earlier: dk(B" + dup_5_5[0].id_prev_deadkey + ") + [" + dup_5_5[0].modifier_deadkey @@ -1466,12 +1380,12 @@ export class KeylayoutToKmnConverter { + dup_5_5[0].deadkey + "] > dk(B" + dup_5_5[0].id_deadkey - + ") here: "); + + ") "); } if (amb_6_6.length > 0) { warningTextArray[2] = warningTextArray[2] - + ("ambiguous 6-6 rule: earlier: dk(B" + + ("ambiguous rule: earlier: dk(B" + amb_6_6[0].id_deadkey + ") + [" + amb_6_6[0].modifier_key @@ -1479,12 +1393,12 @@ export class KeylayoutToKmnConverter { + amb_6_6[0].key + "] > \'" + new TextDecoder().decode(amb_6_6[0].output) - + "\' here: "); + + "\' "); } if (dup_6_6.length > 0) { warningTextArray[2] = warningTextArray[2] - + ("duplicate 6-6x rule: earlier: dk(B" + + ("duplicate rule: earlier: dk(B" + dup_6_6[0].id_deadkey + ") + [" + dup_6_6[0].modifier_key @@ -1492,18 +1406,18 @@ export class KeylayoutToKmnConverter { + dup_6_6[0].key + "] > \'" + new TextDecoder().decode(dup_6_6[0].output) - + "\' here: "); + + "\' "); } } if (warningTextArray[0] !== "") { - warningTextArray[0] = "c WARNING: " + warningTextArray[0]; + warningTextArray[0] = "c WARNING: " + warningTextArray[0]+"here: "; } if (warningTextArray[1] !== "") { - warningTextArray[1] = "c WARNING: " + warningTextArray[1]; + warningTextArray[1] = "c WARNING: " + warningTextArray[1]+"here: "; } if (warningTextArray[2] !== "") { - warningTextArray[2] = "c WARNING: " + warningTextArray[2]; + warningTextArray[2] = "c WARNING: " + warningTextArray[2]+"here: "; } return warningTextArray; @@ -1590,7 +1504,7 @@ export class KeylayoutToKmnConverter { * @return a unicode codepoint if instr is a numeric character reference * else instr if instr is not a numeric character reference */ - public checkOutputChar(instr: string): string { + public convertToUnicodeCodePoint(instr: string): string { if (instr.substring(0, 3) === "&#x") { const num_length = instr.length - instr.indexOf("x") - 1; @@ -1608,10 +1522,6 @@ export class KeylayoutToKmnConverter { else return instr; } - //---------------------------------------------------------------------------------------------------- - //---------------------------------------------------------------------------------------------------- - //---------------------------------------------------------------------------------------------------- - /** * @brief member function to create a list of rule that will be printed to the resulting kmn file @@ -1626,12 +1536,10 @@ export class KeylayoutToKmnConverter { const unique_data_Rules: rule_object[] = data_ukelele.arrayOf_Rules.filter((curr) => { return ((curr.output !== new TextEncoder().encode("") || curr.output !== undefined) && (curr.key !== "") - // && ((curr.rule_type === "C0") || (curr.rule_type === "C1") || (curr.rule_type === "C2" && (curr.deadkey !== "")) || (curr.rule_type === "C3" && (curr.prev_deadkey !== ""))) && ((curr.rule_type === "C0") || (curr.rule_type === "C1") || (curr.rule_type === "C2" && (curr.deadkey !== "")) || (curr.rule_type === "C3" && (curr.deadkey !== "") && (curr.prev_deadkey !== ""))) - ); }).reduce((unique, o) => { if (!unique.some((obj: { @@ -1658,8 +1566,6 @@ export class KeylayoutToKmnConverter { return unique; }, []); - //................................................ C0 C1 ................................................................ - //................................................ C0 C1 ................................................................ //................................................ C0 C1 ................................................................ for (let k = 0; k < unique_data_Rules.length; k++) { @@ -1690,7 +1596,7 @@ export class KeylayoutToKmnConverter { const warn_text = this.reviewRules(unique_data_Rules, k); const output_character = new TextDecoder().decode(unique_data_Rules[k].output); - const output_character_unicode = this.checkOutputChar(output_character); + const output_character_unicode = this.convertToUnicodeCodePoint(output_character); // if we are about to print a unicode codepoint instead of a single character we need to check if it is a control character if ((output_character_unicode.length > 1) @@ -1703,10 +1609,10 @@ export class KeylayoutToKmnConverter { // add a warning in front of rules in case unavailable modifiers or ambiguous rules are used - // if warning contains duplicate rules we do not write out this rule (even if there are other warnings for the same rule) since that rule had been written before + // if warning contains duplicate rules we do not write out this rule + // (even if there are other warnings for the same rule) since that rule had been written before if ((warn_text[2].indexOf("duplicate") < 0)) { - data += - warn_text[2] + data += warn_text[2] + "+ [" + (unique_data_Rules[k].modifier_key + ' ' + unique_data_Rules[k].key).trim() + `] > \'` @@ -1716,11 +1622,6 @@ export class KeylayoutToKmnConverter { } } - // Todo remove this marker - data += "\n c ########## C2 #################################################################\n"; - - //................................................ C2 ................................................................... - //................................................ C2 ................................................................... //................................................ C2 ................................................................... for (let k = 0; k < unique_data_Rules.length; k++) { @@ -1729,7 +1630,7 @@ export class KeylayoutToKmnConverter { const warn_text = this.reviewRules(unique_data_Rules, k); const output_character = new TextDecoder().decode(unique_data_Rules[k].output); - const output_character_unicode = this.checkOutputChar(output_character); + const output_character_unicode = this.convertToUnicodeCodePoint(output_character); // if we are about to print a unicode codepoint instead of a single character we need to check if it is a control character if ((output_character_unicode.length > 1) @@ -1741,21 +1642,21 @@ export class KeylayoutToKmnConverter { } // add a warning in front of rules in case unavailable modifiers or ambiguous rules are used - // if warning contains duplicate rules we do not write out this rule (even if there are other warnings for the same rule) since that rule had been written before + // if warning contains duplicate rules we do not write out this rule + // (even if there are other warnings for the same rule) since that rule had been written before if ((warn_text[1].indexOf("duplicate") < 0)) { data += warn_text[1] - + "+ [" - + (unique_data_Rules[k].modifier_deadkey + " " + unique_data_Rules[k].deadkey).trim() - + "] > dk(A" - + String(unique_data_Rules[k].id_deadkey) + + "+ [" + (unique_data_Rules[k].modifier_deadkey + " " + + unique_data_Rules[k].deadkey).trim() + + "] > dk(A" + String(unique_data_Rules[k].id_deadkey) + ")\n"; } if ((warn_text[2].indexOf("duplicate") < 0)) { - data += - warn_text[2] + data += warn_text[2] + "dk(A" - + (String(unique_data_Rules[k].id_deadkey) + ") + [" + unique_data_Rules[k].modifier_key).trim() + + (String(unique_data_Rules[k].id_deadkey) + ") + [" + + unique_data_Rules[k].modifier_key).trim() + " " + unique_data_Rules[k].key + "] > \'" + output_character_unicode @@ -1767,10 +1668,6 @@ export class KeylayoutToKmnConverter { } //................................................ C3 ................................................................... - //................................................ C3 ................................................................... - //................................................ C3 ................................................................... - - data += "\nc ########## C3 #################################################################\n"; for (let k = 0; k < unique_data_Rules.length; k++) { if (unique_data_Rules[k].rule_type === "C3") { @@ -1778,7 +1675,7 @@ export class KeylayoutToKmnConverter { const warn_text = this.reviewRules(unique_data_Rules, k); const output_character = new TextDecoder().decode(unique_data_Rules[k].output); - const output_character_unicode = this.checkOutputChar(output_character); + const output_character_unicode = this.convertToUnicodeCodePoint(output_character); // if we are about to print a unicode codepoint instead of a single character we need to check if a control character is to be used if ((output_character_unicode.length > 1) @@ -1790,23 +1687,23 @@ export class KeylayoutToKmnConverter { } // add a warning in front of rules in case unavailable modifiers or ambiguous rules are used - // if warning contains duplicate rules we do not write out this rule (even if there are other warnings for the same rule) since that rule had been written before + // if warning contains duplicate rules we do not write out this rule + // (even if there are other warnings for the same rule) since that rule had been written before if ((warn_text[0].indexOf("duplicate") < 0) ) { - data += - warn_text[0] + data += warn_text[0] + "+ [" - + (unique_data_Rules[k].modifier_prev_deadkey + " " + unique_data_Rules[k].prev_deadkey).trim() + + (unique_data_Rules[k].modifier_prev_deadkey + " " + + unique_data_Rules[k].prev_deadkey).trim() + "] > dk(C" + String(unique_data_Rules[k].id_prev_deadkey) + ")\n"; } if ((warn_text[1].indexOf("duplicate") < 0) ) { - data += - warn_text[1] - + "dk(C" - + (String(unique_data_Rules[k].id_prev_deadkey) + ") + [" + unique_data_Rules[k].modifier_deadkey).trim() + data += warn_text[1] + + "dk(C" + (String(unique_data_Rules[k].id_prev_deadkey) + ") + [" + + unique_data_Rules[k].modifier_deadkey).trim() + " " + unique_data_Rules[k].deadkey + "] > dk(B" @@ -1816,9 +1713,10 @@ export class KeylayoutToKmnConverter { if ((warn_text[2].indexOf("duplicate") < 0) ) { - data += - warn_text[2] + "dk(B" - + (String(unique_data_Rules[k].id_deadkey) + ") + [" + unique_data_Rules[k].modifier_key).trim() + data += warn_text[2] + "dk(B" + + (String(unique_data_Rules[k].id_deadkey) + + ") + [" + + unique_data_Rules[k].modifier_key).trim() + " " + unique_data_Rules[k].key + "] > \'" @@ -1829,10 +1727,8 @@ export class KeylayoutToKmnConverter { if ((warn_text[0].indexOf("duplicate") < 0) || (warn_text[1].indexOf("duplicate") < 0) || (warn_text[2].indexOf("duplicate") < 0)) { data += "\n"; } - } } - return data; } @@ -1864,73 +1760,11 @@ export class KeylayoutToKmnConverter { data += "\n"; return data; } - - /// console log all entries C3 TODO remove - public writeDataset(dataRules: rule_object[]) { - for (let i = 0; i < dataRules.length; i++) { - //if (dataRules[i].key === "") { - if (1 === 1) { - - - console.log("dataRules[i].key ", "..", dataRules[i].key, "..", dataRules[i].key === ""); - - console.log("dataRules ", i, - - dataRules[i].rule_type !== "" ? dataRules[i].rule_type : "--".padEnd(4, " "), - - "| ", (dataRules[i].modifier_prev_deadkey !== "" ? dataRules[i].modifier_prev_deadkey.padEnd(33, " ") : "--".padEnd(33, " ")), - (dataRules[i].prev_deadkey !== "" ? dataRules[i].prev_deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), - (dataRules[i].id_prev_deadkey !== 0 ? ("dk(A" + String(dataRules[i].id_prev_deadkey) + ")").padEnd(11, " ") : "--".padEnd(11, " ")), - (dataRules[i].unique_prev_deadkey !== 0 ? ("unique(A" + String(dataRules[i].unique_prev_deadkey) + ")").padEnd(11, " ") : "--".padEnd(11, " ")), - - (dataRules[i].modifier_deadkey !== "" ? dataRules[i].modifier_deadkey.padEnd(30, " ") : "--".padEnd(30, " ")), - (dataRules[i].deadkey !== "" ? dataRules[i].deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), - dataRules[i].rule_type === "C2" ? (dataRules[i].unique_deadkey !== 0 ? ("unique(C" + String(dataRules[i].unique_deadkey) + ")").padEnd(9, " ") : "--".padEnd(9, " ")) : ((dataRules[i].unique_prev_deadkey !== 0 ? ("unique(B" + dataRules[i].id_deadkey + ")").padEnd(9, " ") : "--".padEnd(9, " "))), - - dataRules[i].id_prev_deadkey, - dataRules[i].id_deadkey, - - "| ", (dataRules[i].modifier_key !== "" ? dataRules[i].modifier_key.padEnd(40, " ") : "--".padEnd(40, " ")), - (dataRules[i].key !== "" ? dataRules[i].key.padEnd(8, " ") : "--".padEnd(8, " ")), - (new TextDecoder().decode(dataRules[i].output) !== "" ? new TextDecoder().decode(dataRules[i].output).padEnd(10, " ") : ("--" + dataRules[i].output) + "--"), - - "| °°"); - } - } - - } - // TODO remove - public writeDatasetSingle(dataRules: rule_object) { - - console.log("dataRules[i].key ", "..", dataRules.key, "..", dataRules.key === ""); - - console.log("dataRules ", - dataRules.rule_type !== "" ? dataRules.rule_type : "--".padEnd(4, " "), - - "| ", (dataRules.modifier_prev_deadkey !== "" ? dataRules.modifier_prev_deadkey.padEnd(33, " ") : "--".padEnd(33, " ")), - (dataRules.prev_deadkey !== "" ? dataRules.prev_deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), - (dataRules.id_prev_deadkey !== 0 ? ("dk(A" + String(dataRules.id_prev_deadkey) + ")").padEnd(11, " ") : "--".padEnd(11, " ")), - (dataRules.unique_prev_deadkey !== 0 ? ("unique(A" + String(dataRules.unique_prev_deadkey) + ")").padEnd(11, " ") : "--".padEnd(11, " ")), - - (dataRules.modifier_deadkey !== "" ? dataRules.modifier_deadkey.padEnd(30, " ") : "--".padEnd(30, " ")), - (dataRules.deadkey !== "" ? dataRules.deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), - dataRules.rule_type === "C2" ? (dataRules.unique_deadkey !== 0 ? ("unique(C" + String(dataRules.unique_deadkey) + ")").padEnd(9, " ") : "--".padEnd(9, " ")) : ((dataRules.unique_prev_deadkey !== 0 ? ("unique(B" + dataRules.id_deadkey + ")").padEnd(9, " ") : "--".padEnd(9, " "))), - - dataRules.id_prev_deadkey, - dataRules.id_deadkey, - - "| ", (dataRules.modifier_key !== "" ? dataRules.modifier_key.padEnd(40, " ") : "--".padEnd(40, " ")), - (dataRules.key !== "" ? dataRules.key.padEnd(8, " ") : "--".padEnd(8, " ")), - (new TextDecoder().decode(dataRules.output) !== "" ? new TextDecoder().decode(dataRules.output).padEnd(10, " ") : ("--" + dataRules.output) + "--"), - - "| °°"); - - } } /** - * @brief class for all storing a rule containing data for key, deadkey, previous deadkey, output) - */ + * @brief class for all storing a rule containing data for key, deadkey, previous deadkey, output) + */ class Rules { constructor( public rule_type: string, /* C0, C1, C2, C3, or C4 */ diff --git a/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts index c5e9c9b97d4..63a97cd1d97 100644 --- a/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts @@ -2,12 +2,6 @@ * Keyman is copyright (C) SIL International. MIT License. */ -/*run with -cd developer/src/kmc-convert/ -./build.sh test*/ - - - import 'mocha'; import { assert } from 'chai'; import { compilerTestCallbacks, compilerTestOptions } from './helpers/index.js'; @@ -22,39 +16,19 @@ describe('KeylayoutToKmnConverter', function () { compilerTestCallbacks.clear(); }); - // convert_object - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - - // convert_object from usable file name - //copy into C:\Projects\keyman\keyman\developer\src\kmc-convert\test\DATA then they run OK - //const inputFilename = makePathToFixture('../data/US_complete.keylayout'); // OKOK - const inputFilename = makePathToFixture('../data/Italian_copy.keylayout'); // OKOK + const inputFilename = makePathToFixture('../data/Italian_copy.keylayout'); // OKOK //const inputFilename = makePathToFixture('../data/German_complete.keylayout'); // OK NO NCAPS SHIFT <-> SHIFT NCAPS //const inputFilename = makePathToFixture('../data/German_Standard_copy.keylayout'); // OK NO NCAPS SHIFT <-> SHIFT NCAPS - //const inputFilename = makePathToFixture('../data/German_Standard2.keylayout'); // OKOK small //const inputFilename = makePathToFixture('../data/Spanish_copy.keylayout'); // OKOK //const inputFilename = makePathToFixture('../data/Latin_American_copy.keylayout'); // OKOK //const inputFilename = makePathToFixture('../data/Swiss_French_copy.keylayout'); // OKOK //const inputFilename = makePathToFixture('../data/Swiss_German_copy.keylayout'); // OKOK //const inputFilename = makePathToFixture('../data/US_copy.keylayout'); // OKOK + //const inputFilename = makePathToFixture('../data/Polish_copy.keylayout'); // OKOK - //const inputFilename = makePathToFixture('../data/My_dk_Keyboard.keylayout'); // No - //const inputFilename = makePathToFixture('../data/German_StandardTweaked.keylayout'); // NO C3 - - const read = sut.read(inputFilename); - const converted = sut.convert(read); - - // empty convert_object from unavailable file name - const inputFilename_unavailable = makePathToFixture('X.keylayout'); - const read_unavailable = sut.read(inputFilename_unavailable); - const converted_unavailable = sut.convert(read_unavailable); - - // empty convert_object from empty filename - const inputFilename_empty = makePathToFixture(''); - const read_empty = sut.read(inputFilename_empty); - const converted_empty = sut.convert(read_empty); describe("run() ", function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); it('run() should throw on null inputs', async function () { // note, could use 'chai as promised' library to make this more fluent: @@ -105,6 +79,9 @@ describe('KeylayoutToKmnConverter', function () { }); describe("read() ", function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const inputFilename_unavailable = makePathToFixture('X.keylayout'); + it('read() should return filled array on correct input', async function () { const result = sut.read(inputFilename); assert.isNotEmpty(result); @@ -137,6 +114,15 @@ describe('KeylayoutToKmnConverter', function () { }); describe("write() ", function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const read = sut.read(inputFilename); + const converted = sut.convert(read); + + // empty convert_object from unavailable file name + const inputFilename_unavailable = makePathToFixture('X.keylayout'); + const read_unavailable = sut.read(inputFilename_unavailable); + const converted_unavailable = sut.convert(read_unavailable); + it('write() should return true (no error) if no inputfile', async function () { const result = sut.write(converted_unavailable); assert.isTrue(result); @@ -149,6 +135,19 @@ describe('KeylayoutToKmnConverter', function () { }); describe("convert() ", function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const read = sut.read(inputFilename); + const converted = sut.convert(read); + + // empty convert_object from unavailable file name + const inputFilename_unavailable = makePathToFixture('X.keylayout'); + const read_unavailable = sut.read(inputFilename_unavailable); + const converted_unavailable = sut.convert(read_unavailable); + + // empty convert_object from empty filename + const inputFilename_empty = makePathToFixture(''); + const read_empty = sut.read(inputFilename_empty); + const converted_empty = sut.convert(read_empty); it('should return converted array on correct input', async function () { // we use 'converted' from above @@ -193,6 +192,8 @@ describe('KeylayoutToKmnConverter', function () { }); describe('create_kmn_modifier ', function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + [ ['anycontrol', true, 'NCAPS CTRL'], ['shift?', true, 'NCAPS'], @@ -221,6 +222,8 @@ describe('KeylayoutToKmnConverter', function () { }); describe('getHexFromString ', function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + [ ['0009', '0009'], ['000027', '001B'], @@ -243,7 +246,9 @@ describe('KeylayoutToKmnConverter', function () { }); }); - describe('checkOutputChar ', function () { + describe('convertToUnicodeCodePoint ', function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + [ ["􏘁", 'U+10F601'], ["😁", 'U+1F601'], @@ -266,13 +271,15 @@ describe('KeylayoutToKmnConverter', function () { [' ;', ' ;'] ].forEach(function (values) { it(('should convert "' + values[0] + '"').padEnd(25, " ") + 'to "' + values[1] + '"', async function () { - const result = sut.checkOutputChar(values[0] as string); + const result = sut.convertToUnicodeCodePoint(values[0] as string); assert.equal(result, values[1]); }); }); }); describe("isAcceptableKeymanModifier ", function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + [ ["NCAPS", true], ["NxCAPS", false], @@ -296,6 +303,8 @@ describe('KeylayoutToKmnConverter', function () { }); describe("map_UkeleleKC_To_VK ", function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + [ [0x00, "K_A"], [0x31, "K_SPACE"], @@ -315,6 +324,7 @@ describe('KeylayoutToKmnConverter', function () { }); describe("checkIfCapsIsUsed ", function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); it(("checkIfCapsIsUsed([['caps', 'xxx'], ['yyy']])").padEnd(45, " ") + " should return true", async function () { const result = sut.checkIfCapsIsUsed([["caps", "xxx"], ["yyy"]]); @@ -336,6 +346,10 @@ describe('KeylayoutToKmnConverter', function () { }); describe("get_Modifier_array__From__KeyModifier_array ", function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const read = sut.read(inputFilename); + const converted = sut.convert(read); + [[[['0', 0]], [['', 'shift? caps? ']]], [[['0', 1]], [['anyShift caps?', 'shift? rightShift caps? ', 'shift? leftShift caps? ', 'shift leftShift caps ']]], [[['0', 999]], [null]], @@ -363,6 +377,9 @@ describe('KeylayoutToKmnConverter', function () { }); describe("get_KeyModifier_array__From__ActionID ", function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const read = sut.read(inputFilename); + [ ["a16", [['32', 3]]], ["a19", [['45', 3]]], @@ -387,6 +404,9 @@ describe('KeylayoutToKmnConverter', function () { }); describe("get_ActionID__From__ActionNext ", function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const read = sut.read(inputFilename); + [ ["none", ""], ["a18", ""], @@ -409,6 +429,9 @@ describe('KeylayoutToKmnConverter', function () { }); describe("get_ActionIndex__From__ActionId ", function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const read = sut.read(inputFilename); + [ ["none", 0], ["a16", 8], @@ -429,6 +452,9 @@ describe('KeylayoutToKmnConverter', function () { }); describe("get_Output__From__ActionId_None ", function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const read = sut.read(inputFilename); + [["a14", "u"], ["", ""], [" ", ""], @@ -454,6 +480,8 @@ describe('KeylayoutToKmnConverter', function () { }); describe("get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array ", function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const read = sut.read(inputFilename); const b1_keycode_arr = [ ['49', 'K_SPACE', 'a0', '0', 'ˆ'], @@ -565,6 +593,19 @@ describe('KeylayoutToKmnConverter', function () { }); describe("writeData_Stores() ", function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const read = sut.read(inputFilename); + const converted = sut.convert(read); + + // empty convert_object from unavailable file name + const inputFilename_unavailable = makePathToFixture('X.keylayout'); + const read_unavailable = sut.read(inputFilename_unavailable); + const converted_unavailable = sut.convert(read_unavailable); + + // empty convert_object from empty filename + const inputFilename_empty = makePathToFixture(''); + const read_empty = sut.read(inputFilename_empty); + const converted_empty = sut.convert(read_empty); const out_expected_first: string = "c ......................................................................\n" @@ -603,6 +644,10 @@ describe('KeylayoutToKmnConverter', function () { }); describe("get_ActionStateOutput_array__From__ActionState ", function () { + + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const read = sut.read(inputFilename); + [["1", [ ['a0', '1', 'ˆ'], ['a1', '1', 'Â'], @@ -644,6 +689,11 @@ describe('KeylayoutToKmnConverter', function () { }); describe("get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput ", function () { + + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const read = sut.read(inputFilename); + const converted = sut.convert(read); + [ ["a1", "A", true, [ ['a1', 'A', 'a1', '1', 'K_A', 'SHIFT NCAPS'], @@ -675,6 +725,8 @@ describe('KeylayoutToKmnConverter', function () { }); describe("get_KeyActionOutput_array__From__ActionStateOutput_array ", function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const read = sut.read(inputFilename); const b6_actionId_arr = [ ['a0', '1', 'ˆ'], @@ -775,10 +827,4 @@ describe('KeylayoutToKmnConverter', function () { }); }); - - // Todo remove - after(function () { - console.log("\nTESTS OK ##########################################################################"); - }); - }); From 40e3beca29ce09e562447742cc12690c4a11de37 Mon Sep 17 00:00:00 2001 From: Sabine Date: Mon, 24 Mar 2025 17:24:02 +0100 Subject: [PATCH 070/251] feat(developer): split createRuleData to createRuleData and reviewRuleInputData | function comments --- .../keylayout-to-kmn-converter.ts | 156 ++++++++++-------- 1 file changed, 85 insertions(+), 71 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 9a99af55c05..c5c305c01e3 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -89,7 +89,7 @@ export class KeylayoutToKmnConverter { * @brief member function to run read/convert/write * @param inputFilename the ukelele .keylayout-file to be converted * @param outputFilename the resulting keyman .kmn-file - * @return + * @return null on success */ async run(inputFilename: string, outputFilename: string): Promise { @@ -119,11 +119,11 @@ export class KeylayoutToKmnConverter { } /** - * @brief take filename, open and read data from .keylayout-file and store in several arrays of the data object - * member function to read filename ( a .keylayout-file) and write contents into Uint8Array keys_all_Layers - * @param filename the ukelele .keylayout-file to be converted - * @return in case of success Uint8Array keys_all_Layers; else null - */ public read(filename: string): Object { + * @brief member function to parse data from a .keylayout-file and store to a json object + * @param filename the ukelele .keylayout-file to be parsed + * @return in case of success: json object containing data of the .keylayout file; else null + */ + public read(filename: string): Object { let xmlFile; let jsonObj = []; @@ -137,7 +137,7 @@ export class KeylayoutToKmnConverter { xmlFile = readFileSync((process.cwd() + "\\data" + filename.substring(filename.lastIndexOf("\\"))).replace(" ", ""), 'utf8'); const parser = new XMLParser(options); jsonObj = parser.parse(xmlFile); // get plain Object - boxArrays(jsonObj.keyboard); // jsonObj now contains only arrays; no single fields + boxArrays(jsonObj.keyboard); // jsonObj now contains arrays; no single fields } catch (err) { console.log(err.message); @@ -145,13 +145,10 @@ export class KeylayoutToKmnConverter { return jsonObj; } - /** - * @brief member function to convert data of .keylayout-file to kmn-file. This will convert/rename modifiers, position of Keys and deadkeys and save into an array - * if no tags are provided an empty data_object will be returned - * @param take data_ukelele and create a mapping from mac Keycodes to key-names and save to data_ukelele object - * @param data_ukelele (Uint8Array) data of the ukelele .keylayout-file - * @return outArray Uint8Array keys_all_Layers, the converted data for kmn-files if all layers have been converted; else null + * @brief member function to read filename and behaviour of a json object into a convert_object + * @param jsonObj containing filename, behaviour and rules of a json object + * @return an convert_object containing all data ready to print out */ public convert(jsonObj: any): convert_object { @@ -186,32 +183,12 @@ export class KeylayoutToKmnConverter { return data_object; } - /** - * @brief member function to write data from object to file - * @param data_ukelele the array holding keyboard data - * @return true if data has been written; false if not - */ - public write(data_ukelele: convert_object): boolean { - - let data: string = "\n"; - //const save_filename = "data//" + data_ukelele.keylayout_filename.substring(0, data_ukelele.keylayout_filename.lastIndexOf(".")) + ".kmn"; - - // add top part of kmn file: STORES - data += this.writeData_Stores(data_ukelele); - - // add bottom part of kmn file: RULES - data += this.writeData_Rules(data_ukelele); - - try { - this.callbacks.fs.writeFileSync("data/MyResult.kmn", new TextEncoder().encode(data)); - //this.callbacks.fs.writeFileSync(save_filename, new TextEncoder().encode(data)); - return true; - } catch (err) { - console.log('Error writing kmn file:' + err.message); - return false; - } - } - +/** + * @brief member function to read the rules contained in a json object and add array of Rules[] to an convert_object + * @param data_ukelele: an object containing the name of the input file, an array of behaviours and an (empty) array of Rules + * @param jsonObj: json Object containing all data read from a keylayout file + * @return an object containing the name of the input file, an array of behaviours and a populated array of Rules[] + */ public createRuleData(data_ukelele: convert_object, jsonObj: any): convert_object { const object_array: rule_object[] = []; @@ -492,6 +469,17 @@ export class KeylayoutToKmnConverter { } } } + data_ukelele.arrayOf_Rules = object_array; + + return this.reviewRuleInputData(data_ukelele); + } + +/** + * @brief member function to review data in array of Rules[] of data_ukelele: remove duplicate rules and mark first occurace of a rule in object_array + * @param data_ukelele: an object containing the name of the input file, an array of behaviours and an array of Rules + * @return an object containing the name of the input file, an array of behaviours and the revised array of Rules[] + */ + public reviewRuleInputData(data_ukelele: convert_object): convert_object { // -------------------------------------------------------------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------------------------------------------------------------- @@ -502,6 +490,7 @@ export class KeylayoutToKmnConverter { let unique_dkB_count = 0; const list_of_unique_Text2_rules: string[][] = []; + const object_array: rule_object[] = data_ukelele.arrayOf_Rules; //------------------------------------ C2: dk ---------------------------------- // first rule is always unique object_array[0].unique_deadkey = unique_dkB_count; @@ -591,10 +580,35 @@ export class KeylayoutToKmnConverter { return data_ukelele; } + /** + * @brief member function to write data from object to a kmn file + * @param data_ukelele the array holding all keyboard data + * @return true if data has been written; false if not + */ + public write(data_ukelele: convert_object): boolean { + + let data: string = "\n"; + //const save_filename = "data//" + data_ukelele.keylayout_filename.substring(0, data_ukelele.keylayout_filename.lastIndexOf(".")) + ".kmn"; + + // add top part of kmn file: STORES + data += this.writeData_Stores(data_ukelele); + + // add bottom part of kmn file: RULES + data += this.writeData_Rules(data_ukelele); + + try { + this.callbacks.fs.writeFileSync("data/MyResult.kmn", new TextEncoder().encode(data)); + //this.callbacks.fs.writeFileSync(save_filename, new TextEncoder().encode(data)); + return true; + } catch (err) { + console.log('Error writing kmn file:' + err.message); + return false; + } + } // --------------------------------------------------------------------------------------------------------------------- /** - * @brief loop through data and and return array of [Keycode,Keyname,actionId,actionIDIndex, output] for a given actionID + * @brief member function to return array of [Keycode,Keyname,actionId,actionIDIndex, output] for a given actionID in of [ actionID,state,output] * @param data :any - an object containing all data read from a .keylayout file * @param search :string[][] - array of [ actionID,state,output] * @return a string[][] containing [Keycode,Keyname,actionId,actionIDIndex, output] @@ -627,10 +641,10 @@ export class KeylayoutToKmnConverter { } /** - * @brief loop through data, find the actionID and return its index + * @brief member function to return an index for a given actionID * @param data :any - an object containing all data read from a .keylayout file - * @param search :string - value next to be found - * @return a number containing the index of an actionId + * @param search :string - value 'id' to be found + * @return a number specifying the index of an actionId */ public get_ActionIndex__From__ActionId(data: any, search: string): number { for (let i = 0; i < data.keyboard.actions.action.length; i++) { @@ -642,9 +656,9 @@ export class KeylayoutToKmnConverter { } /** - * @brief loop through data, find the actionID of a certain state-next pair + * @brief member function to find the actionID of a certain state-next pair * @param data :any an object containing all data read from a .keylayout file - * @param search :string value next to be found + * @param search :string value 'next' to be found * @return a string containing the actionId of a certain state-next pair */ public get_ActionID__From__ActionNext(data: any, search: string): string { @@ -661,9 +675,9 @@ export class KeylayoutToKmnConverter { } /** - * @brief loop through data, find all actionId-output pairs for a certain state and store in an array + * @brief member function to get an array of all actionId-output pairs for a certain state * @param data : any an object containing all data read from a .keylayout file - * @param search : string a state to be found + * @param search : string a 'state' to be found * @return an array: string[][] containing all [actionId, state, output] for a certain state */ public get_ActionStateOutput_array__From__ActionState(data: any, search: string): string[][] { @@ -686,7 +700,7 @@ export class KeylayoutToKmnConverter { } /** - * @brief loop through data, find the output for a certain actionID for state none + * @brief member function to find the output for a certain actionID for state 'none' * @param data :any an object containing all data read from a .keylayout file * @param search :string an actionId to be found * @return a string containing the output character @@ -707,7 +721,7 @@ export class KeylayoutToKmnConverter { } /** - * @brief loop through data and create an 2D array of [KeyName,actionId,behaviour,modifier,output] + * @brief member function to create an 2D array of [KeyName,actionId,behaviour,modifier,output] * @param data : any an object containing all data read from a .keylayout file * @param search : array of [keycode,keyname,actionId,behaviour,output] to be found * @param isCAPSused : boolean flag to indicate if CAPS is used in a keylayout file or not @@ -754,7 +768,7 @@ export class KeylayoutToKmnConverter { } /** - * @brief loop through data and create an array of [actionID, output, behaviour,keyname,modifier] for a given actionId + * @brief member function to create an array of [actionID, output, behaviour,keyname,modifier] for a given actionId * @param data : any - an object containing all data read from a .keylayout file * @param modi : any - an array of modifiers * @param search : string - an actionId to be found @@ -809,7 +823,7 @@ export class KeylayoutToKmnConverter { } /** - * @brief loop through data and create an array of [keycode,behaviour] for a given actionId + * @brief member function to create an array of [keycode,behaviour] for a given actionId * @param data : any - an object containing all data read from a .keylayout file * @param search : string - an actionId to be found * @return an array: number[][] containing [keycode,behaviour] @@ -832,9 +846,9 @@ export class KeylayoutToKmnConverter { } /** - * @brief loop through data and create an array of modifier behaviours for a given keycode in [keycode,modifier] + * @brief member function to create an array of modifier behaviours for a given keycode in [keycode,modifier] * @param data : any - an object containing all data read from a .keylayout file - * @param search : number[][] - an array[keycode,modifier] to be found + * @param search : (string | number)[][] - an array[keycode,modifier] to be found * @return an array: string[] containing modifiers */ public get_Modifier_array__From__KeyModifier_array(data: any, search: (string | number)[][]): string[] { @@ -846,10 +860,10 @@ export class KeylayoutToKmnConverter { } /** - * @brief create a kmn modifier from a keylayout modifier + * @brief member function to create a kmn modifier from a keylayout modifier * @param keylayout_modifier :string - modifier used in a .keylayout file * @param isCAPSused : boolean flag to indicate if CAPS is used in a keylayout file or not - * @return string - a modifier value suitable to use in a .kmn-file + * @return string - a modifier value suitable for use in a .kmn-file */ public create_kmn_modifier(keylayout_modifier: string, isCAPSused: boolean): string { let add_modifier: string = ""; @@ -928,19 +942,18 @@ export class KeylayoutToKmnConverter { } /** - * @brief check if CAPS is used in a keylayout file or not - * @param keylayout_modifier the modifier value used in the .keylayout-file - * @return kmn_modifier the modifier value used in the .kmn-file + * @brief member function to check if CAPS is used throughout a keylayout file or not + * @param keylayout_modifier the modifier string used in the .keylayout-file + * @return kmn_modifier the modifier string used in the .kmn-file */ public checkIfCapsIsUsed(keylayout_modifier: string[][]): boolean { return JSON.stringify(keylayout_modifier).toUpperCase().includes("CAPS"); } /** - * @brief check if CAPS is used in a keylayout file or not - * @param keylayout_modifier the modifier value used in the .keylayout-file - * @return true if a modifier can be used in keyman - * false if not + * @brief member function to check if a modifier can be used in keyman + * @param keylayout_modifier the modifier string used in the .keylayout-file + * @return true if the modifier can be used in keyman; false if not */ public isAcceptableKeymanModifier(keylayout_modifier: string): boolean { if (keylayout_modifier === null) @@ -971,7 +984,7 @@ export class KeylayoutToKmnConverter { } /** - * @brief check rules for acceptable modifiers, duplicate or ambiguous rules and return an array containing possible warnings + * @brief member function to reviev rules for acceptable modifiers, duplicate or ambiguous rules and return an array containing possible warnings * definition of comparisons e.g. 1-1, 2-4, 6-6 * see https://docs.google.com/document/d/12J3NGO6RxIthCpZDTR8FYSRjiMgXJDLwPY2z9xqKzJ0/edit?tab=t.0#heading=h.pcz8rjyrl5ug * @param rule : rule_object[] - an array of all rules @@ -1411,13 +1424,13 @@ export class KeylayoutToKmnConverter { } if (warningTextArray[0] !== "") { - warningTextArray[0] = "c WARNING: " + warningTextArray[0]+"here: "; + warningTextArray[0] = "c WARNING: " + warningTextArray[0] + "here: "; } if (warningTextArray[1] !== "") { - warningTextArray[1] = "c WARNING: " + warningTextArray[1]+"here: "; + warningTextArray[1] = "c WARNING: " + warningTextArray[1] + "here: "; } if (warningTextArray[2] !== "") { - warningTextArray[2] = "c WARNING: " + warningTextArray[2]+"here: "; + warningTextArray[2] = "c WARNING: " + warningTextArray[2] + "here: "; } return warningTextArray; @@ -1502,7 +1515,7 @@ export class KeylayoutToKmnConverter { * @brief member function to convert a numeric character reference to a unicode codepoint * @param instr the value that will converted * @return a unicode codepoint if instr is a numeric character reference - * else instr if instr is not a numeric character reference + * instr if instr is not a numeric character reference */ public convertToUnicodeCodePoint(instr: string): string { @@ -1524,9 +1537,9 @@ export class KeylayoutToKmnConverter { } /** - * @brief member function to create a list of rule that will be printed to the resulting kmn file + * @brief member function to create data from rules that will be printed to the resulting kmn file * @param data_ukelele an object containing all data read from a .keylayout file - * @return string - a list of rules + * @return string - all rules to be printed */ public writeData_Rules(data_ukelele: convert_object): string { @@ -1733,9 +1746,9 @@ export class KeylayoutToKmnConverter { } /** - * @brief member function to create list of stores that will be printed to the resulting kmn file + * @brief member function to create data for stores that will be printed to the resulting kmn file * @param data_ukelele an object containing all data read from a .keylayout file - * @return string - a list of stores + * @return string - all stores to be printed */ public writeData_Stores(data_ukelele: convert_object): string { @@ -1760,6 +1773,7 @@ export class KeylayoutToKmnConverter { data += "\n"; return data; } + } /** From 56c21bd897483898aa7815df5105842fefada366 Mon Sep 17 00:00:00 2001 From: Sabine Date: Wed, 26 Mar 2025 14:21:37 +0100 Subject: [PATCH 071/251] feat(developer): add several .keylayout files to git; rearrange methods --- .../src/kmc-convert/data/French.keylayout | 1066 ++++++++++++ .../src/kmc-convert/data/Italian.keylayout | 1060 ++++++++++++ .../data/Italian_command.keylayout | 1063 ++++++++++++ .../kmc-convert/data/Latin_American.keylayout | 820 +++++++++ .../src/kmc-convert/data/Polish.keylayout | 1030 +++++++++++ .../src/kmc-convert/data/Spanish.keylayout | 1062 ++++++++++++ .../kmc-convert/data/Swiss_French.keylayout | 1174 +++++++++++++ .../kmc-convert/data/Swiss_German.keylayout | 1289 ++++++++++++++ developer/src/kmc-convert/data/US.keylayout | 1136 ++++++++++++ .../keylayout-to-kmn-converter.ts | 1122 ++++++------ .../test/test-keylayout-to-kmn-converter.ts | 1533 +++++++++-------- 11 files changed, 11128 insertions(+), 1227 deletions(-) create mode 100644 developer/src/kmc-convert/data/French.keylayout create mode 100644 developer/src/kmc-convert/data/Italian.keylayout create mode 100644 developer/src/kmc-convert/data/Italian_command.keylayout create mode 100644 developer/src/kmc-convert/data/Latin_American.keylayout create mode 100644 developer/src/kmc-convert/data/Polish.keylayout create mode 100644 developer/src/kmc-convert/data/Spanish.keylayout create mode 100644 developer/src/kmc-convert/data/Swiss_French.keylayout create mode 100644 developer/src/kmc-convert/data/Swiss_German.keylayout create mode 100644 developer/src/kmc-convert/data/US.keylayout diff --git a/developer/src/kmc-convert/data/French.keylayout b/developer/src/kmc-convert/data/French.keylayout new file mode 100644 index 00000000000..a4c0743b37f --- /dev/null +++ b/developer/src/kmc-convert/data/French.keylayout @@ -0,0 +1,1066 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/data/Italian.keylayout b/developer/src/kmc-convert/data/Italian.keylayout new file mode 100644 index 00000000000..7d1c75953e1 --- /dev/null +++ b/developer/src/kmc-convert/data/Italian.keylayout @@ -0,0 +1,1060 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/data/Italian_command.keylayout b/developer/src/kmc-convert/data/Italian_command.keylayout new file mode 100644 index 00000000000..77832fd2bb7 --- /dev/null +++ b/developer/src/kmc-convert/data/Italian_command.keylayout @@ -0,0 +1,1063 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/data/Latin_American.keylayout b/developer/src/kmc-convert/data/Latin_American.keylayout new file mode 100644 index 00000000000..4a5d3b198c1 --- /dev/null +++ b/developer/src/kmc-convert/data/Latin_American.keylayout @@ -0,0 +1,820 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/data/Polish.keylayout b/developer/src/kmc-convert/data/Polish.keylayout new file mode 100644 index 00000000000..c2a52899e73 --- /dev/null +++ b/developer/src/kmc-convert/data/Polish.keylayout @@ -0,0 +1,1030 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/data/Spanish.keylayout b/developer/src/kmc-convert/data/Spanish.keylayout new file mode 100644 index 00000000000..b5fbe9714bf --- /dev/null +++ b/developer/src/kmc-convert/data/Spanish.keylayout @@ -0,0 +1,1062 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/data/Swiss_French.keylayout b/developer/src/kmc-convert/data/Swiss_French.keylayout new file mode 100644 index 00000000000..8bd3f689971 --- /dev/null +++ b/developer/src/kmc-convert/data/Swiss_French.keylayout @@ -0,0 +1,1174 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/data/Swiss_German.keylayout b/developer/src/kmc-convert/data/Swiss_German.keylayout new file mode 100644 index 00000000000..9d4d5be6a1e --- /dev/null +++ b/developer/src/kmc-convert/data/Swiss_German.keylayout @@ -0,0 +1,1289 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/data/US.keylayout b/developer/src/kmc-convert/data/US.keylayout new file mode 100644 index 00000000000..eaf4fbb4195 --- /dev/null +++ b/developer/src/kmc-convert/data/US.keylayout @@ -0,0 +1,1136 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index c5c305c01e3..c715809236d 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -18,14 +18,9 @@ import { ConverterToKmnArtifacts } from "../converter-artifacts.js"; // what if nodes in keylayout file do not exist/ diff name keyboard <-> keyboardA -> new issue // --------------------------------------------------- -// Filter functions use the same type -// check (string |number) <-> number +// add all tests again& remove data files test +// SHIFT NCAPS <-> NCAPS SHIFT -// create NAME.kmn instead Myesult,kmn - -// ToDo "undefined" or undefined ???? - -// separate createRuleData and check for duplicates/amb rules import { XMLParser } from 'fast-xml-parser'; // for reading an xml file import { readFileSync } from 'fs'; @@ -93,7 +88,8 @@ export class KeylayoutToKmnConverter { */ async run(inputFilename: string, outputFilename: string): Promise { - if (!inputFilename || !outputFilename) { + //if (!inputFilename || !outputFilename) { + if (!inputFilename) { throw new Error('Invalid parameters'); } const jsonO: object = this.read(inputFilename); @@ -110,7 +106,7 @@ export class KeylayoutToKmnConverter { return null; } - const out_text: boolean = this.write(outArray); + const out_text: boolean = this.write(outArray, outputFilename); if (!out_text) { throw new Error('Error while processing write()'); return null; @@ -183,12 +179,12 @@ export class KeylayoutToKmnConverter { return data_object; } -/** - * @brief member function to read the rules contained in a json object and add array of Rules[] to an convert_object - * @param data_ukelele: an object containing the name of the input file, an array of behaviours and an (empty) array of Rules - * @param jsonObj: json Object containing all data read from a keylayout file - * @return an object containing the name of the input file, an array of behaviours and a populated array of Rules[] - */ + /** + * @brief member function to read the rules contained in a json object and add array of Rules[] to an convert_object + * @param data_ukelele: an object containing the name of the input file, an array of behaviours and an (empty) array of Rules + * @param jsonObj: json Object containing all data read from a keylayout file + * @return an object containing the name of the input file, an array of behaviours and a populated array of Rules[] + */ public createRuleData(data_ukelele: convert_object, jsonObj: any): convert_object { const object_array: rule_object[] = []; @@ -214,8 +210,8 @@ export class KeylayoutToKmnConverter { // ...............e. g. ............................................................................... // ............................................................................................................................... - if ((jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] !== undefined) - && (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] !== "")) { + if ((jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] !== undefined) && (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] !== "") + ) { // loop behaviours for (let l = 0; l < data_ukelele.arrayOf_Modifiers[i].length; l++) { @@ -240,9 +236,9 @@ export class KeylayoutToKmnConverter { ); // ToDo "undefined" or undefined ???? - if (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] !== "") { - object_array.push(rule_obj); - } + // if (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] !== "") { + object_array.push(rule_obj); + // } } } @@ -462,9 +458,11 @@ export class KeylayoutToKmnConverter { } } } else { - console.log("ERROR : some entries are not available"); - // Todo prevent break for output ="" - console.log(" ", jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]); + console.log("ERROR : some output characters can not be used in keyman \"", + (jsonObj.keyboard['@_name'] + ".keylayout\""), + "\"\" :", + jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]); + continue; } } @@ -474,23 +472,21 @@ export class KeylayoutToKmnConverter { return this.reviewRuleInputData(data_ukelele); } -/** - * @brief member function to review data in array of Rules[] of data_ukelele: remove duplicate rules and mark first occurace of a rule in object_array - * @param data_ukelele: an object containing the name of the input file, an array of behaviours and an array of Rules - * @return an object containing the name of the input file, an array of behaviours and the revised array of Rules[] - */ + /** + * @brief member function to review data in array of Rules[] of data_ukelele: remove duplicate rules and mark first occurace of a rule in object_array + * @param data_ukelele: an object containing the name of the input file, an array of behaviours and an array of Rules + * @return an object containing the name of the input file, an array of behaviours and the revised array of Rules[] + */ public reviewRuleInputData(data_ukelele: convert_object): convert_object { - // -------------------------------------------------------------------------------------------------------------------------------------------------- - // -------------------------------------------------------------------------------------------------------------------------------------------------- // check for duplicate C2 and C3 rules in object_array (e.g. [NCAPS RALT K_8] > dk(C12) ): create a separate array of unique rules, // then compare to object_array and mark first occurrence of a rule in object_array - // -------------------------------------------------------------------------------------------------------------------------------------------------- - // -------------------------------------------------------------------------------------------------------------------------------------------------- + let unique_dkB_count = 0; const list_of_unique_Text2_rules: string[][] = []; const object_array: rule_object[] = data_ukelele.arrayOf_Rules; + //------------------------------------ C2: dk ---------------------------------- // first rule is always unique object_array[0].unique_deadkey = unique_dkB_count; @@ -541,7 +537,7 @@ export class KeylayoutToKmnConverter { } } - // check if first part of C3 rule contains already defined rule of C2 + // check if first part of C3 rule contains a rule that is already defined in C2 if (isFirstUsedHere_prev_dk) { object_array[i].unique_prev_deadkey = unique_dkA_count; unique_dkA_count++; @@ -583,12 +579,18 @@ export class KeylayoutToKmnConverter { /** * @brief member function to write data from object to a kmn file * @param data_ukelele the array holding all keyboard data + * @param outputfilename the file that will be written; if no outputfilename is given an outputfilename will be created from data_ukelele.keylayout_filename * @return true if data has been written; false if not */ - public write(data_ukelele: convert_object): boolean { - + public write(data_ukelele: convert_object, outputfilename: string = ""): boolean { + let save_filename; let data: string = "\n"; - //const save_filename = "data//" + data_ukelele.keylayout_filename.substring(0, data_ukelele.keylayout_filename.lastIndexOf(".")) + ".kmn"; + + if ((outputfilename === "") || (outputfilename === null)) { + save_filename = "data//" + data_ukelele.keylayout_filename.substring(0, data_ukelele.keylayout_filename.lastIndexOf(".")) + ".kmn"; + } + else + save_filename = outputfilename; // add top part of kmn file: STORES data += this.writeData_Stores(data_ukelele); @@ -597,390 +599,150 @@ export class KeylayoutToKmnConverter { data += this.writeData_Rules(data_ukelele); try { - this.callbacks.fs.writeFileSync("data/MyResult.kmn", new TextEncoder().encode(data)); - //this.callbacks.fs.writeFileSync(save_filename, new TextEncoder().encode(data)); + this.callbacks.fs.writeFileSync(save_filename, new TextEncoder().encode(data)); return true; } catch (err) { console.log('Error writing kmn file:' + err.message); return false; } } - // --------------------------------------------------------------------------------------------------------------------- /** - * @brief member function to return array of [Keycode,Keyname,actionId,actionIDIndex, output] for a given actionID in of [ actionID,state,output] - * @param data :any - an object containing all data read from a .keylayout file - * @param search :string[][] - array of [ actionID,state,output] - * @return a string[][] containing [Keycode,Keyname,actionId,actionIDIndex, output] - */ - public get_KeyActionOutput_array__From__ActionStateOutput_array(data: any, search: string[][]): string[][] { + * @brief member function to create a kmn modifier from a keylayout modifier + * @param keylayout_modifier :string - modifier used in a .keylayout file + * @param isCAPSused : boolean flag to indicate if CAPS is used in a keylayout file or not + * @return string - a modifier value suitable for use in a .kmn-file + */ + public create_kmn_modifier(keylayout_modifier: string, isCAPSused: boolean): string { + let add_modifier: string = ""; + let kmn_modifier: string = ""; + let kmn_ncaps: string = ""; - if ((search === undefined) || (search === null)) - return []; + const modifier_state: string[] = keylayout_modifier.split(" "); - const returnarray2D: string[][] = []; - for (let k = 0; k < search.length; k++) { - for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { - for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { - const returnarray: string[] = []; - if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search[k][0] && - data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'] < KeylayoutToKmnConverter.USED_KEYS_COUNT) { - returnarray.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']); - returnarray.push(this.map_UkeleleKC_To_VK(Number(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']))); - returnarray.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action']); - returnarray.push(data.keyboard.keyMapSet[0].keyMap[i]['@_index']); - returnarray.push(search[k][2]); - } - if (returnarray.length > 0) { - returnarray2D.push(returnarray); - } - } + for (let i = 0; i < modifier_state.length; i++) { + + if (isCAPSused && (keylayout_modifier).toUpperCase().indexOf("CAPS") === -1) { + kmn_ncaps = " NCAPS "; } - } - return returnarray2D; - } - /** - * @brief member function to return an index for a given actionID - * @param data :any - an object containing all data read from a .keylayout file - * @param search :string - value 'id' to be found - * @return a number specifying the index of an actionId - */ - public get_ActionIndex__From__ActionId(data: any, search: string): number { - for (let i = 0; i < data.keyboard.actions.action.length; i++) { - if (data.keyboard.actions.action[i]['@_id'] === search) { - return i; + // if we find a modifier containing a '?' e.g. SHIFT? => SHIFT occurs 0 or 1 times so it is not necessary. If it is not necessary we don't write this modifier + if (modifier_state[i].toUpperCase().includes('?') && (!modifier_state[i].toUpperCase().includes('CAPS?'))) { + add_modifier = ""; } - } - return 0; - } - /** - * @brief member function to find the actionID of a certain state-next pair - * @param data :any an object containing all data read from a .keylayout file - * @param search :string value 'next' to be found - * @return a string containing the actionId of a certain state-next pair - */ - public get_ActionID__From__ActionNext(data: any, search: string): string { - if (search !== "none") { - for (let i = 0; i < data.keyboard.actions.action.length; i++) { - for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { - if (data.keyboard.actions.action[i].when[j]['@_next'] === search) { - return data.keyboard.actions.action[i]['@_id']; - } - } + // if we find caps? => caps is not necessary. If caps is not necessary and isCAPSused we need to write out NCAPS. + else if (isCAPSused && (modifier_state[i].toUpperCase().includes('CAPS?'))) { + add_modifier = "NCAPS "; + } + else if (!isCAPSused && (modifier_state[i].toUpperCase().includes('CAPS?'))) { + add_modifier = ""; + } + else if (modifier_state[i].toUpperCase().includes('CAPS')) { + add_modifier = "CAPS "; + } + else if (isCAPSused && (modifier_state[i].toUpperCase().includes('NCAPS'))) { + add_modifier = "NCAPS "; } - } - return ""; - } - /** - * @brief member function to get an array of all actionId-output pairs for a certain state - * @param data : any an object containing all data read from a .keylayout file - * @param search : string a 'state' to be found - * @return an array: string[][] containing all [actionId, state, output] for a certain state - */ - public get_ActionStateOutput_array__From__ActionState(data: any, search: string): string[][] { - const returnarray2D: string[][] = []; + else if ((modifier_state[i].toUpperCase() === 'ANYSHIFT') || (modifier_state[i].toUpperCase() === 'SHIFT')) { + add_modifier = "SHIFT "; + } + else if ((modifier_state[i].toUpperCase() === "LEFTSHIFT") || (modifier_state[i].toUpperCase() === "LSHIFT")) { + add_modifier = "SHIFT "; + } + else if ((modifier_state[i].toUpperCase() === "RIGHTSHIFT") || (modifier_state[i].toUpperCase() === "RSHIFT")) { + add_modifier = "SHIFT "; + } - for (let i = 0; i < data.keyboard.actions.action.length; i++) { - for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { - const returnarray: string[] = []; - if ((data.keyboard.actions.action[i].when[j]['@_state'] === search)) { - returnarray.push(data.keyboard.actions.action[i]['@_id']); - returnarray.push(data.keyboard.actions.action[i].when[j]['@_state']); - returnarray.push(data.keyboard.actions.action[i].when[j]['@_output']); - } - if (returnarray.length > 0) { - returnarray2D.push(returnarray); - } + else if ((modifier_state[i].toUpperCase() === 'ANYCONTROL') || (modifier_state[i].toUpperCase() === 'CONTROL')) { + add_modifier = "CTRL "; + } + else if ((modifier_state[i].toUpperCase() === "LEFTCONTROL") || (modifier_state[i].toUpperCase() === "LCONTROL")) { + add_modifier = "LCTRL "; + } + else if ((modifier_state[i].toUpperCase() === "RIGHTCONTROL") || (modifier_state[i].toUpperCase() === "RCONTROL")) { + add_modifier = "RCTRL "; } - } - return returnarray2D; - } - /** - * @brief member function to find the output for a certain actionID for state 'none' - * @param data :any an object containing all data read from a .keylayout file - * @param search :string an actionId to be found - * @return a string containing the output character - */ - public get_Output__From__ActionId_None(data: any, search: string): string { - let OutputValue: string = ""; + else if ((modifier_state[i].toUpperCase() === "LEFTOPTION") || (modifier_state[i].toUpperCase() === "LOPTION")) { + add_modifier = "LALT "; + } + else if ((modifier_state[i].toUpperCase() === "RIGHTOPTION") || (modifier_state[i].toUpperCase() === "ROPTION")) { + add_modifier = "RALT "; + } + else if ((modifier_state[i].toUpperCase() === 'ANYOPTION') || (modifier_state[i].toUpperCase() === 'OPTION')) { + add_modifier = "RALT "; + } - for (let i = 0; i < data.keyboard.actions.action.length; i++) { - if (data.keyboard.actions.action[i]['@_id'] === search) { - for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { - if (data.keyboard.actions.action[i].when[j]['@_state'] === "none") { - OutputValue = data.keyboard.actions.action[i].when[j]['@_output']; - } - } + else { + add_modifier = String(modifier_state[i]) + " "; } + kmn_modifier += kmn_ncaps + add_modifier; + //console.log("kmn_modifier ", kmn_modifier); + } - return OutputValue; + + // remove duplicate and empty entries and make sure NCAPS is at the beginning + const duplicate_modifier_array: string[] = kmn_modifier.split(" ").filter(item => item); + const unique_modifier: string[] = duplicate_modifier_array.filter(function (item, pos, self) { + /* + console.log("kmn_modifier ", kmn_modifier); + console.log("duplicate_modifier_array ", duplicate_modifier_array); + + + if (kmn_modifier.indexOf("NCAPS") !== -1) { + duplicate_modifier_array.unshift("NCAPS"); + } + console.log(" duplicate_modifier_array", duplicate_modifier_array); + + + */ + return self.indexOf(item) === pos; + }); + return unique_modifier.flat().toString().replace(/,/g, " "); } /** - * @brief member function to create an 2D array of [KeyName,actionId,behaviour,modifier,output] - * @param data : any an object containing all data read from a .keylayout file - * @param search : array of [keycode,keyname,actionId,behaviour,output] to be found - * @param isCAPSused : boolean flag to indicate if CAPS is used in a keylayout file or not - * @return an array: string[][] containing [KeyName,actionId,behaviour,modifier,output] + * @brief member function to check if CAPS is used throughout a keylayout file or not + * @param keylayout_modifier the modifier string used in the .keylayout-file + * @return kmn_modifier the modifier string used in the .kmn-file */ - public get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(data: any, search: (boolean | string)[][], isCAPSused: boolean): string[][] { - const returnarray: string[][] = []; + public checkIfCapsIsUsed(keylayout_modifier: string[][]): boolean { + return JSON.stringify(keylayout_modifier).toUpperCase().includes("CAPS"); + } - if (!((search === undefined) || (search === null) || (search.length === 0))) { - for (let i = 0; i < search.length; i++) { - const behaviour: number = Number(search[i][3]); + /** + * @brief member function to check if a modifier can be used in keyman + * @param keylayout_modifier the modifier string used in the .keylayout-file + * @return true if the modifier can be used in keyman; false if not + */ + public isAcceptableKeymanModifier(keylayout_modifier: string): boolean { + if (keylayout_modifier === null) + return false; - for (let j = 0; j < data.keyboard.modifierMap.keyMapSelect[behaviour].modifier.length; j++) { - const returnarray1D: string[] = []; - // KeyName - returnarray1D.push(String(search[i][1])); - // actionId - returnarray1D.push(String(search[i][2])); - // behaviour - returnarray1D.push(String(search[i][3])); - // modifier - returnarray1D.push(String(this.create_kmn_modifier(data.keyboard.modifierMap.keyMapSelect[behaviour].modifier[j]['@_keys'], isCAPSused))); - // output - returnarray1D.push(String(search[i][4])); + let iskKeymanModifier: boolean = true; + const modifier_single: string[] = keylayout_modifier.split(" "); - if (returnarray1D.length > 0) { - returnarray.push(returnarray1D); - } - } + for (let i = 0; i < modifier_single.length; i++) { + if ( + (modifier_single[i].toUpperCase() === "NCAPS") + || (modifier_single[i].toUpperCase() === "CAPS") + || (modifier_single[i].toUpperCase() === "SHIFT") + || (modifier_single[i].toUpperCase() === "ALT") + || (modifier_single[i].toUpperCase() === "RALT") + || (modifier_single[i].toUpperCase() === "LALT") + || (modifier_single[i].toUpperCase() === "CTRL") + || (modifier_single[i].toUpperCase() === "LCTRL") + || (modifier_single[i].toUpperCase() === "RCTRL") + || (modifier_single[i].toUpperCase() === "") + ) { + iskKeymanModifier &&= true; + } else { + iskKeymanModifier &&= false; } } - // remove duplicates - const [unique_returnarray] = returnarray.reduce((acc, curr) => { - const [uniq, set] = acc; - if (!set.has(curr.join(','))) { - set.add(curr.join(',')); - uniq.push(curr); - } - return acc; - }, - [[], new Set()], - ); - return unique_returnarray; - } - - /** - * @brief member function to create an array of [actionID, output, behaviour,keyname,modifier] for a given actionId - * @param data : any - an object containing all data read from a .keylayout file - * @param modi : any - an array of modifiers - * @param search : string - an actionId to be found - * @param outchar : string - the output character - * @param isCAPSused : boolean - flag to indicate if CAPS is used in a keylayout file or not - * @return an array: string[][] containing [actionID,output,actionID, behaviour,keyname,modifier] - */ - public get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput(data: any, modi: any, search: string, outchar: string, isCapsused: boolean): string[][] { - const returnarray2D: string[][] = []; - - if ((search === "") || (search === undefined) || !((isCapsused === true) || (isCapsused === false))) { - return []; - } - - // loop behaviors (in ukelele it is possible to define multiple modifier combinations that behave in the same) - for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { - for (let j = 0; j < KeylayoutToKmnConverter.USED_KEYS_COUNT; j++) { - if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { - for (let k = 0; k < modi[data.keyboard.keyMapSet[0].keyMap[i]['@_index']].length; k++) { - const returnarray: string[] = []; - const behaviour: string = data.keyboard.keyMapSet[0].keyMap[i]['@_index']; - const modifierkmn: string = this.create_kmn_modifier(modi[behaviour][k], isCapsused); - const keyName: string = this.map_UkeleleKC_To_VK(Number(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])); - - returnarray.push(search); - returnarray.push(outchar); - returnarray.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action']); - returnarray.push(behaviour); - returnarray.push(keyName); - returnarray.push(modifierkmn); - - if (returnarray.length > 0) { - returnarray2D.push(returnarray); - } - } - } - } - } - // remove duplicates - const [unique_returnarray] = returnarray2D.reduce((acc, curr) => { - const [uniq, set] = acc; - if (!set.has(curr.join(','))) { - set.add(curr.join(',')); - uniq.push(curr); - } - return acc; - }, - [[], new Set()], - ); - - return unique_returnarray; - } - - /** - * @brief member function to create an array of [keycode,behaviour] for a given actionId - * @param data : any - an object containing all data read from a .keylayout file - * @param search : string - an actionId to be found - * @return an array: number[][] containing [keycode,behaviour] - */ - public get_KeyModifier_array__From__ActionID(data: any, search: string): number[][] { - const mapIndexArray_2D: number[][] = []; - for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { - for (let j = 0; j < KeylayoutToKmnConverter.USED_KEYS_COUNT; j++) { - const mapIndexArrayperKey: number[] = []; - if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { - mapIndexArrayperKey.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']); - mapIndexArrayperKey.push(i); - } - if (mapIndexArrayperKey.length > 0) { - mapIndexArray_2D.push(mapIndexArrayperKey); - } - } - } - return mapIndexArray_2D; - } - - /** - * @brief member function to create an array of modifier behaviours for a given keycode in [keycode,modifier] - * @param data : any - an object containing all data read from a .keylayout file - * @param search : (string | number)[][] - an array[keycode,modifier] to be found - * @return an array: string[] containing modifiers - */ - public get_Modifier_array__From__KeyModifier_array(data: any, search: (string | number)[][]): string[] { - const mapIndexArray_2D: string[] = []; - for (let i = 0; i < search.length; i++) { - mapIndexArray_2D.push(data[search[i][1]]); - } - return mapIndexArray_2D; - } - - /** - * @brief member function to create a kmn modifier from a keylayout modifier - * @param keylayout_modifier :string - modifier used in a .keylayout file - * @param isCAPSused : boolean flag to indicate if CAPS is used in a keylayout file or not - * @return string - a modifier value suitable for use in a .kmn-file - */ - public create_kmn_modifier(keylayout_modifier: string, isCAPSused: boolean): string { - let add_modifier: string = ""; - let kmn_modifier: string = ""; - let kmn_ncaps: string = ""; - - const modifier_state: string[] = keylayout_modifier.split(" "); - - for (let i = 0; i < modifier_state.length; i++) { - - if (isCAPSused && (keylayout_modifier).toUpperCase().indexOf("CAPS") === -1) { - kmn_ncaps = " NCAPS "; - } - - // if we find a modifier containing a '?' e.g. SHIFT? => SHIFT is not necessary. If it is not necessary we don't write this modifier - if (modifier_state[i].toUpperCase().includes('?') && (!modifier_state[i].toUpperCase().includes('CAPS?'))) { - add_modifier = ""; - } - - // if we find caps? => caps is not necessary. If caps is not necessary and isCAPSused we need to write out NCAPS. - else if (isCAPSused && (modifier_state[i].toUpperCase().includes('CAPS?'))) { - add_modifier = "NCAPS "; - } - else if (!isCAPSused && (modifier_state[i].toUpperCase().includes('CAPS?'))) { - add_modifier = ""; - } - else if (modifier_state[i].toUpperCase().includes('CAPS')) { - add_modifier = "CAPS "; - } - else if (isCAPSused && (modifier_state[i].toUpperCase().includes('NCAPS'))) { - add_modifier = "NCAPS "; - } - - else if ((modifier_state[i].toUpperCase() === 'ANYSHIFT') || (modifier_state[i].toUpperCase() === 'SHIFT')) { - add_modifier = "SHIFT "; - } - else if ((modifier_state[i].toUpperCase() === "LEFTSHIFT") || (modifier_state[i].toUpperCase() === "LSHIFT")) { - add_modifier = "SHIFT "; - } - else if ((modifier_state[i].toUpperCase() === "RIGHTSHIFT") || (modifier_state[i].toUpperCase() === "RSHIFT")) { - add_modifier = "SHIFT "; - } - - else if ((modifier_state[i].toUpperCase() === 'ANYCONTROL') || (modifier_state[i].toUpperCase() === 'CONTROL')) { - add_modifier = "CTRL "; - } - else if ((modifier_state[i].toUpperCase() === "LEFTCONTROL") || (modifier_state[i].toUpperCase() === "LCONTROL")) { - add_modifier = "LCTRL "; - } - else if ((modifier_state[i].toUpperCase() === "RIGHTCONTROL") || (modifier_state[i].toUpperCase() === "RCONTROL")) { - add_modifier = "RCTRL "; - } - - else if ((modifier_state[i].toUpperCase() === "LEFTOPTION") || (modifier_state[i].toUpperCase() === "LOPTION")) { - add_modifier = "LALT "; - } - else if ((modifier_state[i].toUpperCase() === "RIGHTOPTION") || (modifier_state[i].toUpperCase() === "ROPTION")) { - add_modifier = "RALT "; - } - else if ((modifier_state[i].toUpperCase() === 'ANYOPTION') || (modifier_state[i].toUpperCase() === 'OPTION')) { - add_modifier = "RALT "; - } - - else { - add_modifier = String(modifier_state[i]) + " "; - } - kmn_modifier += kmn_ncaps + add_modifier; - } - - // remove duplicate and empty entries - const duplicate_modifier_array: string[] = kmn_modifier.split(" ").filter(item => item); - const unique_modifier: string[] = duplicate_modifier_array.filter(function (item, pos, self) { - return self.indexOf(item) === pos; - }); - return unique_modifier.flat().toString().replace(/,/g, " "); - } - - /** - * @brief member function to check if CAPS is used throughout a keylayout file or not - * @param keylayout_modifier the modifier string used in the .keylayout-file - * @return kmn_modifier the modifier string used in the .kmn-file - */ - public checkIfCapsIsUsed(keylayout_modifier: string[][]): boolean { - return JSON.stringify(keylayout_modifier).toUpperCase().includes("CAPS"); - } - - /** - * @brief member function to check if a modifier can be used in keyman - * @param keylayout_modifier the modifier string used in the .keylayout-file - * @return true if the modifier can be used in keyman; false if not - */ - public isAcceptableKeymanModifier(keylayout_modifier: string): boolean { - if (keylayout_modifier === null) - return false; - - let iskKeymanModifier: boolean = true; - const modifier_single: string[] = keylayout_modifier.split(" "); - - for (let i = 0; i < modifier_single.length; i++) { - if ( - (modifier_single[i].toUpperCase() === "NCAPS") - || (modifier_single[i].toUpperCase() === "CAPS") - || (modifier_single[i].toUpperCase() === "SHIFT") - || (modifier_single[i].toUpperCase() === "ALT") - || (modifier_single[i].toUpperCase() === "RALT") - || (modifier_single[i].toUpperCase() === "LALT") - || (modifier_single[i].toUpperCase() === "CTRL") - || (modifier_single[i].toUpperCase() === "LCTRL") - || (modifier_single[i].toUpperCase() === "RCTRL") - || (modifier_single[i].toUpperCase() === "") - ) { - iskKeymanModifier &&= true; - } else { - iskKeymanModifier &&= false; - } - } - return iskKeymanModifier; + return iskKeymanModifier; } /** @@ -995,9 +757,8 @@ export class KeylayoutToKmnConverter { const warningTextArray: string[] = Array(3).fill(""); - // +++++++++++++++++++++++++ check unavailable modifiers ++++++++++++++++++++++++++++++++++++++ + // ------------------------- check unavailable modifiers ------------------------- - // Todo remoce C1-C3's and other markers if ((rule[index].rule_type === "C0") || (rule[index].rule_type === "C1")) { if (!this.isAcceptableKeymanModifier(rule[index].modifier_key)) { warningTextArray[2] = "unavailable modifier : "; @@ -1025,7 +786,7 @@ export class KeylayoutToKmnConverter { } } - // +++++++++++++++++++++++++ check ambiguous/duplicate rules ++++++++++++++++++++++++++++++++++++++ + // ------------------------- check ambiguous/duplicate rules ------------------------- if ((rule[index].rule_type === "C0") || (rule[index].rule_type === "C1")) { @@ -1115,7 +876,6 @@ export class KeylayoutToKmnConverter { } if (rule[index].rule_type === "C2") { - // 2-2: + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(C3) const amb_2_2 = rule.filter((curr, idx) => curr.rule_type === "C2" @@ -1224,6 +984,7 @@ export class KeylayoutToKmnConverter { } if (rule[index].rule_type === "C3") { + // 2-4 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(B11) const amb_2_4 = rule.filter((curr, idx) => ((curr.rule_type === "C2")) @@ -1436,104 +1197,34 @@ export class KeylayoutToKmnConverter { return warningTextArray; } + /** - * @brief member function to map Ukelele keycodes to Windows Keycodes - * @param pos Ukelele (=mac) keycodes - * @return keycode on a Windows Keyboard + * @brief member function to create data for stores that will be printed to the resulting kmn file + * @param data_ukelele an object containing all data read from a .keylayout file + * @return string - all stores to be printed */ - public map_UkeleleKC_To_VK(pos: number): string { + public writeData_Stores(data_ukelele: convert_object): string { - // ukelele KC --> // VK_US - if (pos === 0x0A) return "K_BKQUOTE"; /* ^ */ - else if (pos === 0x12) return "K_1"; /* 1 */ - else if (pos === 0x13) return "K_2"; /* 2 */ - else if (pos === 0x14) return "K_3"; /* 3 */ - else if (pos === 0x15) return "K_4"; /* 4 */ - else if (pos === 0x17) return "K_5"; /* 5 */ - else if (pos === 0x16) return "K_6"; /* 6 */ - else if (pos === 0x1A) return "K_7"; /* 7 */ - else if (pos === 0x1C) return "K_8"; /* 8 */ - else if (pos === 0x19) return "K_9"; /* 9 */ - else if (pos === 0x1D) return "K_0"; /* 0 */ - else if (pos === 0x1B) return "K_HYPHEN"; /* ß */ - else if (pos === 0x18) return "K_EQUAL"; /* ´ */ + let data: string = ""; + data += "c ......................................................................\n"; + data += "c ......................................................................\n"; + data += "c Keyman keyboard generated by kmn-convert\n"; + data += "c from Ukelele file: " + data_ukelele.keylayout_filename + "\n"; + data += "c ......................................................................\n"; + data += "c ......................................................................\n"; + data += "\n"; - else if (pos === 0x0C) return "K_Q"; /* Q */ - else if (pos === 0x0D) return "K_W"; /* W */ - else if (pos === 0x0E) return "K_E"; /* E */ - else if (pos === 0x0F) return "K_R"; /* R */ - else if (pos === 0x11) return "K_T"; /* T */ - else if (pos === 0x10) return "K_Y"; /* Y */ - else if (pos === 0x20) return "K_U"; /* U */ - else if (pos === 0x22) return "K_I"; /* I */ - else if (pos === 0x1F) return "K_O"; /* O */ - else if (pos === 0x23) return "K_P"; /* P */ - else if (pos === 0x21) return "K_LBRKT"; /* [ */ - else if (pos === 0x1E) return "K_RBRKT"; /* ] */ - else if (pos === 0x31) return "K_SPACE"; /* \ */ - else if (pos === 0x2A) return "K_BKSLASH"; /* \ */ // 42 for ISO correct?? - // else if (pos === 0x30) return "K_?C1" /* \ */ // 48 for ANSI correct?? - - else if (pos === 0x00) return "K_A"; /* A */ - else if (pos === 0x01) return "K_S"; /* S */ - else if (pos === 0x02) return "K_D"; /* D */ - else if (pos === 0x03) return "K_F"; /* F */ - else if (pos === 0x05) return "K_G"; /* G */ - else if (pos === 0x04) return "K_H"; /* H */ - else if (pos === 0x26) return "K_J"; /* J */ - else if (pos === 0x28) return "K_K"; /* K */ - else if (pos === 0x25) return "K_L"; /* L */ - else if (pos === 0x29) return "K_COLON"; /* : */ - else if (pos === 0x27) return "K_QUOTE"; /* " */ - - else if (pos === 0x23) return "K_oE2"; /* | */ - else if (pos === 0x06) return "K_Z"; /* Z */ - else if (pos === 0x07) return "K_X"; /* X */ - else if (pos === 0x08) return "K_C"; /* C */ - else if (pos === 0x09) return "K_V"; /* V */ - else if (pos === 0x0B) return "K_B"; /* B */ - else if (pos === 0x2D) return "K_N"; /* N */ - else if (pos === 0x2E) return "K_M"; /* M */ - else if (pos === 0x2B) return "K_COMMA"; /* , */ - else if (pos === 0x2F) return "K_PERIOD"; /* . */ - else if (pos === 0x2C) return "K_SLASH"; /* / */ - - else if (pos === 0x24) return "K_ENTER"; - else return ""; - } - - /** - * @brief member function to return the unicode value - * @param instr the string that will converted - * @return hexadecimal value of a character - */ - public getHexFromString(instr: string): string { - return Number(instr).toString(16).slice(-6).toUpperCase().padStart(4, "0"); - } - - /** - * @brief member function to convert a numeric character reference to a unicode codepoint - * @param instr the value that will converted - * @return a unicode codepoint if instr is a numeric character reference - * instr if instr is not a numeric character reference - */ - public convertToUnicodeCodePoint(instr: string): string { - - if (instr.substring(0, 3) === "&#x") { - const num_length = instr.length - instr.indexOf("x") - 1; - const num_str = instr.substring(instr.indexOf("x") + 1, instr.length - 1); - return ("U+" + num_str.slice(-num_length).padStart(4, "0")); - } + data += "store(&VERSION) \'10.0\'\n"; + data += "store(&TARGETS) \'any\'\n"; + data += "store(&KEYBOARDVERSION) \'1.0\'\n"; + data += "store(©RIGHT) '© 2024 SIL International\'\n"; - // if not hex: convert to hex - if ((instr.substring(0, 2) === "&#")) { - const num_length = instr.length - instr.indexOf("#") - 1; - const num_str = instr.substring(instr.indexOf("#") + 1, instr.length - 1); - return ("U+" + this.getHexFromString(num_str.slice(-num_length)).padStart(4, "0")); - } + data += "\n"; + data += "begin Unicode > use(main)\n\n"; + data += "group(main) using keys\n\n"; - else - return instr; + data += "\n"; + return data; } /** @@ -1547,7 +1238,7 @@ export class KeylayoutToKmnConverter { // filter array of all rules and remove duplicates const unique_data_Rules: rule_object[] = data_ukelele.arrayOf_Rules.filter((curr) => { - return ((curr.output !== new TextEncoder().encode("") || curr.output !== undefined) + return (!(curr.output === new TextEncoder().encode("") || curr.output === undefined) && (curr.key !== "") && ((curr.rule_type === "C0") || (curr.rule_type === "C1") @@ -1564,6 +1255,8 @@ export class KeylayoutToKmnConverter { }) => new TextDecoder().decode(obj.output) === new TextDecoder().decode(o.output) + && obj.output !== new TextEncoder().encode("") + && obj.rule_type === o.rule_type && obj.modifier_key === o.modifier_key && obj.key === o.key @@ -1579,6 +1272,8 @@ export class KeylayoutToKmnConverter { return unique; }, []); + // this.writeDataset(unique_data_Rules); + //................................................ C0 C1 ................................................................ for (let k = 0; k < unique_data_Rules.length; k++) { @@ -1622,7 +1317,7 @@ export class KeylayoutToKmnConverter { // add a warning in front of rules in case unavailable modifiers or ambiguous rules are used - // if warning contains duplicate rules we do not write out this rule + // if warning contains duplicate rules we do not write out the whole rule // (even if there are other warnings for the same rule) since that rule had been written before if ((warn_text[2].indexOf("duplicate") < 0)) { data += warn_text[2] @@ -1655,7 +1350,7 @@ export class KeylayoutToKmnConverter { } // add a warning in front of rules in case unavailable modifiers or ambiguous rules are used - // if warning contains duplicate rules we do not write out this rule + // if warning contains duplicate rules we do not write out the whole rule // (even if there are other warnings for the same rule) since that rule had been written before if ((warn_text[1].indexOf("duplicate") < 0)) { data += warn_text[1] @@ -1700,7 +1395,7 @@ export class KeylayoutToKmnConverter { } // add a warning in front of rules in case unavailable modifiers or ambiguous rules are used - // if warning contains duplicate rules we do not write out this rule + // if warning contains duplicate rules we do not write out the whole rule // (even if there are other warnings for the same rule) since that rule had been written before if ((warn_text[0].indexOf("duplicate") < 0) ) { @@ -1746,34 +1441,441 @@ export class KeylayoutToKmnConverter { } /** - * @brief member function to create data for stores that will be printed to the resulting kmn file - * @param data_ukelele an object containing all data read from a .keylayout file - * @return string - all stores to be printed + * @brief member function to map Ukelele keycodes to Windows Keycodes + * @param pos Ukelele (=mac) keycodes + * @return keycode on a Windows Keyboard */ - public writeData_Stores(data_ukelele: convert_object): string { + public map_UkeleleKC_To_VK(pos: number): string { - let data: string = ""; - data += "c ......................................................................\n"; - data += "c ......................................................................\n"; - data += "c Keyman keyboard generated by kmn-convert\n"; - data += "c from Ukelele file: " + data_ukelele.keylayout_filename + "\n"; - data += "c ......................................................................\n"; - data += "c ......................................................................\n"; - data += "\n"; + // ukelele KC --> VK_US + if (pos === 0x0A) return "K_BKQUOTE"; /* ^ */ + else if (pos === 0x12) return "K_1"; /* 1 */ + else if (pos === 0x13) return "K_2"; /* 2 */ + else if (pos === 0x14) return "K_3"; /* 3 */ + else if (pos === 0x15) return "K_4"; /* 4 */ + else if (pos === 0x17) return "K_5"; /* 5 */ + else if (pos === 0x16) return "K_6"; /* 6 */ + else if (pos === 0x1A) return "K_7"; /* 7 */ + else if (pos === 0x1C) return "K_8"; /* 8 */ + else if (pos === 0x19) return "K_9"; /* 9 */ + else if (pos === 0x1D) return "K_0"; /* 0 */ + else if (pos === 0x1B) return "K_HYPHEN"; /* ß */ + else if (pos === 0x18) return "K_EQUAL"; /* ´ */ - data += "store(&VERSION) \'10.0\'\n"; - data += "store(&TARGETS) \'any\'\n"; - data += "store(&KEYBOARDVERSION) \'1.0\'\n"; - data += "store(©RIGHT) '© 2024 SIL International\'\n"; + else if (pos === 0x0C) return "K_Q"; /* Q */ + else if (pos === 0x0D) return "K_W"; /* W */ + else if (pos === 0x0E) return "K_E"; /* E */ + else if (pos === 0x0F) return "K_R"; /* R */ + else if (pos === 0x11) return "K_T"; /* T */ + else if (pos === 0x10) return "K_Y"; /* Y */ + else if (pos === 0x20) return "K_U"; /* U */ + else if (pos === 0x22) return "K_I"; /* I */ + else if (pos === 0x1F) return "K_O"; /* O */ + else if (pos === 0x23) return "K_P"; /* P */ + else if (pos === 0x21) return "K_LBRKT"; /* [ */ + else if (pos === 0x1E) return "K_RBRKT"; /* ] */ + else if (pos === 0x31) return "K_SPACE"; /* \ */ + else if (pos === 0x2A) return "K_BKSLASH"; /* \ */ // 42 for ISO correct?? + // else if (pos === 0x30) return "K_?C1" /* \ */ // 48 for ANSI correct?? - data += "\n"; - data += "begin Unicode > use(main)\n\n"; - data += "group(main) using keys\n\n"; + else if (pos === 0x00) return "K_A"; /* A */ + else if (pos === 0x01) return "K_S"; /* S */ + else if (pos === 0x02) return "K_D"; /* D */ + else if (pos === 0x03) return "K_F"; /* F */ + else if (pos === 0x05) return "K_G"; /* G */ + else if (pos === 0x04) return "K_H"; /* H */ + else if (pos === 0x26) return "K_J"; /* J */ + else if (pos === 0x28) return "K_K"; /* K */ + else if (pos === 0x25) return "K_L"; /* L */ + else if (pos === 0x29) return "K_COLON"; /* : */ + else if (pos === 0x27) return "K_QUOTE"; /* " */ - data += "\n"; - return data; + else if (pos === 0x23) return "K_oE2"; /* | */ + else if (pos === 0x06) return "K_Z"; /* Z */ + else if (pos === 0x07) return "K_X"; /* X */ + else if (pos === 0x08) return "K_C"; /* C */ + else if (pos === 0x09) return "K_V"; /* V */ + else if (pos === 0x0B) return "K_B"; /* B */ + else if (pos === 0x2D) return "K_N"; /* N */ + else if (pos === 0x2E) return "K_M"; /* M */ + else if (pos === 0x2B) return "K_COMMA"; /* , */ + else if (pos === 0x2F) return "K_PERIOD"; /* . */ + else if (pos === 0x2C) return "K_SLASH"; /* / */ + + else if (pos === 0x24) return "K_ENTER"; + else return ""; + } + + /** + * @brief member function to return the unicode value + * @param instr the string that will converted + * @return hexadecimal value of a character + */ + public getHexFromString(instr: string): string { + return Number(instr).toString(16).slice(-6).toUpperCase().padStart(4, "0"); + } + + /** + * @brief member function to convert a numeric character reference to a unicode codepoint + * @param instr the value that will converted + * @return a unicode codepoint if instr is a numeric character reference + * instr if instr is not a numeric character reference + */ + public convertToUnicodeCodePoint(instr: string): string { + + if (instr.substring(0, 3) === "&#x") { + const num_length = instr.length - instr.indexOf("x") - 1; + const num_str = instr.substring(instr.indexOf("x") + 1, instr.length - 1); + return ("U+" + num_str.slice(-num_length).padStart(4, "0")); + } + + // if not hex: convert to hex + if ((instr.substring(0, 2) === "&#")) { + const num_length = instr.length - instr.indexOf("#") - 1; + const num_str = instr.substring(instr.indexOf("#") + 1, instr.length - 1); + return ("U+" + this.getHexFromString(num_str.slice(-num_length)).padStart(4, "0")); + } + + else + return instr; + } + + /** + * @brief member function to return an index for a given actionID + * @param data :any - an object containing all data read from a .keylayout file + * @param search :string - value 'id' to be found + * @return a number specifying the index of an actionId + */ + public get_ActionIndex__From__ActionId(data: any, search: string): number { + for (let i = 0; i < data.keyboard.actions.action.length; i++) { + if (data.keyboard.actions.action[i]['@_id'] === search) { + return i; + } + } + return 0; + } + + /** + * @brief member function to find the actionID of a certain state-next pair + * @param data :any an object containing all data read from a .keylayout file + * @param search :string value 'next' to be found + * @return a string containing the actionId of a certain state-next pair + */ + public get_ActionID__From__ActionNext(data: any, search: string): string { + if (search !== "none") { + for (let i = 0; i < data.keyboard.actions.action.length; i++) { + for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { + if (data.keyboard.actions.action[i].when[j]['@_next'] === search) { + return data.keyboard.actions.action[i]['@_id']; + } + } + } + } + return ""; + } + + /** + * @brief member function to create an array of modifier behaviours for a given keycode in [keycode,modifier] + * @param data : any - an object containing all data read from a .keylayout file + * @param search : (string | number)[][] - an array[keycode,modifier] to be found + * @return an array: string[] containing modifiers + */ + public get_Modifier_array__From__KeyModifier_array(data: any, search: (string | number)[][]): string[] { + const mapIndexArray_2D: string[] = []; + for (let i = 0; i < search.length; i++) { + mapIndexArray_2D.push(data[search[i][1]]); + } + return mapIndexArray_2D; + } + + /** + * @brief member function to find the output for a certain actionID for state 'none' + * @param data :any an object containing all data read from a .keylayout file + * @param search :string an actionId to be found + * @return a string containing the output character + */ + public get_Output__From__ActionId_None(data: any, search: string): string { + let OutputValue: string = ""; + + for (let i = 0; i < data.keyboard.actions.action.length; i++) { + if (data.keyboard.actions.action[i]['@_id'] === search) { + for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { + if (data.keyboard.actions.action[i].when[j]['@_state'] === "none") { + OutputValue = data.keyboard.actions.action[i].when[j]['@_output']; + } + } + } + } + return OutputValue; + } + + /** + * @brief member function to return array of [Keycode,Keyname,actionId,actionIDIndex, output] for a given actionID in of [ actionID,state,output] + * @param data :any - an object containing all data read from a .keylayout file + * @param search :string[][] - array of [ actionID,state,output] + * @return a string[][] containing [Keycode,Keyname,actionId,actionIDIndex, output] + */ + public get_KeyActionOutput_array__From__ActionStateOutput_array(data: any, search: string[][]): string[][] { + + if ((search === undefined) || (search === null)) + return []; + + const returnarray2D: string[][] = []; + for (let k = 0; k < search.length; k++) { + for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { + for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { + const returnarray: string[] = []; + if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search[k][0] && + data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'] < KeylayoutToKmnConverter.USED_KEYS_COUNT) { + returnarray.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']); + returnarray.push(this.map_UkeleleKC_To_VK(Number(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']))); + returnarray.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action']); + returnarray.push(data.keyboard.keyMapSet[0].keyMap[i]['@_index']); + returnarray.push(search[k][2]); + } + if (returnarray.length > 0) { + returnarray2D.push(returnarray); + } + } + } + } + return returnarray2D; + } + + /** + * @brief member function to get an array of all actionId-output pairs for a certain state + * @param data : any an object containing all data read from a .keylayout file + * @param search : string a 'state' to be found + * @return an array: string[][] containing all [actionId, state, output] for a certain state + */ + public get_ActionStateOutput_array__From__ActionState(data: any, search: string): string[][] { + const returnarray2D: string[][] = []; + + for (let i = 0; i < data.keyboard.actions.action.length; i++) { + for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { + const returnarray: string[] = []; + if ((data.keyboard.actions.action[i].when[j]['@_state'] === search)) { + returnarray.push(data.keyboard.actions.action[i]['@_id']); + returnarray.push(data.keyboard.actions.action[i].when[j]['@_state']); + returnarray.push(data.keyboard.actions.action[i].when[j]['@_output']); + } + if (returnarray.length > 0) { + returnarray2D.push(returnarray); + } + } + } + return returnarray2D; } + /** + * @brief member function to create an 2D array of [KeyName,actionId,behaviour,modifier,output] + * @param data : any an object containing all data read from a .keylayout file + * @param search : array of [keycode,keyname,actionId,behaviour,output] to be found + * @param isCAPSused : boolean flag to indicate if CAPS is used in a keylayout file or not + * @return an array: string[][] containing [KeyName,actionId,behaviour,modifier,output] + */ + public get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(data: any, search: (boolean | string)[][], isCAPSused: boolean): string[][] { + const returnarray: string[][] = []; + + if (!((search === undefined) || (search === null) || (search.length === 0))) { + for (let i = 0; i < search.length; i++) { + const behaviour: number = Number(search[i][3]); + + for (let j = 0; j < data.keyboard.modifierMap.keyMapSelect[behaviour].modifier.length; j++) { + const returnarray1D: string[] = []; + // KeyName + returnarray1D.push(String(search[i][1])); + // actionId + returnarray1D.push(String(search[i][2])); + // behaviour + returnarray1D.push(String(search[i][3])); + // modifier + returnarray1D.push(String(this.create_kmn_modifier(data.keyboard.modifierMap.keyMapSelect[behaviour].modifier[j]['@_keys'], isCAPSused))); + // output + returnarray1D.push(String(search[i][4])); + + if (returnarray1D.length > 0) { + returnarray.push(returnarray1D); + } + } + } + } + // remove duplicates + const [unique_returnarray] = returnarray.reduce((acc, curr) => { + const [uniq, set] = acc; + if (!set.has(curr.join(','))) { + set.add(curr.join(',')); + uniq.push(curr); + } + return acc; + }, + [[], new Set()], + ); + return unique_returnarray; + } + + /** + * @brief member function to create an array of [actionID, output, behaviour,keyname,modifier] for a given actionId + * @param data : any - an object containing all data read from a .keylayout file + * @param modi : any - an array of modifiers + * @param search : string - an actionId to be found + * @param outchar : string - the output character + * @param isCAPSused : boolean - flag to indicate if CAPS is used in a keylayout file or not + * @return an array: string[][] containing [actionID,output,actionID, behaviour,keyname,modifier] + */ + public get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput(data: any, modi: any, search: string, outchar: string, isCapsused: boolean): string[][] { + const returnarray2D: string[][] = []; + + if ((search === "") || (search === undefined) || !((isCapsused === true) || (isCapsused === false))) { + return []; + } + + // loop behaviors (in ukelele it is possible to define multiple modifier combinations that behave in the same) + for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { + for (let j = 0; j < KeylayoutToKmnConverter.USED_KEYS_COUNT; j++) { + if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { + for (let k = 0; k < modi[data.keyboard.keyMapSet[0].keyMap[i]['@_index']].length; k++) { + const returnarray: string[] = []; + const behaviour: string = data.keyboard.keyMapSet[0].keyMap[i]['@_index']; + const modifierkmn: string = this.create_kmn_modifier(modi[behaviour][k], isCapsused); + const keyName: string = this.map_UkeleleKC_To_VK(Number(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])); + + returnarray.push(search); + returnarray.push(outchar); + returnarray.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action']); + returnarray.push(behaviour); + returnarray.push(keyName); + returnarray.push(modifierkmn); + + if (returnarray.length > 0) { + returnarray2D.push(returnarray); + } + } + } + } + } + // remove duplicates + const [unique_returnarray] = returnarray2D.reduce((acc, curr) => { + const [uniq, set] = acc; + if (!set.has(curr.join(','))) { + set.add(curr.join(',')); + uniq.push(curr); + } + return acc; + }, + [[], new Set()], + ); + + return unique_returnarray; + } + + /** + * @brief member function to create an array of [keycode,behaviour] for a given actionId + * @param data : any - an object containing all data read from a .keylayout file + * @param search : string - an actionId to be found + * @return an array: number[][] containing [keycode,behaviour] + */ + public get_KeyModifier_array__From__ActionID(data: any, search: string): number[][] { + const mapIndexArray_2D: number[][] = []; + for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { + for (let j = 0; j < KeylayoutToKmnConverter.USED_KEYS_COUNT; j++) { + const mapIndexArrayperKey: number[] = []; + if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { + mapIndexArrayperKey.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']); + mapIndexArrayperKey.push(i); + } + if (mapIndexArrayperKey.length > 0) { + mapIndexArray_2D.push(mapIndexArrayperKey); + } + } + } + return mapIndexArray_2D; + } + + // console log all entries C3 TODO remove + public writeDataset(dataRules: rule_object[]) { + for (let i = 0; i < dataRules.length; i++) { + //if (dataRules[i].key === "") { + if ((i > 2934) && (i < 2939)) { + // if (true ) { + + + console.log("dataRules[i].outp ", "..", dataRules[i].output, "..", dataRules[i].output === new TextEncoder().encode("")); + + console.log("dataRules ", i, + + dataRules[i].rule_type !== "" ? dataRules[i].rule_type : "--".padEnd(4, " "), + + "| ", (dataRules[i].modifier_prev_deadkey !== "" ? dataRules[i].modifier_prev_deadkey.padEnd(33, " ") : "--".padEnd(33, " ")), + (dataRules[i].prev_deadkey !== "" ? dataRules[i].prev_deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), + (dataRules[i].id_prev_deadkey !== 0 ? ("dk(A" + String(dataRules[i].id_prev_deadkey) + ")").padEnd(11, " ") : "--".padEnd(11, " ")), + (dataRules[i].unique_prev_deadkey !== 0 ? ("unique(A" + String(dataRules[i].unique_prev_deadkey) + ")").padEnd(11, " ") : "--".padEnd(11, " ")), + + (dataRules[i].modifier_deadkey !== "" ? dataRules[i].modifier_deadkey.padEnd(30, " ") : "--".padEnd(30, " ")), + (dataRules[i].deadkey !== "" ? dataRules[i].deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), + dataRules[i].rule_type === "C2" ? (dataRules[i].unique_deadkey !== 0 ? ("unique(C" + String(dataRules[i].unique_deadkey) + ")").padEnd(9, " ") : "--".padEnd(9, " ")) : ((dataRules[i].unique_prev_deadkey !== 0 ? ("unique(B" + dataRules[i].id_deadkey + ")").padEnd(9, " ") : "--".padEnd(9, " "))), + + dataRules[i].id_prev_deadkey, + dataRules[i].id_deadkey, + + "| ", (dataRules[i].modifier_key !== "" ? dataRules[i].modifier_key.padEnd(40, " ") : "--".padEnd(40, " ")), + (dataRules[i].key !== "" ? dataRules[i].key.padEnd(8, " ") : "--".padEnd(8, " ")), + (new TextDecoder().decode(dataRules[i].output) !== "" ? new TextDecoder().decode(dataRules[i].output).padEnd(10, " ") : ("--" + dataRules[i].output) + "--"), + + "| °°"); + } + } + + } + // TODO remove + public writeDatasetSingle(dataRules: rule_object) { + + console.log("dataRules[i].key ", "..", dataRules.key, "..", dataRules.key === ""); + + console.log("dataRules ", + dataRules.rule_type !== "" ? dataRules.rule_type : "--".padEnd(4, " "), + + "| ", (dataRules.modifier_prev_deadkey !== "" ? dataRules.modifier_prev_deadkey.padEnd(33, " ") : "--".padEnd(33, " ")), + (dataRules.prev_deadkey !== "" ? dataRules.prev_deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), + (dataRules.id_prev_deadkey !== 0 ? ("dk(A" + String(dataRules.id_prev_deadkey) + ")").padEnd(11, " ") : "--".padEnd(11, " ")), + (dataRules.unique_prev_deadkey !== 0 ? ("unique(A" + String(dataRules.unique_prev_deadkey) + ")").padEnd(11, " ") : "--".padEnd(11, " ")), + + (dataRules.modifier_deadkey !== "" ? dataRules.modifier_deadkey.padEnd(30, " ") : "--".padEnd(30, " ")), + (dataRules.deadkey !== "" ? dataRules.deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), + dataRules.rule_type === "C2" ? (dataRules.unique_deadkey !== 0 ? ("unique(C" + String(dataRules.unique_deadkey) + ")").padEnd(9, " ") : "--".padEnd(9, " ")) : ((dataRules.unique_prev_deadkey !== 0 ? ("unique(B" + dataRules.id_deadkey + ")").padEnd(9, " ") : "--".padEnd(9, " "))), + + dataRules.id_prev_deadkey, + dataRules.id_deadkey, + + "| ", (dataRules.modifier_key !== "" ? dataRules.modifier_key.padEnd(40, " ") : "--".padEnd(40, " ")), + (dataRules.key !== "" ? dataRules.key.padEnd(8, " ") : "--".padEnd(8, " ")), + (new TextDecoder().decode(dataRules.output) !== "" ? new TextDecoder().decode(dataRules.output).padEnd(10, " ") : ("--" + dataRules.output) + "--"), + + "| °°"); + + } + + + + + public Translate_Allmodifiers(data: convert_object) { + //let i=0; i< data. + console.log("HuRRA ",); + console.log(" ", data.arrayOf_Modifiers); + + const modi_flat = data.arrayOf_Modifiers.flat(); + console.log("modi_flat ", modi_flat); + const cps: boolean = this.checkIfCapsIsUsed(data.arrayOf_Modifiers); + + for (let i = 0; i < modi_flat.length; i++) { + + console.log(" ", this.create_kmn_modifier(modi_flat[i], cps)); + } + + + //const modi= data.arrayOf_Modifiers + + } } /** diff --git a/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts index 63a97cd1d97..1fbb88b9c2a 100644 --- a/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts @@ -16,21 +16,60 @@ describe('KeylayoutToKmnConverter', function () { compilerTestCallbacks.clear(); }); - const inputFilename = makePathToFixture('../data/Italian_copy.keylayout'); // OKOK - //const inputFilename = makePathToFixture('../data/German_complete.keylayout'); // OK NO NCAPS SHIFT <-> SHIFT NCAPS - //const inputFilename = makePathToFixture('../data/German_Standard_copy.keylayout'); // OK NO NCAPS SHIFT <-> SHIFT NCAPS - //const inputFilename = makePathToFixture('../data/Spanish_copy.keylayout'); // OKOK - //const inputFilename = makePathToFixture('../data/Latin_American_copy.keylayout'); // OKOK - //const inputFilename = makePathToFixture('../data/Swiss_French_copy.keylayout'); // OKOK - //const inputFilename = makePathToFixture('../data/Swiss_German_copy.keylayout'); // OKOK - //const inputFilename = makePathToFixture('../data/US_copy.keylayout'); // OKOK - //const inputFilename = makePathToFixture('../data/Polish_copy.keylayout'); // OKOK + + describe('RunOneFile ', function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const inputFilename = makePathToFixture('../data/XX.keylayout'); + console.log(" inputFilename: ", inputFilename); + + const outputFilename = "data//" + inputFilename.substring(0, inputFilename.lastIndexOf(".")) + ".kmn"; + sut.run(inputFilename, outputFilename); + assert.isTrue(true); + ; + }); + + describe('RunAllFiles ', function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + [ + [makePathToFixture('../data/Italian.keylayout')], + [makePathToFixture('../data/Italian_command.keylayout')], + [makePathToFixture('../data/Swiss_French.keylayout')], + [makePathToFixture('../data/Spanish.keylayout')], + [makePathToFixture('../data/Swiss_German.keylayout')], + [makePathToFixture('../data/US.keylayout')], + [makePathToFixture('../data/Polish.keylayout')], + [makePathToFixture('../data/French.keylayout')], + [makePathToFixture('../data/Latin_American.keylayout')], + [makePathToFixture('../data/German_complete.keylayout')], + [makePathToFixture('../data/German_Standard.keylayout')], + ].forEach(function (files_) { + console.log(" inputFilename: ", files_[0]); + + const outputFilename = "data//" + files_[0].substring(0, files_[0].lastIndexOf(".")) + ".kmn"; + sut.run(files_[0], outputFilename); + assert.isTrue(true); + }); + }); + + + //const inputFilename = makePathToFixture('../data/Italian.keylayout'); // OKOK + //const inputFilename = makePathToFixture('../data/Spanish.keylayout'); // OKOK + // no const inputFilename = makePathToFixture('../data/German_complete.keylayout'); // OK NO NCAPS SHIFT <-> SHIFT NCAPS + // no const inputFilename = makePathToFixture('../data/German_Standard.keylayout'); // OK NO NCAPS SHIFT <-> SHIFT NCAPS + // no const inputFilename = makePathToFixture('../data/Latin_American.keylayout'); // OKOK + //const inputFilename = makePathToFixture('../data/Swiss_French.keylayout'); // OKOK + //const inputFilename = makePathToFixture('../data/Swiss_German.keylayout'); // OKOK + //const inputFilename = makePathToFixture('../data/US.keylayout'); // OKOK + //const inputFilename = makePathToFixture('../data/Polish.keylayout'); // OKOK + //const inputFilename = makePathToFixture('../data/French.keylayout'); // OKOK + + describe("run() ", function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - it('run() should throw on null inputs', async function () { + it('run() should throw on null input file name and null output file name', async function () { // note, could use 'chai as promised' library to make this more fluent: let threw = false; try { @@ -41,790 +80,850 @@ describe('KeylayoutToKmnConverter', function () { assert.isTrue(threw); }); - it('run() should throw on wrong output file', async function () { + it('run() should throw on null input file name and empty output file name', async function () { let threw = false; try { - await sut.run(null, "X"); + await sut.run(null, ""); } catch { threw = true; } assert.isTrue(threw); }); - it('run() should throw on wrong intput file', async function () { + it('run() should throw on null input file name', async function () { let threw = false; try { - await sut.run("X", null); + await sut.run(null, "X"); } catch { threw = true; } assert.isTrue(threw); }); - - it('run() should return true if ran OK', async function () { - - // TODO use path also - // const outputFilename = "data//" +inputFilename.substring(0, inputFilename.lastIndexOf(".")) + ".kmn" - const outputFilename = makePathToFixture('../data/MyResult.kmn'); - + it('run() should return on unavailable input file name and null output file name', async function () { + const inputFilename = makePathToFixture('../data/Unavailable.keylayout'); let threw = false; try { - await sut.run(inputFilename, outputFilename); + await sut.run(inputFilename, null); } catch { threw = true; } - assert.isTrue(!threw); - }); - }); - - describe("read() ", function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const inputFilename_unavailable = makePathToFixture('X.keylayout'); - - it('read() should return filled array on correct input', async function () { - const result = sut.read(inputFilename); - assert.isNotEmpty(result); - }); - - it('read() should return empty array on null input', async function () { - const result = sut.read(null); - assert.isEmpty(result); - }); - - it('read() should return empty array on empty input', async function () { - const result = sut.read(""); - assert.isEmpty(result); - }); - - it('read() should return empty array on space as input', async function () { - const result = sut.read(" "); - assert.isEmpty(result); + assert.isFalse(threw); }); - it('read() should return empty array on unavailable file name', async function () { - const result = sut.read(inputFilename_unavailable); - assert.isEmpty(result); - }); - - it('read() should return empty array on typo in path', async function () { - const result = sut.read('../data|Italian_copy.keylayout'); - assert.isEmpty(result); - }); - }); - - describe("write() ", function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const read = sut.read(inputFilename); - const converted = sut.convert(read); - - // empty convert_object from unavailable file name - const inputFilename_unavailable = makePathToFixture('X.keylayout'); - const read_unavailable = sut.read(inputFilename_unavailable); - const converted_unavailable = sut.convert(read_unavailable); - - it('write() should return true (no error) if no inputfile', async function () { - const result = sut.write(converted_unavailable); - assert.isTrue(result); - }); - - it('write() should return true (no error) if written', async function () { - const result = sut.write(converted); - assert.isTrue(result); - }); - }); - - describe("convert() ", function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const read = sut.read(inputFilename); - const converted = sut.convert(read); - - // empty convert_object from unavailable file name - const inputFilename_unavailable = makePathToFixture('X.keylayout'); - const read_unavailable = sut.read(inputFilename_unavailable); - const converted_unavailable = sut.convert(read_unavailable); + it('run() should return on correct input file name and empty output file name ', async function () { + console.log(" ------------------",); - // empty convert_object from empty filename - const inputFilename_empty = makePathToFixture(''); - const read_empty = sut.read(inputFilename_empty); - const converted_empty = sut.convert(read_empty); - - it('should return converted array on correct input', async function () { - // we use 'converted' from above - assert.isTrue(converted.arrayOf_Rules.length !== 0); - }); - - it('should return empty on empty input', async function () { - // we use 'converted_empty' from above - assert.isTrue((converted_empty.keylayout_filename === '' - && converted_empty.arrayOf_Modifiers.length === 0 - && converted_empty.arrayOf_Rules.length === 0)); + const inputFilename = makePathToFixture('../data/Italian_command.keylayout'); + let threw = false; + try { + await sut.run(inputFilename, ""); + } catch { + threw = true; + } + assert.isFalse(threw); }); - it('should return empty on only name as input', async function () { - // we use 'converted_unavailable' from above - assert.isTrue((converted_unavailable.keylayout_filename === '' - && converted_unavailable.arrayOf_Modifiers.length === 0 - && converted_unavailable.arrayOf_Rules.length === 0)); + it('run() should return on correct input file name and null output file name', async function () { + console.log(" ------------------",); + const inputFilename = makePathToFixture('../data/Italian_command.keylayout'); + let threw = false; + try { + await sut.run(inputFilename, null); + } catch { + threw = true; + } + assert.isFalse(threw); }); - it('should return empty on only modifiers as input', async function () { - const converted_mod = sut.convert({ - keylayout_filename: '', - arrayOf_Modifiers: [['caps'], ['Shift'], ['command']], - arrayOf_Rules: [] - }); - assert.isTrue((converted_mod.keylayout_filename === '' - && converted_mod.arrayOf_Modifiers.length === 0 - && converted_mod.arrayOf_Rules.length === 0)); + it('run() should return on correct input file name and given output file name ', async function () { + console.log(" ------------------",); + const inputFilename = makePathToFixture('../data/Italian_command.keylayout'); + const outputFilename = makePathToFixture('../../data/OutputName.kmn'); + let threw = false; + try { + await sut.run(inputFilename, outputFilename); + } catch { + threw = true; + } + assert.isFalse(threw); }); - it('should return empty on only rules as input', async function () { - const converted_rule = sut.convert({ - keylayout_filename: '', - arrayOf_Modifiers: [], - arrayOf_Rules: [["C0", "", "", 0, 0, "", "", 0, 0, "CAPS", "K_A", "A"]] - }); - assert.isTrue((converted_rule.keylayout_filename === '' - && converted_rule.arrayOf_Modifiers.length === 0 - && converted_rule.arrayOf_Rules.length === 0)); + it('run() throw on incorrect input file extention ', async function () { + console.log(" ------------------",); + const inputFilename = makePathToFixture('../data/Italian_command.A'); + const outputFilename = makePathToFixture('../../data/OutputName.B'); + let threw = false; + try { + await sut.run(inputFilename, outputFilename); + } catch { + threw = true; + } + assert.isFalse(threw); }); + }); - - describe('create_kmn_modifier ', function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - - [ - ['anycontrol', true, 'NCAPS CTRL'], - ['shift?', true, 'NCAPS'], - ['?', true, 'NCAPS'], - ['?', false, ''], - ['caps', true, 'CAPS'], - ['', true, 'NCAPS'], - [' ', false, ''], - ['wrongModifierName', false, 'wrongModifierName'], - ['shift', false, 'SHIFT'], - ['shift command', true, 'NCAPS SHIFT command'], - ['rshift', true, 'NCAPS SHIFT'], - ['rshift', false, 'SHIFT'], - ['rightshift', true, 'NCAPS SHIFT'], - ['riGhtsHift', true, 'NCAPS SHIFT'], - ['LEFTCONTROL', true, 'NCAPS LCTRL'], - ['RCONTROL', true, 'NCAPS RCTRL'], - ['leftoption', true, 'NCAPS LALT'], - ['loption', true, 'NCAPS LALT'], - ].forEach(function (values) { - it(('should convert "' + values[0] + '"').padEnd(36, " ") + 'to "' + values[2] + '"', async function () { - const result = sut.create_kmn_modifier(values[0] as string, values[1] as boolean); - assert.equal(result, values[2]); + + describe("read() ", function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const inputFilename_unavailable = makePathToFixture('X.keylayout'); + + it('read() should return filled array on correct input', async function () { + const inputFilename = makePathToFixture('../data/Italian.keylayout'); + const result = sut.read(inputFilename); + assert.isNotEmpty(result); + }); + + it('read() should return empty array on null input', async function () { + const result = sut.read(null); + assert.isEmpty(result); + }); + + it('read() should return empty array on empty input', async function () { + const result = sut.read(""); + assert.isEmpty(result); + }); + + it('read() should return empty array on space as input', async function () { + const result = sut.read(" "); + assert.isEmpty(result); + }); + + it('read() should return empty array on unavailable file name', async function () { + const result = sut.read(inputFilename_unavailable); + assert.isEmpty(result); + }); + + it('read() should return empty array on typo in path', async function () { + const result = sut.read('../data|Italian.keylayout'); + assert.isEmpty(result); }); }); - }); - - describe('getHexFromString ', function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - - [ - ['0009', '0009'], - ['000027', '001B'], - ['00027', '001B'], - ['0027', '001B'], - ['027', '001B'], - ['27', '001B'], - ['001C', '0NAN'], - ['0000', '0000'], - ['X', '0NAN'], - ['', '0000'], - [' ', '0000'], - [123, '007B'], - [null, '0000'], - ].forEach(function (values) { - it(('should convert "' + values[0] + '"').padEnd(25, " ") + 'to "' + values[1] + '"', async function () { - const result = sut.getHexFromString(values[0] as string); - assert.equal(result, values[1]); + + describe("write() ", function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const inputFilename = makePathToFixture('../data/Italian.keylayout'); + const read = sut.read(inputFilename); + const converted = sut.convert(read); + + // empty convert_object from unavailable file name + const inputFilename_unavailable = makePathToFixture('X.keylayout'); + const read_unavailable = sut.read(inputFilename_unavailable); + const converted_unavailable = sut.convert(read_unavailable); + + it('write() should return true (no error) if no inputfile', async function () { + const result = sut.write(converted_unavailable); + assert.isTrue(result); + }); + + it('write() should return true (no error) if written', async function () { + const result = sut.write(converted); + assert.isTrue(result); }); }); - }); - - describe('convertToUnicodeCodePoint ', function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - - [ - ["􏘁", 'U+10F601'], - ["😁", 'U+1F601'], - [" ", 'U+0009'], - ["™", 'U+0099'], - ["ঙ", 'U+0999'], - ["香", 'U+9999'], - ["򙦙", 'U+99999'], - ["􏘁", 'U+10F601'], - ["😁", 'U+1F601'], - [" ", 'U+0009'], - ["c", 'U+0063'], - ["ϧ", 'U+03E7'], - ["✏", 'U+270F'], - ["𘚟", 'U+1869F'], - ['0000;', '0000;'], - ['X;', 'X;'], - ['123;', '123;'], - [';', ';'], - [' ;', ' ;'] - ].forEach(function (values) { - it(('should convert "' + values[0] + '"').padEnd(25, " ") + 'to "' + values[1] + '"', async function () { - const result = sut.convertToUnicodeCodePoint(values[0] as string); - assert.equal(result, values[1]); + + describe("convert() ", function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const inputFilename = makePathToFixture('../data/Italian.keylayout'); + const read = sut.read(inputFilename); + const converted = sut.convert(read); + + // empty convert_object from unavailable file name + const inputFilename_unavailable = makePathToFixture('X.keylayout'); + const read_unavailable = sut.read(inputFilename_unavailable); + const converted_unavailable = sut.convert(read_unavailable); + + // empty convert_object from empty filename + const inputFilename_empty = makePathToFixture(''); + const read_empty = sut.read(inputFilename_empty); + const converted_empty = sut.convert(read_empty); + + it('should return converted array on correct input', async function () { + // we use 'converted' from above + assert.isTrue(converted.arrayOf_Rules.length !== 0); + }); + + it('should return empty on empty input', async function () { + // we use 'converted_empty' from above + assert.isTrue((converted_empty.keylayout_filename === '' + && converted_empty.arrayOf_Modifiers.length === 0 + && converted_empty.arrayOf_Rules.length === 0)); + }); + + it('should return empty on only name as input', async function () { + // we use 'converted_unavailable' from above + assert.isTrue((converted_unavailable.keylayout_filename === '' + && converted_unavailable.arrayOf_Modifiers.length === 0 + && converted_unavailable.arrayOf_Rules.length === 0)); + }); + + it('should return empty on only modifiers as input', async function () { + const converted_mod = sut.convert({ + keylayout_filename: '', + arrayOf_Modifiers: [['caps'], ['Shift'], ['command']], + arrayOf_Rules: [] + }); + assert.isTrue((converted_mod.keylayout_filename === '' + && converted_mod.arrayOf_Modifiers.length === 0 + && converted_mod.arrayOf_Rules.length === 0)); + }); + + it('should return empty on only rules as input', async function () { + const converted_rule = sut.convert({ + keylayout_filename: '', + arrayOf_Modifiers: [], + arrayOf_Rules: [["C0", "", "", 0, 0, "", "", 0, 0, "CAPS", "K_A", "A"]] + }); + assert.isTrue((converted_rule.keylayout_filename === '' + && converted_rule.arrayOf_Modifiers.length === 0 + && converted_rule.arrayOf_Rules.length === 0)); }); }); - }); - - describe("isAcceptableKeymanModifier ", function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - - [ - ["NCAPS", true], - ["NxCAPS", false], - ["SHIFT", true], - ["ALT", true], - ["RALT", true], - ["LALT", true], - ["CTRL", true], - ["LCTRL", true], - ["RCTRL", true], - ["LCTRL CAPS", true], - ["LCTRL X", false], - ["", true], - [null, false], - ].forEach(function (values) { - it(("isAcceptableKeymanModifier(" + values[0] + ")").padEnd(38, " ") + ' should return ' + values[1], async function () { - const result = sut.isAcceptableKeymanModifier(values[0] as string); - assert.equal(result, values[1]); + + describe('create_kmn_modifier ', function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + + [ + ['anycontrol', true, 'NCAPS CTRL'], + ['shift?', true, 'NCAPS'], + ['?', true, 'NCAPS'], + ['?', false, ''], + ['caps', true, 'CAPS'], + ['', true, 'NCAPS'], + [' ', false, ''], + ['wrongModifierName', false, 'wrongModifierName'], + ['shift', false, 'SHIFT'], + ['shift command', true, 'NCAPS SHIFT command'], + ['rshift', true, 'NCAPS SHIFT'], + ['rshift', false, 'SHIFT'], + ['rightshift', true, 'NCAPS SHIFT'], + ['riGhtsHift', true, 'NCAPS SHIFT'], + ['LEFTCONTROL', true, 'NCAPS LCTRL'], + ['RCONTROL', true, 'NCAPS RCTRL'], + ['leftoption', true, 'NCAPS LALT'], + ['loption', true, 'NCAPS LALT'], + ].forEach(function (values) { + it(('should convert "' + values[0] + '"').padEnd(36, " ") + 'to "' + values[2] + '"', async function () { + const result = sut.create_kmn_modifier(values[0] as string, values[1] as boolean); + assert.equal(result, values[2]); + }); }); }); - }); - - describe("map_UkeleleKC_To_VK ", function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - - [ - [0x00, "K_A"], - [0x31, "K_SPACE"], - [0x18, "K_EQUAL"], - [0x10, "K_Y"], - [0x18, "K_EQUAL"], - [0x21, "K_LBRKT"], - [0x999, ""], - [-1, ""], - [null, ""], - ].forEach(function (values) { - it(("map_UkeleleKC_To_VK(" + values[0] + ")").padEnd(26, " ") + "should return " + "'" + values[1] + "'", async function () { - const result = sut.map_UkeleleKC_To_VK(values[0] as number); - assert.equal(result, values[1]); + + describe('getHexFromString ', function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + + [ + ['0009', '0009'], + ['000027', '001B'], + ['00027', '001B'], + ['0027', '001B'], + ['027', '001B'], + ['27', '001B'], + ['001C', '0NAN'], + ['0000', '0000'], + ['X', '0NAN'], + ['', '0000'], + [' ', '0000'], + [123, '007B'], + [null, '0000'], + ].forEach(function (values) { + it(('should convert "' + values[0] + '"').padEnd(25, " ") + 'to "' + values[1] + '"', async function () { + const result = sut.getHexFromString(values[0] as string); + assert.equal(result, values[1]); + }); }); }); - }); - - describe("checkIfCapsIsUsed ", function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - - it(("checkIfCapsIsUsed([['caps', 'xxx'], ['yyy']])").padEnd(45, " ") + " should return true", async function () { - const result = sut.checkIfCapsIsUsed([["caps", "xxx"], ["yyy"]]); - assert.isTrue(result); + + describe('convertToUnicodeCodePoint ', function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + + [ + ["􏘁", 'U+10F601'], + ["😁", 'U+1F601'], + [" ", 'U+0009'], + ["™", 'U+0099'], + ["ঙ", 'U+0999'], + ["香", 'U+9999'], + ["򙦙", 'U+99999'], + ["􏘁", 'U+10F601'], + ["😁", 'U+1F601'], + [" ", 'U+0009'], + ["c", 'U+0063'], + ["ϧ", 'U+03E7'], + ["✏", 'U+270F'], + ["𘚟", 'U+1869F'], + ['0000;', '0000;'], + ['X;', 'X;'], + ['123;', '123;'], + [';', ';'], + [' ;', ' ;'] + ].forEach(function (values) { + it(('should convert "' + values[0] + '"').padEnd(25, " ") + 'to "' + values[1] + '"', async function () { + const result = sut.convertToUnicodeCodePoint(values[0] as string); + assert.equal(result, values[1]); + }); + }); }); - - it(("checkIfCapsIsUsed([['zzz', 'xxx'], ['yyy']])").padEnd(45, " ") + " should return false", async function () { - const result = sut.checkIfCapsIsUsed([["zzz", "xxx"], ["yyy"]]); - assert.isFalse(result); + + describe("isAcceptableKeymanModifier ", function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + + [ + ["NCAPS", true], + ["NxCAPS", false], + ["SHIFT", true], + ["ALT", true], + ["RALT", true], + ["LALT", true], + ["CTRL", true], + ["LCTRL", true], + ["RCTRL", true], + ["LCTRL CAPS", true], + ["LCTRL X", false], + ["", true], + [null, false], + ].forEach(function (values) { + it(("isAcceptableKeymanModifier(" + values[0] + ")").padEnd(38, " ") + ' should return ' + values[1], async function () { + const result = sut.isAcceptableKeymanModifier(values[0] as string); + assert.equal(result, values[1]); + }); + }); }); - it(("checkIfCapsIsUsed([['', ''], ['']])").padEnd(45, " ") + " should return false", async function () { - const result = sut.checkIfCapsIsUsed([["", ""], [""]]); - assert.isFalse(result); + + describe("map_UkeleleKC_To_VK ", function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + + [ + [0x00, "K_A"], + [0x31, "K_SPACE"], + [0x18, "K_EQUAL"], + [0x10, "K_Y"], + [0x18, "K_EQUAL"], + [0x21, "K_LBRKT"], + [0x999, ""], + [-1, ""], + [null, ""], + ].forEach(function (values) { + it(("map_UkeleleKC_To_VK(" + values[0] + ")").padEnd(26, " ") + "should return " + "'" + values[1] + "'", async function () { + const result = sut.map_UkeleleKC_To_VK(values[0] as number); + assert.equal(result, values[1]); + }); + }); }); - it(("checkIfCapsIsUsed([null])").padEnd(45, " ") + " should return false", async function () { - const result = sut.checkIfCapsIsUsed([null]); - assert.isFalse(result); + + describe("checkIfCapsIsUsed ", function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + + it(("checkIfCapsIsUsed([['caps', 'xxx'], ['yyy']])").padEnd(45, " ") + " should return true", async function () { + const result = sut.checkIfCapsIsUsed([["caps", "xxx"], ["yyy"]]); + assert.isTrue(result); + }); + + it(("checkIfCapsIsUsed([['zzz', 'xxx'], ['yyy']])").padEnd(45, " ") + " should return false", async function () { + const result = sut.checkIfCapsIsUsed([["zzz", "xxx"], ["yyy"]]); + assert.isFalse(result); + }); + it(("checkIfCapsIsUsed([['', ''], ['']])").padEnd(45, " ") + " should return false", async function () { + const result = sut.checkIfCapsIsUsed([["", ""], [""]]); + assert.isFalse(result); + }); + it(("checkIfCapsIsUsed([null])").padEnd(45, " ") + " should return false", async function () { + const result = sut.checkIfCapsIsUsed([null]); + assert.isFalse(result); + }); }); - }); - - describe("get_Modifier_array__From__KeyModifier_array ", function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const read = sut.read(inputFilename); - const converted = sut.convert(read); - - [[[['0', 0]], [['', 'shift? caps? ']]], - [[['0', 1]], [['anyShift caps?', 'shift? rightShift caps? ', 'shift? leftShift caps? ', 'shift leftShift caps ']]], - [[['0', 999]], [null]], - [[['999',]], [null]], - [[['0', -999]], [null]], - [[['0']], [null]], - ].forEach(function (values) { - it((values[1][0] !== null) ? - ("get_Modifier_array__From__KeyModifier_array(['" + values[0][0][0] + "', '" + values[0][0][1] + "'])").padEnd(68, " ") + " should return ['" + values[1][0][0] + "', '" + values[1][0][1] + "']" : - ("get_Modifier_array__From__KeyModifier_array(['" + values[0][0][0] + "', '" + values[0][0][1] + "'])").padEnd(68, " ") + " should return ['" + values[1][0] + "']", async function () { + + describe("get_Modifier_array__From__KeyModifier_array ", function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const inputFilename = makePathToFixture('../data/Italian.keylayout'); + const read = sut.read(inputFilename); + const converted = sut.convert(read); + + [[[['0', 0]], [['', 'shift? caps? ']]], + [[['0', 1]], [['anyShift caps?', 'shift? rightShift caps? ', 'shift? leftShift caps? ', 'shift leftShift caps ']]], + [[['0', 999]], [null]], + [[['999',]], [null]], + [[['0', -999]], [null]], + [[['0']], [null]], + ].forEach(function (values) { + it((values[1][0] !== null) ? + ("get_Modifier_array__From__KeyModifier_array(['" + values[0][0][0] + "', '" + values[0][0][1] + "'])").padEnd(68, " ") + " should return ['" + values[1][0][0] + "', '" + values[1][0][1] + "']" : + ("get_Modifier_array__From__KeyModifier_array(['" + values[0][0][0] + "', '" + values[0][0][1] + "'])").padEnd(68, " ") + " should return ['" + values[1][0] + "']", async function () { + const result = sut.get_Modifier_array__From__KeyModifier_array(converted.arrayOf_Modifiers, values[0]); + assert.deepStrictEqual(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); + + [[[[null]], [null]], + [[[undefined]], [null]], + [[[]], [null]], + ].forEach(function (values) { + it(("get_Modifier_array__From__KeyModifier_array([" + values[0][0] + "])").padEnd(68, " ") + " should return ['" + values[1][0] + "']", async function () { const result = sut.get_Modifier_array__From__KeyModifier_array(converted.arrayOf_Modifiers, values[0]); assert.deepStrictEqual(JSON.stringify(result), JSON.stringify(values[1])); }); + }); }); - - [[[[null]], [null]], - [[[undefined]], [null]], - [[[]], [null]], - ].forEach(function (values) { - it(("get_Modifier_array__From__KeyModifier_array([" + values[0][0] + "])").padEnd(68, " ") + " should return ['" + values[1][0] + "']", async function () { - const result = sut.get_Modifier_array__From__KeyModifier_array(converted.arrayOf_Modifiers, values[0]); - assert.deepStrictEqual(JSON.stringify(result), JSON.stringify(values[1])); + + describe("get_KeyModifier_array__From__ActionID ", function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const inputFilename = makePathToFixture('../data/Italian.keylayout'); + const read = sut.read(inputFilename); + + [ + ["a16", [['32', 3]]], + ["a19", [['45', 3]]], + ["a18", [['24', 0], ['24', 3]]], + ["unknown", []], + [undefined, []], + [null, []], + [" ", []], + ["", []], + ].forEach(function (values) { + + let outstring = "[ "; + for (let i = 0; i < values[1].length; i++) { + outstring = outstring + "[ '" + values[1][i][0] + "', " + values[1][i][1].toString() + "], "; + } + + it(("get_KeyModifier_array__From__ActionID('" + values[0] + "')").padEnd(57, " ") + ' should return ' + outstring.substring(0, outstring.lastIndexOf(']') + 2) + " ]", async function () { + const result = sut.get_KeyModifier_array__From__ActionID(read, String(values[0])); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); }); }); - }); - - describe("get_KeyModifier_array__From__ActionID ", function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const read = sut.read(inputFilename); - - [ - ["a16", [['32', 3]]], - ["a19", [['45', 3]]], - ["a18", [['24', 0], ['24', 3]]], - ["unknown", []], - [undefined, []], - [null, []], - [" ", []], - ["", []], - ].forEach(function (values) { - - let outstring = "[ "; - for (let i = 0; i < values[1].length; i++) { - outstring = outstring + "[ '" + values[1][i][0] + "', " + values[1][i][1].toString() + "], "; - } - - it(("get_KeyModifier_array__From__ActionID('" + values[0] + "')").padEnd(57, " ") + ' should return ' + outstring.substring(0, outstring.lastIndexOf(']') + 2) + " ]", async function () { - const result = sut.get_KeyModifier_array__From__ActionID(read, String(values[0])); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + + describe("get_ActionID__From__ActionNext ", function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const inputFilename = makePathToFixture('../data/Italian.keylayout'); + const read = sut.read(inputFilename); + + [ + ["none", ""], + ["a18", ""], + ["0", ""], + ["1", "a16"], + ["2", "a8"], + ["3", "a17"], + ["", ""], + [" ", ""], + ["99", ""], + [null, ""], + [undefined, ""], + ["unknown", ""], + ].forEach(function (values) { + it(("get_ActionID__From__ActionNext('" + values[0] + "')").padEnd(49, " ") + ' should return ' + "'" + values[1] + "'", async function () { + const result = sut.get_ActionID__From__ActionNext(read, String(values[0])); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); }); }); - }); - - describe("get_ActionID__From__ActionNext ", function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const read = sut.read(inputFilename); - - [ - ["none", ""], - ["a18", ""], - ["0", ""], - ["1", "a16"], - ["2", "a8"], - ["3", "a17"], + + describe("get_ActionIndex__From__ActionId ", function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const inputFilename = makePathToFixture('../data/Italian.keylayout'); + const read = sut.read(inputFilename); + + [ + ["none", 0], + ["a16", 8], + ["a18", 10], + ["a19", 11], + ["0", 0], + ["", 0], + [" ", 0], + [null, 0], + [undefined, 0], + ["unknown", 0], + ].forEach(function (values) { + it(("get_ActionIndex__From__ActionId('" + values[0] + "')").padEnd(50, " ") + ' should return ' + values[1], async function () { + const result = sut.get_ActionIndex__From__ActionId(read, String(values[0])); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); + }); + + describe("get_Output__From__ActionId_None ", function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const inputFilename = makePathToFixture('../data/Italian.keylayout'); + const read = sut.read(inputFilename); + + [["a14", "u"], ["", ""], [" ", ""], - ["99", ""], - [null, ""], - [undefined, ""], + ["a18", undefined], ["unknown", ""], - ].forEach(function (values) { - it(("get_ActionID__From__ActionNext('" + values[0] + "')").padEnd(49, " ") + ' should return ' + "'" + values[1] + "'", async function () { - const result = sut.get_ActionID__From__ActionNext(read, String(values[0])); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + ].forEach(function (values) { + it( + ("get_Output__From__ActionId_None('" + values[0] + "')").padEnd(56, " ") + ' should return ' + "'" + values[1] + "'", async function () { + const result = sut.get_Output__From__ActionId_None(read, String(values[0])); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); }); - }); - }); - - describe("get_ActionIndex__From__ActionId ", function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const read = sut.read(inputFilename); - - [ - ["none", 0], - ["a16", 8], - ["a18", 10], - ["a19", 11], - ["0", 0], - ["", 0], - [" ", 0], - [null, 0], - [undefined, 0], - ["unknown", 0], - ].forEach(function (values) { - it(("get_ActionIndex__From__ActionId('" + values[0] + "')").padEnd(50, " ") + ' should return ' + values[1], async function () { - const result = sut.get_ActionIndex__From__ActionId(read, String(values[0])); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); - }); - }); - }); - - describe("get_Output__From__ActionId_None ", function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const read = sut.read(inputFilename); - - [["a14", "u"], - ["", ""], - [" ", ""], - ["a18", undefined], - ["unknown", ""], - ].forEach(function (values) { - it( - ("get_Output__From__ActionId_None('" + values[0] + "')").padEnd(56, " ") + ' should return ' + "'" + values[1] + "'", async function () { + + [[null, ""], + [undefined, ""], + [99, ""], + ].forEach(function (values) { + it(("get_Output__From__ActionId_None('" + values[0] + "')").padEnd(56, " ") + ' should return ' + values[1], async function () { const result = sut.get_Output__From__ActionId_None(read, String(values[0])); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); - }); - - [[null, ""], - [undefined, ""], - [99, ""], - ].forEach(function (values) { - it(("get_Output__From__ActionId_None('" + values[0] + "')").padEnd(56, " ") + ' should return ' + values[1], async function () { - const result = sut.get_Output__From__ActionId_None(read, String(values[0])); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); - }); - - describe("get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array ", function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const read = sut.read(inputFilename); - - const b1_keycode_arr = [ - ['49', 'K_SPACE', 'a0', '0', 'ˆ'], - ['49', 'K_SPACE', 'a0', '1', 'ˆ'], - ['49', 'K_SPACE', 'a0', '2', 'ˆ'], - ['6', 'K_Z', 'a0', '4', 'ˆ'], - ['25', 'K_9', 'a0', '4', 'ˆ'], - ['43', 'K_COMMA', 'a0', '4', 'ˆ'], - ['49', 'K_SPACE', 'a0', '7', 'ˆ'], - ['0', 'K_A', 'a1', '1', 'Â'], - ['0', 'K_A', 'a1', '2', 'Â'], - ['14', 'K_E', 'a10', '0', 'ê'], - ['34', 'K_I', 'a11', '0', 'î'], - ['31', 'K_O', 'a13', '0', 'ô'], - ['32', 'K_U', 'a14', '0', 'û'], - ['14', 'K_E', 'a2', '1', 'Ê'], - ['14', 'K_E', 'a2', '2', 'Ê'], - ['34', 'K_I', 'a3', '1', 'Î'], - ['34', 'K_I', 'a3', '2', 'Î'], - ['31', 'K_O', 'a5', '1', 'Ô'], - ['31', 'K_O', 'a5', '2', 'Ô'], - ['32', 'K_U', 'a6', '1', 'Û'], - ['32', 'K_U', 'a6', '2', 'Û'], - ['0', 'K_A', 'a9', '0', 'â'] - ]; - const b1_modifierKey_arr = [ - ['K_SPACE', 'a0', '0', 'NCAPS', 'ˆ'], - ['K_SPACE', 'a0', '1', 'SHIFT NCAPS', 'ˆ'], - ['K_SPACE', 'a0', '1', 'SHIFT CAPS', 'ˆ'], - ['K_SPACE', 'a0', '2', 'CAPS', 'ˆ'], - ['K_Z', 'a0', '4', 'SHIFT NCAPS RALT', 'ˆ'], - ['K_9', 'a0', '4', 'SHIFT NCAPS RALT', 'ˆ'], - ['K_COMMA', 'a0', '4', 'SHIFT NCAPS RALT', 'ˆ'], - ['K_SPACE', 'a0', '7', 'NCAPS CTRL', 'ˆ'], - ['K_SPACE', 'a0', '7', 'NCAPS RALT CTRL', 'ˆ'], - ['K_A', 'a1', '1', 'SHIFT NCAPS', 'Â'], - ['K_A', 'a1', '1', 'SHIFT CAPS', 'Â'], - ['K_A', 'a1', '2', 'CAPS', 'Â'], - ['K_E', 'a10', '0', 'NCAPS', 'ê'], - ['K_I', 'a11', '0', 'NCAPS', 'î'], - ['K_O', 'a13', '0', 'NCAPS', 'ô'], - ['K_U', 'a14', '0', 'NCAPS', 'û'], - ['K_E', 'a2', '1', 'SHIFT NCAPS', 'Ê'], - ['K_E', 'a2', '1', 'SHIFT CAPS', 'Ê'], - ['K_E', 'a2', '2', 'CAPS', 'Ê'], - ['K_I', 'a3', '1', 'SHIFT NCAPS', 'Î'], - ['K_I', 'a3', '1', 'SHIFT CAPS', 'Î'], - ['K_I', 'a3', '2', 'CAPS', 'Î'], - ['K_O', 'a5', '1', 'SHIFT NCAPS', 'Ô'], - ['K_O', 'a5', '1', 'SHIFT CAPS', 'Ô'], - ['K_O', 'a5', '2', 'CAPS', 'Ô'], - ['K_U', 'a6', '1', 'SHIFT NCAPS', 'Û'], - ['K_U', 'a6', '1', 'SHIFT CAPS', 'Û'], - ['K_U', 'a6', '2', 'CAPS', 'Û'], - ['K_A', 'a9', '0', 'NCAPS', 'â'] - ]; - - // isCaps_used === true; input defined - [[b1_keycode_arr, b1_modifierKey_arr], - [[['49', 'K_SPACE', 'a0', '0', 'ˆ']], [['K_SPACE', 'a0', '0', 'NCAPS', 'ˆ']]], - [[['49', 'K_SPACE', 'a0', '0', '']], [['K_SPACE', 'a0', '0', 'NCAPS', '']]], - [[['49', 'K_SPACE', 'a0', '', 'ˆ']], [['K_SPACE', 'a0', '', 'NCAPS', 'ˆ']]], - [[['49', 'K_SPACE', '', '0', 'ˆ']], [['K_SPACE', '', '0', 'NCAPS', 'ˆ']]], - [[['49', '', 'a0', '0', 'ˆ']], [['', 'a0', '0', 'NCAPS', 'ˆ']]], - [[['', 'K_SPACE', 'a0', '0', 'ˆ']], [['K_SPACE', 'a0', '0', 'NCAPS', 'ˆ']]], - [[['', 'K_SPACE', 'a0', '0', 'ˆ']], [['K_SPACE', 'a0', '0', 'NCAPS', 'ˆ']]], - [[['', '', '', '', '']], [['', '', '', 'NCAPS', '']]], - ].forEach(function (values) { - - const isCaps_used = true; - const string_in = "get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(['" + "', '" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "', '" + values[0][0][3] + "', '" + values[0][0][4] + "'])"; - const string_out = "['" + "', '" + values[1][0][0] + "', '" + values[1][0][1] + "', '" + values[1][0][2] + "', '" + values[1][0][3] + "', '" + values[1][0][4] + "']"; - - it((JSON.stringify(values[1]).length > 60) ? 'an array of objects should return an array of objectss' : - string_in.padEnd(74, " ") + ' should return ' + string_out, async function () { + + describe("get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array ", function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const inputFilename = makePathToFixture('../data/Italian.keylayout'); + const read = sut.read(inputFilename); + + const b1_keycode_arr = [ + ['49', 'K_SPACE', 'a0', '0', 'ˆ'], + ['49', 'K_SPACE', 'a0', '1', 'ˆ'], + ['49', 'K_SPACE', 'a0', '2', 'ˆ'], + ['6', 'K_Z', 'a0', '4', 'ˆ'], + ['25', 'K_9', 'a0', '4', 'ˆ'], + ['43', 'K_COMMA', 'a0', '4', 'ˆ'], + ['49', 'K_SPACE', 'a0', '7', 'ˆ'], + ['0', 'K_A', 'a1', '1', 'Â'], + ['0', 'K_A', 'a1', '2', 'Â'], + ['14', 'K_E', 'a10', '0', 'ê'], + ['34', 'K_I', 'a11', '0', 'î'], + ['31', 'K_O', 'a13', '0', 'ô'], + ['32', 'K_U', 'a14', '0', 'û'], + ['14', 'K_E', 'a2', '1', 'Ê'], + ['14', 'K_E', 'a2', '2', 'Ê'], + ['34', 'K_I', 'a3', '1', 'Î'], + ['34', 'K_I', 'a3', '2', 'Î'], + ['31', 'K_O', 'a5', '1', 'Ô'], + ['31', 'K_O', 'a5', '2', 'Ô'], + ['32', 'K_U', 'a6', '1', 'Û'], + ['32', 'K_U', 'a6', '2', 'Û'], + ['0', 'K_A', 'a9', '0', 'â'] + ]; + const b1_modifierKey_arr = [ + ['K_SPACE', 'a0', '0', 'NCAPS', 'ˆ'], + ['K_SPACE', 'a0', '1', 'SHIFT NCAPS', 'ˆ'], + ['K_SPACE', 'a0', '1', 'SHIFT CAPS', 'ˆ'], + ['K_SPACE', 'a0', '2', 'CAPS', 'ˆ'], + ['K_Z', 'a0', '4', 'SHIFT NCAPS RALT', 'ˆ'], + ['K_9', 'a0', '4', 'SHIFT NCAPS RALT', 'ˆ'], + ['K_COMMA', 'a0', '4', 'SHIFT NCAPS RALT', 'ˆ'], + ['K_SPACE', 'a0', '7', 'NCAPS CTRL', 'ˆ'], + ['K_SPACE', 'a0', '7', 'NCAPS RALT CTRL', 'ˆ'], + ['K_A', 'a1', '1', 'SHIFT NCAPS', 'Â'], + ['K_A', 'a1', '1', 'SHIFT CAPS', 'Â'], + ['K_A', 'a1', '2', 'CAPS', 'Â'], + ['K_E', 'a10', '0', 'NCAPS', 'ê'], + ['K_I', 'a11', '0', 'NCAPS', 'î'], + ['K_O', 'a13', '0', 'NCAPS', 'ô'], + ['K_U', 'a14', '0', 'NCAPS', 'û'], + ['K_E', 'a2', '1', 'SHIFT NCAPS', 'Ê'], + ['K_E', 'a2', '1', 'SHIFT CAPS', 'Ê'], + ['K_E', 'a2', '2', 'CAPS', 'Ê'], + ['K_I', 'a3', '1', 'SHIFT NCAPS', 'Î'], + ['K_I', 'a3', '1', 'SHIFT CAPS', 'Î'], + ['K_I', 'a3', '2', 'CAPS', 'Î'], + ['K_O', 'a5', '1', 'SHIFT NCAPS', 'Ô'], + ['K_O', 'a5', '1', 'SHIFT CAPS', 'Ô'], + ['K_O', 'a5', '2', 'CAPS', 'Ô'], + ['K_U', 'a6', '1', 'SHIFT NCAPS', 'Û'], + ['K_U', 'a6', '1', 'SHIFT CAPS', 'Û'], + ['K_U', 'a6', '2', 'CAPS', 'Û'], + ['K_A', 'a9', '0', 'NCAPS', 'â'] + ]; + + // isCaps_used === true; input defined + [[b1_keycode_arr, b1_modifierKey_arr], + [[['49', 'K_SPACE', 'a0', '0', 'ˆ']], [['K_SPACE', 'a0', '0', 'NCAPS', 'ˆ']]], + [[['49', 'K_SPACE', 'a0', '0', '']], [['K_SPACE', 'a0', '0', 'NCAPS', '']]], + [[['49', 'K_SPACE', 'a0', '', 'ˆ']], [['K_SPACE', 'a0', '', 'NCAPS', 'ˆ']]], + [[['49', 'K_SPACE', '', '0', 'ˆ']], [['K_SPACE', '', '0', 'NCAPS', 'ˆ']]], + [[['49', '', 'a0', '0', 'ˆ']], [['', 'a0', '0', 'NCAPS', 'ˆ']]], + [[['', 'K_SPACE', 'a0', '0', 'ˆ']], [['K_SPACE', 'a0', '0', 'NCAPS', 'ˆ']]], + [[['', 'K_SPACE', 'a0', '0', 'ˆ']], [['K_SPACE', 'a0', '0', 'NCAPS', 'ˆ']]], + [[['', '', '', '', '']], [['', '', '', 'NCAPS', '']]], + ].forEach(function (values) { + + const isCaps_used = true; + const string_in = "get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(['" + "', '" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "', '" + values[0][0][3] + "', '" + values[0][0][4] + "'])"; + const string_out = "['" + "', '" + values[1][0][0] + "', '" + values[1][0][1] + "', '" + values[1][0][2] + "', '" + values[1][0][3] + "', '" + values[1][0][4] + "']"; + + it((JSON.stringify(values[1]).length > 60) ? 'an array of objects should return an array of objectss' : + string_in.padEnd(74, " ") + ' should return ' + string_out, async function () { + const result = sut.get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(read, values[0], isCaps_used); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); + + // isCaps_used === false; input defined + [[[['49', 'K_SPACE', 'a0', '0', 'ˆ']], [['K_SPACE', 'a0', '0', '', 'ˆ']]], + [[['49', 'K_SPACE', 'a0', '0', '']], [['K_SPACE', 'a0', '0', '', '']]], + [[['', 'K_SPACE', 'a0', '0', 'ˆ']], [['K_SPACE', 'a0', '0', '', 'ˆ']]], + [[['', '', '', '', '']], [['', '', '', '', '']]], + ].forEach(function (values) { + + const isCaps_used = false; + const string_in = "get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(['" + "', '" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "', '" + values[0][0][3] + "', '" + values[0][0][4] + "'])"; + const string_out = "['" + "', '" + values[1][0][0] + "', '" + values[1][0][1] + "', '" + values[1][0][2] + "', '" + values[1][0][3] + "', '" + values[1][0][4] + "']"; + + it(string_in.padEnd(74, " ") + ' should return ' + string_out, async function () { const result = sut.get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(read, values[0], isCaps_used); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); - }); - - // isCaps_used === false; input defined - [[[['49', 'K_SPACE', 'a0', '0', 'ˆ']], [['K_SPACE', 'a0', '0', '', 'ˆ']]], - [[['49', 'K_SPACE', 'a0', '0', '']], [['K_SPACE', 'a0', '0', '', '']]], - [[['', 'K_SPACE', 'a0', '0', 'ˆ']], [['K_SPACE', 'a0', '0', '', 'ˆ']]], - [[['', '', '', '', '']], [['', '', '', '', '']]], - ].forEach(function (values) { - - const isCaps_used = false; - const string_in = "get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(['" + "', '" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "', '" + values[0][0][3] + "', '" + values[0][0][4] + "'])"; - const string_out = "['" + "', '" + values[1][0][0] + "', '" + values[1][0][1] + "', '" + values[1][0][2] + "', '" + values[1][0][3] + "', '" + values[1][0][4] + "']"; - - it(string_in.padEnd(74, " ") + ' should return ' + string_out, async function () { - const result = sut.get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(read, values[0], isCaps_used); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); - }); - - // isCaps_used === true; input undefined/null/empty - [[[], []], - [undefined, []], - [null, []], - ].forEach(function (values) { - const isCaps = true; - it(("get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array([" + values[0] + "])").padEnd(74, " ") + ' should return ' + "[" + values[1] + "]", async function () { - const result = sut.get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(read, values[0], isCaps); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + + // isCaps_used === true; input undefined/null/empty + [[[], []], + [undefined, []], + [null, []], + ].forEach(function (values) { + const isCaps = true; + it(("get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array([" + values[0] + "])").padEnd(74, " ") + ' should return ' + "[" + values[1] + "]", async function () { + const result = sut.get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(read, values[0], isCaps); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); }); }); - }); - - describe("writeData_Stores() ", function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const read = sut.read(inputFilename); - const converted = sut.convert(read); - - // empty convert_object from unavailable file name - const inputFilename_unavailable = makePathToFixture('X.keylayout'); - const read_unavailable = sut.read(inputFilename_unavailable); - const converted_unavailable = sut.convert(read_unavailable); - - // empty convert_object from empty filename - const inputFilename_empty = makePathToFixture(''); - const read_empty = sut.read(inputFilename_empty); - const converted_empty = sut.convert(read_empty); - - const out_expected_first: string = - "c ......................................................................\n" - + "c ......................................................................\n" - + "c Keyman keyboard generated by kmn-convert\n" - + "c from Ukelele file: "; - - const out_expected_last: string = - "\n" - + "c ......................................................................\n" - + "c ......................................................................\n" - + "\n" - + "store(&VERSION) '10.0'\n" - + "store(&TARGETS) 'any'\n" - + "store(&KEYBOARDVERSION) '1.0'\n" - + "store(©RIGHT) '© 2024 SIL International'\n" - + "\n" - + "begin Unicode > use(main)\n\n" - + "group(main) using keys\n\n" - + "\n"; - - it(('writeData_Stores should return store text with filename ').padEnd(62, " ") + 'on correct input', async function () { - const written_correctName = sut.writeData_Stores(converted); - assert.equal(written_correctName, (out_expected_first + converted.keylayout_filename + out_expected_last)); + + describe("writeData_Stores() ", function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const inputFilename = makePathToFixture('../data/Italian.keylayout'); + const read = sut.read(inputFilename); + const converted = sut.convert(read); + + // empty convert_object from unavailable file name + const inputFilename_unavailable = makePathToFixture('X.keylayout'); + const read_unavailable = sut.read(inputFilename_unavailable); + const converted_unavailable = sut.convert(read_unavailable); + + // empty convert_object from empty filename + const inputFilename_empty = makePathToFixture(''); + const read_empty = sut.read(inputFilename_empty); + const converted_empty = sut.convert(read_empty); + + const out_expected_first: string = + "c ......................................................................\n" + + "c ......................................................................\n" + + "c Keyman keyboard generated by kmn-convert\n" + + "c from Ukelele file: "; + + const out_expected_last: string = + "\n" + + "c ......................................................................\n" + + "c ......................................................................\n" + + "\n" + + "store(&VERSION) '10.0'\n" + + "store(&TARGETS) 'any'\n" + + "store(&KEYBOARDVERSION) '1.0'\n" + + "store(©RIGHT) '© 2024 SIL International'\n" + + "\n" + + "begin Unicode > use(main)\n\n" + + "group(main) using keys\n\n" + + "\n"; + + it(('writeData_Stores should return store text with filename ').padEnd(62, " ") + 'on correct input', async function () { + const written_correctName = sut.writeData_Stores(converted); + assert.equal(written_correctName, (out_expected_first + converted.keylayout_filename + out_expected_last)); + }); + + it(('writeData_Stores should return store text without filename ').padEnd(62, " ") + 'on empty input', async function () { + const written_emptyName = sut.writeData_Stores(converted_empty); + assert.equal(written_emptyName, (out_expected_first + out_expected_last)); + }); + + it(('writeData_Stores should return store text without filename ').padEnd(62, " ") + 'on only filename as input', async function () { + const written_onlyName = sut.writeData_Stores(converted_unavailable); + assert.equal(written_onlyName, (out_expected_first + converted_unavailable.keylayout_filename + out_expected_last)); + }); }); - - it(('writeData_Stores should return store text without filename ').padEnd(62, " ") + 'on empty input', async function () { - const written_emptyName = sut.writeData_Stores(converted_empty); - assert.equal(written_emptyName, (out_expected_first + out_expected_last)); + + describe("get_ActionStateOutput_array__From__ActionState ", function () { + + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const inputFilename = makePathToFixture('../data/Italian.keylayout'); + const read = sut.read(inputFilename); + + [["1", [ + ['a0', '1', 'ˆ'], + ['a1', '1', 'Â'], + ['a10', '1', 'ê'], + ['a11', '1', 'î'], + ['a13', '1', 'ô'], + ['a14', '1', 'û'], + ['a2', '1', 'Ê'], + ['a3', '1', 'Î'], + ['a5', '1', 'Ô'], + ['a6', '1', 'Û'], + ['a9', '1', 'â']],], + ["2", [ + ['a0', '2', '`'], + ['a1', '2', 'À'], + ['a10', '2', 'è'], + ['a11', '2', 'ì'], + ['a13', '2', 'ò'], + ['a14', '2', 'ù'], + ['a2', '2', 'È'], + ['a3', '2', 'Ì'], + ['a5', '2', 'Ò'], + ['a6', '2', 'Ù'], + ['a9', '2', 'à']],], + ["789", [],], + ["", [],], + [" ", [],], + [123, [],], + [null, [],], + [undefined, [],], + ].forEach(function (values) { + it((JSON.stringify(values[1]).length > 30) ? + ("get_ActionStateOutput_array__From__ActionState('" + values[0] + "')").padEnd(60, " ") + ' should return an array of objects' : + ("get_ActionStateOutput_array__From__ActionState('" + values[0] + "')").padEnd(60, " ") + ' should return ' + "'" + JSON.stringify(values[1]) + "'", async function () { + const result = sut.get_ActionStateOutput_array__From__ActionState(read, String(values[0])); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); }); - - it(('writeData_Stores should return store text without filename ').padEnd(62, " ") + 'on only filename as input', async function () { - const written_onlyName = sut.writeData_Stores(converted_unavailable); - assert.equal(written_onlyName, (out_expected_first + converted_unavailable.keylayout_filename + out_expected_last)); + + describe("get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput ", function () { + + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const inputFilename = makePathToFixture('../data/Italian.keylayout'); + const read = sut.read(inputFilename); + const converted = sut.convert(read); + + [ + ["a1", "A", true, [ + ['a1', 'A', 'a1', '1', 'K_A', 'SHIFT NCAPS'], + ['a1', 'A', 'a1', '1', 'K_A', 'SHIFT CAPS'], + ['a1', 'A', 'a1', '2', 'K_A', 'CAPS']] + ], + ["a1", "A", false, [ + ['a1', 'A', 'a1', '1', 'K_A', 'SHIFT'], + ['a1', 'A', 'a1', '1', 'K_A', 'SHIFT CAPS'], + ['a1', 'A', 'a1', '2', 'K_A', 'CAPS']] + ], + ["a9", "a", true, [['a9', 'a', 'a9', '0', 'K_A', 'NCAPS']]], + ["a9", "a", false, [['a9', 'a', 'a9', '0', 'K_A', '']]], + ["a9", "a", , [['a9', 'a', 'a9', '0', 'K_A', '']]], + ["a9", "", true, [["a9", "", "a9", "0", "K_A", "NCAPS"]]], + ["a9", "", false, [["a9", "", "a9", "0", "K_A", ""]]], + ["", "a", true, []], + ["", "a", false, []], + ["", "", , []], + + ].forEach(function (values) { + it((JSON.stringify(values[3]).length > 35) ? + ("get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput('" + values[0] + "', '" + values[1] + "', " + values[2] + ")").padEnd(67, " ") + ' should return an array of objects' : + ("get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput('" + values[0] + "', '" + values[1] + "', " + values[2] + ")").padEnd(67, " ") + ' should return ' + "'" + JSON.stringify(values[3]) + "'", async function () { + const result = sut.get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput(read, converted.arrayOf_Modifiers, String(values[0]), String(values[1]), Boolean(values[2])); + assert.equal(JSON.stringify(result), JSON.stringify(values[3])); + }); + }); }); - }); - - describe("get_ActionStateOutput_array__From__ActionState ", function () { - - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const read = sut.read(inputFilename); - - [["1", [ - ['a0', '1', 'ˆ'], - ['a1', '1', 'Â'], - ['a10', '1', 'ê'], - ['a11', '1', 'î'], - ['a13', '1', 'ô'], - ['a14', '1', 'û'], - ['a2', '1', 'Ê'], - ['a3', '1', 'Î'], - ['a5', '1', 'Ô'], - ['a6', '1', 'Û'], - ['a9', '1', 'â']],], - ["2", [ - ['a0', '2', '`'], - ['a1', '2', 'À'], - ['a10', '2', 'è'], - ['a11', '2', 'ì'], - ['a13', '2', 'ò'], - ['a14', '2', 'ù'], - ['a2', '2', 'È'], - ['a3', '2', 'Ì'], - ['a5', '2', 'Ò'], - ['a6', '2', 'Ù'], - ['a9', '2', 'à']],], - ["789", [],], - ["", [],], - [" ", [],], - [123, [],], - [null, [],], - [undefined, [],], - ].forEach(function (values) { - it((JSON.stringify(values[1]).length > 30) ? - ("get_ActionStateOutput_array__From__ActionState('" + values[0] + "')").padEnd(60, " ") + ' should return an array of objects' : - ("get_ActionStateOutput_array__From__ActionState('" + values[0] + "')").padEnd(60, " ") + ' should return ' + "'" + JSON.stringify(values[1]) + "'", async function () { - const result = sut.get_ActionStateOutput_array__From__ActionState(read, String(values[0])); + + describe("get_KeyActionOutput_array__From__ActionStateOutput_array ", function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const inputFilename = makePathToFixture('../data/Italian.keylayout'); + const read = sut.read(inputFilename); + + const b6_actionId_arr = [ + ['a0', '1', 'ˆ'], + ['a1', '1', 'Â'], + ['a10', '1', 'ê'], + ['a11', '1', 'î'], + ['a13', '1', 'ô'], + ['a14', '1', 'û'], + ['a2', '1', 'Ê'], + ['a3', '1', 'Î'], + ['a5', '1', 'Ô'], + ['a6', '1', 'Û'], + ['a9', '1', 'â'] + ]; + const b1_keycode_arr = [ + ['49', 'K_SPACE', 'a0', '0', 'ˆ'], + ['49', 'K_SPACE', 'a0', '1', 'ˆ'], + ['49', 'K_SPACE', 'a0', '2', 'ˆ'], + ['6', 'K_Z', 'a0', '4', 'ˆ'], + ['25', 'K_9', 'a0', '4', 'ˆ'], + ['43', 'K_COMMA', 'a0', '4', 'ˆ'], + ['49', 'K_SPACE', 'a0', '7', 'ˆ'], + ['0', 'K_A', 'a1', '1', 'Â'], + ['0', 'K_A', 'a1', '2', 'Â'], + ['14', 'K_E', 'a10', '0', 'ê'], + ['34', 'K_I', 'a11', '0', 'î'], + ['31', 'K_O', 'a13', '0', 'ô'], + ['32', 'K_U', 'a14', '0', 'û'], + ['14', 'K_E', 'a2', '1', 'Ê'], + ['14', 'K_E', 'a2', '2', 'Ê'], + ['34', 'K_I', 'a3', '1', 'Î'], + ['34', 'K_I', 'a3', '2', 'Î'], + ['31', 'K_O', 'a5', '1', 'Ô'], + ['31', 'K_O', 'a5', '2', 'Ô'], + ['32', 'K_U', 'a6', '1', 'Û'], + ['32', 'K_U', 'a6', '2', 'Û'], + ['0', 'K_A', 'a9', '0', 'â'] + ]; + + [[b6_actionId_arr, b1_keycode_arr], + ].forEach(function (values) { + it(("get_KeyActionOutput_array__From__ActionStateOutput_array([['" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "'],..])").padEnd(73, " ") + ' should return an array of objects', async function () { + const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0]); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); - }); - }); - - describe("get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput ", function () { - - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const read = sut.read(inputFilename); - const converted = sut.convert(read); - - [ - ["a1", "A", true, [ - ['a1', 'A', 'a1', '1', 'K_A', 'SHIFT NCAPS'], - ['a1', 'A', 'a1', '1', 'K_A', 'SHIFT CAPS'], - ['a1', 'A', 'a1', '2', 'K_A', 'CAPS']] - ], - ["a1", "A", false, [ - ['a1', 'A', 'a1', '1', 'K_A', 'SHIFT'], - ['a1', 'A', 'a1', '1', 'K_A', 'SHIFT CAPS'], - ['a1', 'A', 'a1', '2', 'K_A', 'CAPS']] - ], - ["a9", "a", true, [['a9', 'a', 'a9', '0', 'K_A', 'NCAPS']]], - ["a9", "a", false, [['a9', 'a', 'a9', '0', 'K_A', '']]], - ["a9", "a", , [['a9', 'a', 'a9', '0', 'K_A', '']]], - ["a9", "", true, [["a9", "", "a9", "0", "K_A", "NCAPS"]]], - ["a9", "", false, [["a9", "", "a9", "0", "K_A", ""]]], - ["", "a", true, []], - ["", "a", false, []], - ["", "", , []], - - ].forEach(function (values) { - it((JSON.stringify(values[3]).length > 35) ? - ("get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput('" + values[0] + "', '" + values[1] + "', " + values[2] + ")").padEnd(67, " ") + ' should return an array of objects' : - ("get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput('" + values[0] + "', '" + values[1] + "', " + values[2] + ")").padEnd(67, " ") + ' should return ' + "'" + JSON.stringify(values[3]) + "'", async function () { - const result = sut.get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput(read, converted.arrayOf_Modifiers, String(values[0]), String(values[1]), Boolean(values[2])); - assert.equal(JSON.stringify(result), JSON.stringify(values[3])); - }); - }); - }); - - describe("get_KeyActionOutput_array__From__ActionStateOutput_array ", function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const read = sut.read(inputFilename); - - const b6_actionId_arr = [ - ['a0', '1', 'ˆ'], - ['a1', '1', 'Â'], - ['a10', '1', 'ê'], - ['a11', '1', 'î'], - ['a13', '1', 'ô'], - ['a14', '1', 'û'], - ['a2', '1', 'Ê'], - ['a3', '1', 'Î'], - ['a5', '1', 'Ô'], - ['a6', '1', 'Û'], - ['a9', '1', 'â'] - ]; - const b1_keycode_arr = [ - ['49', 'K_SPACE', 'a0', '0', 'ˆ'], - ['49', 'K_SPACE', 'a0', '1', 'ˆ'], - ['49', 'K_SPACE', 'a0', '2', 'ˆ'], - ['6', 'K_Z', 'a0', '4', 'ˆ'], - ['25', 'K_9', 'a0', '4', 'ˆ'], - ['43', 'K_COMMA', 'a0', '4', 'ˆ'], - ['49', 'K_SPACE', 'a0', '7', 'ˆ'], - ['0', 'K_A', 'a1', '1', 'Â'], - ['0', 'K_A', 'a1', '2', 'Â'], - ['14', 'K_E', 'a10', '0', 'ê'], - ['34', 'K_I', 'a11', '0', 'î'], - ['31', 'K_O', 'a13', '0', 'ô'], - ['32', 'K_U', 'a14', '0', 'û'], - ['14', 'K_E', 'a2', '1', 'Ê'], - ['14', 'K_E', 'a2', '2', 'Ê'], - ['34', 'K_I', 'a3', '1', 'Î'], - ['34', 'K_I', 'a3', '2', 'Î'], - ['31', 'K_O', 'a5', '1', 'Ô'], - ['31', 'K_O', 'a5', '2', 'Ô'], - ['32', 'K_U', 'a6', '1', 'Û'], - ['32', 'K_U', 'a6', '2', 'Û'], - ['0', 'K_A', 'a9', '0', 'â'] - ]; - - [[b6_actionId_arr, b1_keycode_arr], - ].forEach(function (values) { - it(("get_KeyActionOutput_array__From__ActionStateOutput_array([['" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "'],..])").padEnd(73, " ") + ' should return an array of objects', async function () { - const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0]); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); - }); - - //----------------- - const oneEntryResult = [ - ["49", "K_SPACE", "a0", "0", "ˆ"], - ["49", "K_SPACE", "a0", "1", "ˆ"], - ["49", "K_SPACE", "a0", "2", "ˆ"], - ["6", "K_Z", "a0", "4", "ˆ"], - ["25", "K_9", "a0", "4", "ˆ"], - ["43", "K_COMMA", "a0", "4", "ˆ"], - ["49", "K_SPACE", "a0", "7", "ˆ"] - ]; - const oneEntryResultNoOutput = [ - ["49", "K_SPACE", "a0", "0", ""], - ["49", "K_SPACE", "a0", "1", ""], - ["49", "K_SPACE", "a0", "2", ""], - ["6", "K_Z", "a0", "4", ""], - ["25", "K_9", "a0", "4", ""], - ["43", "K_COMMA", "a0", "4", ""], - ["49", "K_SPACE", "a0", "7", ""] - ]; - - [[[['a0', '1', 'ˆ']], oneEntryResult], - [[['a0', '1', '']], oneEntryResultNoOutput], - [[['a0', '', 'ˆ']], oneEntryResult], - ].forEach(function (values) { - it(("get_KeyActionOutput_array__From__ActionStateOutput_array(['" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "'])").padEnd(73, " ") + ' should return an array of objects', async function () { - const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0]); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + + //----------------- + const oneEntryResult = [ + ["49", "K_SPACE", "a0", "0", "ˆ"], + ["49", "K_SPACE", "a0", "1", "ˆ"], + ["49", "K_SPACE", "a0", "2", "ˆ"], + ["6", "K_Z", "a0", "4", "ˆ"], + ["25", "K_9", "a0", "4", "ˆ"], + ["43", "K_COMMA", "a0", "4", "ˆ"], + ["49", "K_SPACE", "a0", "7", "ˆ"] + ]; + const oneEntryResultNoOutput = [ + ["49", "K_SPACE", "a0", "0", ""], + ["49", "K_SPACE", "a0", "1", ""], + ["49", "K_SPACE", "a0", "2", ""], + ["6", "K_Z", "a0", "4", ""], + ["25", "K_9", "a0", "4", ""], + ["43", "K_COMMA", "a0", "4", ""], + ["49", "K_SPACE", "a0", "7", ""] + ]; + + [[[['a0', '1', 'ˆ']], oneEntryResult], + [[['a0', '1', '']], oneEntryResultNoOutput], + [[['a0', '', 'ˆ']], oneEntryResult], + ].forEach(function (values) { + it(("get_KeyActionOutput_array__From__ActionStateOutput_array(['" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "'])").padEnd(73, " ") + ' should return an array of objects', async function () { + const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0]); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); }); - }); - - //----------------- - [[[['', '1', 'ˆ']], []], - [[['', '', '']], []], - [[[' ', ' ', '']], []], - ].forEach(function (values) { - it(("get_KeyActionOutput_array__From__ActionStateOutput_array(['" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "'])").padEnd(73, " ") + ' should return ' + "'[" + values[1] + "]'", async function () { - const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0]); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + + //----------------- + [[[['', '1', 'ˆ']], []], + [[['', '', '']], []], + [[[' ', ' ', '']], []], + ].forEach(function (values) { + it(("get_KeyActionOutput_array__From__ActionStateOutput_array(['" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "'])").padEnd(73, " ") + ' should return ' + "'[" + values[1] + "]'", async function () { + const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0]); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); }); - }); - - //----------------- - [[[], []], - [undefined, []], - [null, []], - ].forEach(function (values) { - it(("get_KeyActionOutput_array__From__ActionStateOutput_array(" + values[0] + ")").padEnd(73, " ") + ' should return ' + "'[" + values[1] + "]'", async function () { - const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0]); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + + //----------------- + [[[], []], + [undefined, []], + [null, []], + ].forEach(function (values) { + it(("get_KeyActionOutput_array__From__ActionStateOutput_array(" + values[0] + ")").padEnd(73, " ") + ' should return ' + "'[" + values[1] + "]'", async function () { + const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0]); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); }); }); - }); - + }); From 7315f6cb35adbee5927b5942f7085c7e00b80daf Mon Sep 17 00:00:00 2001 From: Sabine Date: Wed, 26 Mar 2025 15:53:35 +0100 Subject: [PATCH 072/251] feat(developer): enable use without specified output file name --- .../keylayout-to-kmn-converter.ts | 33 +- .../test/test-keylayout-to-kmn-converter.ts | 1489 ++++++++--------- 2 files changed, 758 insertions(+), 764 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index c715809236d..697fda11847 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -65,6 +65,7 @@ export interface rule_object { export interface convert_object { keylayout_filename: string, + kmn_filename: string, arrayOf_Modifiers: string[][], arrayOf_Rules: rule_object[], }; @@ -86,7 +87,7 @@ export class KeylayoutToKmnConverter { * @param outputFilename the resulting keyman .kmn-file * @return null on success */ - async run(inputFilename: string, outputFilename: string): Promise { + async run(inputFilename: string, outputFilename: string = ""): Promise { //if (!inputFilename || !outputFilename) { if (!inputFilename) { @@ -99,15 +100,17 @@ export class KeylayoutToKmnConverter { return null; } - const outArray: convert_object = await this.convert(jsonO); + const outArray: convert_object = await this.convert(jsonO, outputFilename); if (!outArray) { throw new Error('Error while processing convert()'); return null; } - const out_text: boolean = this.write(outArray, outputFilename); - if (!out_text) { + //const out_text_ok: boolean = this.write(outArray, outputFilename); + const out_text_ok: boolean = this.write(outArray); + + if (!out_text_ok) { throw new Error('Error while processing write()'); return null; } @@ -146,7 +149,7 @@ export class KeylayoutToKmnConverter { * @param jsonObj containing filename, behaviour and rules of a json object * @return an convert_object containing all data ready to print out */ - public convert(jsonObj: any): convert_object { + public convert(jsonObj: any, outputfilename: string = ""): convert_object { const modifierBehavior: string[][] = []; // modifier for each behaviour const rule_object: rule_object[] = []; // an array of data for a kmn rule @@ -154,6 +157,7 @@ export class KeylayoutToKmnConverter { const data_object: convert_object = { keylayout_filename: "", + kmn_filename: "", arrayOf_Modifiers: [], arrayOf_Rules: [] }; @@ -161,6 +165,12 @@ export class KeylayoutToKmnConverter { // todo check tags if (jsonObj_any.hasOwnProperty("keyboard")) { + if ((outputfilename === "") || (outputfilename === null)) { + data_object.kmn_filename = (process.cwd() + "\\data\\" + data_object.keylayout_filename.substring(0, data_object.keylayout_filename.lastIndexOf(".")) + ".kmn"); + } + else + data_object.kmn_filename = outputfilename; + data_object.keylayout_filename = jsonObj_any.keyboard['@_name'] + ".keylayout"; data_object.arrayOf_Modifiers = modifierBehavior; // ukelele uses behaviours e.g. 18 modifiersCombinations in 8 KeyMapSelect(behaviors) data_object.arrayOf_Rules = rule_object; @@ -582,15 +592,9 @@ export class KeylayoutToKmnConverter { * @param outputfilename the file that will be written; if no outputfilename is given an outputfilename will be created from data_ukelele.keylayout_filename * @return true if data has been written; false if not */ - public write(data_ukelele: convert_object, outputfilename: string = ""): boolean { - let save_filename; - let data: string = "\n"; + public write(data_ukelele: convert_object): boolean { - if ((outputfilename === "") || (outputfilename === null)) { - save_filename = "data//" + data_ukelele.keylayout_filename.substring(0, data_ukelele.keylayout_filename.lastIndexOf(".")) + ".kmn"; - } - else - save_filename = outputfilename; + let data: string = "\n"; // add top part of kmn file: STORES data += this.writeData_Stores(data_ukelele); @@ -599,7 +603,7 @@ export class KeylayoutToKmnConverter { data += this.writeData_Rules(data_ukelele); try { - this.callbacks.fs.writeFileSync(save_filename, new TextEncoder().encode(data)); + this.callbacks.fs.writeFileSync(data_ukelele.kmn_filename, new TextEncoder().encode(data)); return true; } catch (err) { console.log('Error writing kmn file:' + err.message); @@ -679,7 +683,6 @@ export class KeylayoutToKmnConverter { add_modifier = String(modifier_state[i]) + " "; } kmn_modifier += kmn_ncaps + add_modifier; - //console.log("kmn_modifier ", kmn_modifier); } diff --git a/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts index 1fbb88b9c2a..e7da133e86e 100644 --- a/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts @@ -7,6 +7,7 @@ import { assert } from 'chai'; import { compilerTestCallbacks, compilerTestOptions } from './helpers/index.js'; import { KeylayoutToKmnConverter } from '../src/keylayout-to-kmn/keylayout-to-kmn-converter.js'; import { makePathToFixture } from './helpers/index.js'; +import { error } from 'console'; //----------------------------------------------------------------------------------------------------------------------- @@ -16,25 +17,24 @@ describe('KeylayoutToKmnConverter', function () { compilerTestCallbacks.clear(); }); - +// todo remove describe('RunOneFile ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const inputFilename = makePathToFixture('../data/XX.keylayout'); console.log(" inputFilename: ", inputFilename); - - const outputFilename = "data//" + inputFilename.substring(0, inputFilename.lastIndexOf(".")) + ".kmn"; - sut.run(inputFilename, outputFilename); + sut.run(inputFilename); assert.isTrue(true); ; }); +// todo remove describe('RunAllFiles ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); [ [makePathToFixture('../data/Italian.keylayout')], [makePathToFixture('../data/Italian_command.keylayout')], [makePathToFixture('../data/Swiss_French.keylayout')], - [makePathToFixture('../data/Spanish.keylayout')], + [makePathToFixture('../data/Spanish.keylayout')], [makePathToFixture('../data/Swiss_German.keylayout')], [makePathToFixture('../data/US.keylayout')], [makePathToFixture('../data/Polish.keylayout')], @@ -44,28 +44,12 @@ describe('KeylayoutToKmnConverter', function () { [makePathToFixture('../data/German_Standard.keylayout')], ].forEach(function (files_) { console.log(" inputFilename: ", files_[0]); - - const outputFilename = "data//" + files_[0].substring(0, files_[0].lastIndexOf(".")) + ".kmn"; - sut.run(files_[0], outputFilename); + sut.run(files_[0]); assert.isTrue(true); }); }); - //const inputFilename = makePathToFixture('../data/Italian.keylayout'); // OKOK - //const inputFilename = makePathToFixture('../data/Spanish.keylayout'); // OKOK - // no const inputFilename = makePathToFixture('../data/German_complete.keylayout'); // OK NO NCAPS SHIFT <-> SHIFT NCAPS - // no const inputFilename = makePathToFixture('../data/German_Standard.keylayout'); // OK NO NCAPS SHIFT <-> SHIFT NCAPS - // no const inputFilename = makePathToFixture('../data/Latin_American.keylayout'); // OKOK - //const inputFilename = makePathToFixture('../data/Swiss_French.keylayout'); // OKOK - //const inputFilename = makePathToFixture('../data/Swiss_German.keylayout'); // OKOK - //const inputFilename = makePathToFixture('../data/US.keylayout'); // OKOK - //const inputFilename = makePathToFixture('../data/Polish.keylayout'); // OKOK - //const inputFilename = makePathToFixture('../data/French.keylayout'); // OKOK - - - - describe("run() ", function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); @@ -90,7 +74,7 @@ describe('KeylayoutToKmnConverter', function () { assert.isTrue(threw); }); - it('run() should throw on null input file name', async function () { + it('run() should throw on null input file name and unknown output file name', async function () { let threw = false; try { await sut.run(null, "X"); @@ -100,7 +84,7 @@ describe('KeylayoutToKmnConverter', function () { assert.isTrue(threw); }); - it('run() should return on unavailable input file name and null output file name', async function () { + it('run() should throw on unavailable input file name and null output file name', async function () { const inputFilename = makePathToFixture('../data/Unavailable.keylayout'); let threw = false; try { @@ -108,12 +92,10 @@ describe('KeylayoutToKmnConverter', function () { } catch { threw = true; } - assert.isFalse(threw); + assert.isTrue(threw); }); it('run() should return on correct input file name and empty output file name ', async function () { - console.log(" ------------------",); - const inputFilename = makePathToFixture('../data/Italian_command.keylayout'); let threw = false; try { @@ -125,7 +107,6 @@ describe('KeylayoutToKmnConverter', function () { }); it('run() should return on correct input file name and null output file name', async function () { - console.log(" ------------------",); const inputFilename = makePathToFixture('../data/Italian_command.keylayout'); let threw = false; try { @@ -137,7 +118,6 @@ describe('KeylayoutToKmnConverter', function () { }); it('run() should return on correct input file name and given output file name ', async function () { - console.log(" ------------------",); const inputFilename = makePathToFixture('../data/Italian_command.keylayout'); const outputFilename = makePathToFixture('../../data/OutputName.kmn'); let threw = false; @@ -149,10 +129,21 @@ describe('KeylayoutToKmnConverter', function () { assert.isFalse(threw); }); - it('run() throw on incorrect input file extention ', async function () { - console.log(" ------------------",); + it('run() should throw on incorrect input file extention and output file extention', async function () { const inputFilename = makePathToFixture('../data/Italian_command.A'); - const outputFilename = makePathToFixture('../../data/OutputName.B'); + const outputFilename = makePathToFixture('../../data/OutputXName.B'); + let threw = false; + try { + await sut.run(inputFilename, outputFilename); + } catch { + threw = true; + } + assert.isTrue(threw); + }); + + it('run() return on correct input file extention and unsupperted output file extention', async function () { + const inputFilename = makePathToFixture('../data/Italian_command.keylayout'); + const outputFilename = makePathToFixture('../../data/OutputXName.B'); let threw = false; try { await sut.run(inputFilename, outputFilename); @@ -161,769 +152,769 @@ describe('KeylayoutToKmnConverter', function () { } assert.isFalse(threw); }); - + }); - - describe("read() ", function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const inputFilename_unavailable = makePathToFixture('X.keylayout'); - - it('read() should return filled array on correct input', async function () { - const inputFilename = makePathToFixture('../data/Italian.keylayout'); - const result = sut.read(inputFilename); - assert.isNotEmpty(result); - }); - - it('read() should return empty array on null input', async function () { - const result = sut.read(null); - assert.isEmpty(result); - }); - - it('read() should return empty array on empty input', async function () { - const result = sut.read(""); - assert.isEmpty(result); - }); - - it('read() should return empty array on space as input', async function () { - const result = sut.read(" "); - assert.isEmpty(result); - }); - - it('read() should return empty array on unavailable file name', async function () { - const result = sut.read(inputFilename_unavailable); - assert.isEmpty(result); - }); - - it('read() should return empty array on typo in path', async function () { - const result = sut.read('../data|Italian.keylayout'); - assert.isEmpty(result); - }); - }); - - describe("write() ", function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + + describe("read() ", function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const inputFilename_unavailable = makePathToFixture('X.keylayout'); + + it('read() should return filled array on correct input', async function () { const inputFilename = makePathToFixture('../data/Italian.keylayout'); - const read = sut.read(inputFilename); - const converted = sut.convert(read); - - // empty convert_object from unavailable file name - const inputFilename_unavailable = makePathToFixture('X.keylayout'); - const read_unavailable = sut.read(inputFilename_unavailable); - const converted_unavailable = sut.convert(read_unavailable); - - it('write() should return true (no error) if no inputfile', async function () { - const result = sut.write(converted_unavailable); - assert.isTrue(result); - }); - - it('write() should return true (no error) if written', async function () { - const result = sut.write(converted); - assert.isTrue(result); - }); + const result = sut.read(inputFilename); + assert.isNotEmpty(result); }); - - describe("convert() ", function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const inputFilename = makePathToFixture('../data/Italian.keylayout'); - const read = sut.read(inputFilename); - const converted = sut.convert(read); - - // empty convert_object from unavailable file name - const inputFilename_unavailable = makePathToFixture('X.keylayout'); - const read_unavailable = sut.read(inputFilename_unavailable); - const converted_unavailable = sut.convert(read_unavailable); - - // empty convert_object from empty filename - const inputFilename_empty = makePathToFixture(''); - const read_empty = sut.read(inputFilename_empty); - const converted_empty = sut.convert(read_empty); - - it('should return converted array on correct input', async function () { - // we use 'converted' from above - assert.isTrue(converted.arrayOf_Rules.length !== 0); - }); - - it('should return empty on empty input', async function () { - // we use 'converted_empty' from above - assert.isTrue((converted_empty.keylayout_filename === '' - && converted_empty.arrayOf_Modifiers.length === 0 - && converted_empty.arrayOf_Rules.length === 0)); - }); - - it('should return empty on only name as input', async function () { - // we use 'converted_unavailable' from above - assert.isTrue((converted_unavailable.keylayout_filename === '' - && converted_unavailable.arrayOf_Modifiers.length === 0 - && converted_unavailable.arrayOf_Rules.length === 0)); - }); - - it('should return empty on only modifiers as input', async function () { - const converted_mod = sut.convert({ - keylayout_filename: '', - arrayOf_Modifiers: [['caps'], ['Shift'], ['command']], - arrayOf_Rules: [] - }); - assert.isTrue((converted_mod.keylayout_filename === '' - && converted_mod.arrayOf_Modifiers.length === 0 - && converted_mod.arrayOf_Rules.length === 0)); - }); - - it('should return empty on only rules as input', async function () { - const converted_rule = sut.convert({ - keylayout_filename: '', - arrayOf_Modifiers: [], - arrayOf_Rules: [["C0", "", "", 0, 0, "", "", 0, 0, "CAPS", "K_A", "A"]] - }); - assert.isTrue((converted_rule.keylayout_filename === '' - && converted_rule.arrayOf_Modifiers.length === 0 - && converted_rule.arrayOf_Rules.length === 0)); - }); + + it('read() should return empty array on null input', async function () { + const result = sut.read(null); + assert.isEmpty(result); }); - - describe('create_kmn_modifier ', function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - - [ - ['anycontrol', true, 'NCAPS CTRL'], - ['shift?', true, 'NCAPS'], - ['?', true, 'NCAPS'], - ['?', false, ''], - ['caps', true, 'CAPS'], - ['', true, 'NCAPS'], - [' ', false, ''], - ['wrongModifierName', false, 'wrongModifierName'], - ['shift', false, 'SHIFT'], - ['shift command', true, 'NCAPS SHIFT command'], - ['rshift', true, 'NCAPS SHIFT'], - ['rshift', false, 'SHIFT'], - ['rightshift', true, 'NCAPS SHIFT'], - ['riGhtsHift', true, 'NCAPS SHIFT'], - ['LEFTCONTROL', true, 'NCAPS LCTRL'], - ['RCONTROL', true, 'NCAPS RCTRL'], - ['leftoption', true, 'NCAPS LALT'], - ['loption', true, 'NCAPS LALT'], - ].forEach(function (values) { - it(('should convert "' + values[0] + '"').padEnd(36, " ") + 'to "' + values[2] + '"', async function () { - const result = sut.create_kmn_modifier(values[0] as string, values[1] as boolean); - assert.equal(result, values[2]); - }); - }); + + it('read() should return empty array on empty input', async function () { + const result = sut.read(""); + assert.isEmpty(result); }); - - describe('getHexFromString ', function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - - [ - ['0009', '0009'], - ['000027', '001B'], - ['00027', '001B'], - ['0027', '001B'], - ['027', '001B'], - ['27', '001B'], - ['001C', '0NAN'], - ['0000', '0000'], - ['X', '0NAN'], - ['', '0000'], - [' ', '0000'], - [123, '007B'], - [null, '0000'], - ].forEach(function (values) { - it(('should convert "' + values[0] + '"').padEnd(25, " ") + 'to "' + values[1] + '"', async function () { - const result = sut.getHexFromString(values[0] as string); - assert.equal(result, values[1]); - }); - }); + + it('read() should return empty array on space as input', async function () { + const result = sut.read(" "); + assert.isEmpty(result); }); - - describe('convertToUnicodeCodePoint ', function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - - [ - ["􏘁", 'U+10F601'], - ["😁", 'U+1F601'], - [" ", 'U+0009'], - ["™", 'U+0099'], - ["ঙ", 'U+0999'], - ["香", 'U+9999'], - ["򙦙", 'U+99999'], - ["􏘁", 'U+10F601'], - ["😁", 'U+1F601'], - [" ", 'U+0009'], - ["c", 'U+0063'], - ["ϧ", 'U+03E7'], - ["✏", 'U+270F'], - ["𘚟", 'U+1869F'], - ['0000;', '0000;'], - ['X;', 'X;'], - ['123;', '123;'], - [';', ';'], - [' ;', ' ;'] - ].forEach(function (values) { - it(('should convert "' + values[0] + '"').padEnd(25, " ") + 'to "' + values[1] + '"', async function () { - const result = sut.convertToUnicodeCodePoint(values[0] as string); - assert.equal(result, values[1]); - }); - }); + + it('read() should return empty array on unavailable file name', async function () { + const result = sut.read(inputFilename_unavailable); + assert.isEmpty(result); }); - - describe("isAcceptableKeymanModifier ", function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - - [ - ["NCAPS", true], - ["NxCAPS", false], - ["SHIFT", true], - ["ALT", true], - ["RALT", true], - ["LALT", true], - ["CTRL", true], - ["LCTRL", true], - ["RCTRL", true], - ["LCTRL CAPS", true], - ["LCTRL X", false], - ["", true], - [null, false], - ].forEach(function (values) { - it(("isAcceptableKeymanModifier(" + values[0] + ")").padEnd(38, " ") + ' should return ' + values[1], async function () { - const result = sut.isAcceptableKeymanModifier(values[0] as string); - assert.equal(result, values[1]); - }); - }); + + it('read() should return empty array on typo in path', async function () { + const result = sut.read('../data|Italian.keylayout'); + assert.isEmpty(result); }); - - describe("map_UkeleleKC_To_VK ", function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - - [ - [0x00, "K_A"], - [0x31, "K_SPACE"], - [0x18, "K_EQUAL"], - [0x10, "K_Y"], - [0x18, "K_EQUAL"], - [0x21, "K_LBRKT"], - [0x999, ""], - [-1, ""], - [null, ""], - ].forEach(function (values) { - it(("map_UkeleleKC_To_VK(" + values[0] + ")").padEnd(26, " ") + "should return " + "'" + values[1] + "'", async function () { - const result = sut.map_UkeleleKC_To_VK(values[0] as number); - assert.equal(result, values[1]); - }); - }); + }); + + describe("write() ", function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const inputFilename = makePathToFixture('../data/Italian.keylayout'); + const read = sut.read(inputFilename); + const converted = sut.convert(read); + + // empty convert_object from unavailable file name + const inputFilename_unavailable = makePathToFixture('X.keylayout'); + const read_unavailable = sut.read(inputFilename_unavailable); + const converted_unavailable = sut.convert(read_unavailable); + + it('write() should return false if no inputfile', async function () { + const result = sut.write(converted_unavailable); + assert.isFalse(result); }); - - describe("checkIfCapsIsUsed ", function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - - it(("checkIfCapsIsUsed([['caps', 'xxx'], ['yyy']])").padEnd(45, " ") + " should return true", async function () { - const result = sut.checkIfCapsIsUsed([["caps", "xxx"], ["yyy"]]); - assert.isTrue(result); + + it('write() should return true (no error) if written', async function () { + const result = sut.write(converted); + assert.isTrue(result); + }); + }); + + describe("convert() ", function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const inputFilename = makePathToFixture('../data/Italian.keylayout'); + const read = sut.read(inputFilename); + const converted = sut.convert(read); + + // empty convert_object from unavailable file name + const inputFilename_unavailable = makePathToFixture('X.keylayout'); + const read_unavailable = sut.read(inputFilename_unavailable); + const converted_unavailable = sut.convert(read_unavailable); + + // empty convert_object from empty filename + const inputFilename_empty = makePathToFixture(''); + const read_empty = sut.read(inputFilename_empty); + const converted_empty = sut.convert(read_empty); + + it('should return converted array on correct input', async function () { + // we use 'converted' from above + assert.isTrue(converted.arrayOf_Rules.length !== 0); + }); + + it('should return empty on empty input', async function () { + // we use 'converted_empty' from above + assert.isTrue((converted_empty.keylayout_filename === '' + && converted_empty.arrayOf_Modifiers.length === 0 + && converted_empty.arrayOf_Rules.length === 0)); + }); + + it('should return empty on only name as input', async function () { + // we use 'converted_unavailable' from above + assert.isTrue((converted_unavailable.keylayout_filename === '' + && converted_unavailable.arrayOf_Modifiers.length === 0 + && converted_unavailable.arrayOf_Rules.length === 0)); + }); + + it('should return empty on only modifiers as input', async function () { + const converted_mod = sut.convert({ + keylayout_filename: '', + arrayOf_Modifiers: [['caps'], ['Shift'], ['command']], + arrayOf_Rules: [] + }); + assert.isTrue((converted_mod.keylayout_filename === '' + && converted_mod.arrayOf_Modifiers.length === 0 + && converted_mod.arrayOf_Rules.length === 0)); + }); + + it('should return empty on only rules as input', async function () { + const converted_rule = sut.convert({ + keylayout_filename: '', + arrayOf_Modifiers: [], + arrayOf_Rules: [["C0", "", "", 0, 0, "", "", 0, 0, "CAPS", "K_A", "A"]] + }); + assert.isTrue((converted_rule.keylayout_filename === '' + && converted_rule.arrayOf_Modifiers.length === 0 + && converted_rule.arrayOf_Rules.length === 0)); + }); + }); + + describe('create_kmn_modifier ', function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + + [ + ['anycontrol', true, 'NCAPS CTRL'], + ['shift?', true, 'NCAPS'], + ['?', true, 'NCAPS'], + ['?', false, ''], + ['caps', true, 'CAPS'], + ['', true, 'NCAPS'], + [' ', false, ''], + ['wrongModifierName', false, 'wrongModifierName'], + ['shift', false, 'SHIFT'], + ['shift command', true, 'NCAPS SHIFT command'], + ['rshift', true, 'NCAPS SHIFT'], + ['rshift', false, 'SHIFT'], + ['rightshift', true, 'NCAPS SHIFT'], + ['riGhtsHift', true, 'NCAPS SHIFT'], + ['LEFTCONTROL', true, 'NCAPS LCTRL'], + ['RCONTROL', true, 'NCAPS RCTRL'], + ['leftoption', true, 'NCAPS LALT'], + ['loption', true, 'NCAPS LALT'], + ].forEach(function (values) { + it(('should convert "' + values[0] + '"').padEnd(36, " ") + 'to "' + values[2] + '"', async function () { + const result = sut.create_kmn_modifier(values[0] as string, values[1] as boolean); + assert.equal(result, values[2]); }); - - it(("checkIfCapsIsUsed([['zzz', 'xxx'], ['yyy']])").padEnd(45, " ") + " should return false", async function () { - const result = sut.checkIfCapsIsUsed([["zzz", "xxx"], ["yyy"]]); - assert.isFalse(result); + }); + }); + + describe('getHexFromString ', function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + + [ + ['0009', '0009'], + ['000027', '001B'], + ['00027', '001B'], + ['0027', '001B'], + ['027', '001B'], + ['27', '001B'], + ['001C', '0NAN'], + ['0000', '0000'], + ['X', '0NAN'], + ['', '0000'], + [' ', '0000'], + [123, '007B'], + [null, '0000'], + ].forEach(function (values) { + it(('should convert "' + values[0] + '"').padEnd(25, " ") + 'to "' + values[1] + '"', async function () { + const result = sut.getHexFromString(values[0] as string); + assert.equal(result, values[1]); }); - it(("checkIfCapsIsUsed([['', ''], ['']])").padEnd(45, " ") + " should return false", async function () { - const result = sut.checkIfCapsIsUsed([["", ""], [""]]); - assert.isFalse(result); + }); + }); + + describe('convertToUnicodeCodePoint ', function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + + [ + ["􏘁", 'U+10F601'], + ["😁", 'U+1F601'], + [" ", 'U+0009'], + ["™", 'U+0099'], + ["ঙ", 'U+0999'], + ["香", 'U+9999'], + ["򙦙", 'U+99999'], + ["􏘁", 'U+10F601'], + ["😁", 'U+1F601'], + [" ", 'U+0009'], + ["c", 'U+0063'], + ["ϧ", 'U+03E7'], + ["✏", 'U+270F'], + ["𘚟", 'U+1869F'], + ['0000;', '0000;'], + ['X;', 'X;'], + ['123;', '123;'], + [';', ';'], + [' ;', ' ;'] + ].forEach(function (values) { + it(('should convert "' + values[0] + '"').padEnd(25, " ") + 'to "' + values[1] + '"', async function () { + const result = sut.convertToUnicodeCodePoint(values[0] as string); + assert.equal(result, values[1]); }); - it(("checkIfCapsIsUsed([null])").padEnd(45, " ") + " should return false", async function () { - const result = sut.checkIfCapsIsUsed([null]); - assert.isFalse(result); + }); + }); + + describe("isAcceptableKeymanModifier ", function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + + [ + ["NCAPS", true], + ["NxCAPS", false], + ["SHIFT", true], + ["ALT", true], + ["RALT", true], + ["LALT", true], + ["CTRL", true], + ["LCTRL", true], + ["RCTRL", true], + ["LCTRL CAPS", true], + ["LCTRL X", false], + ["", true], + [null, false], + ].forEach(function (values) { + it(("isAcceptableKeymanModifier(" + values[0] + ")").padEnd(38, " ") + ' should return ' + values[1], async function () { + const result = sut.isAcceptableKeymanModifier(values[0] as string); + assert.equal(result, values[1]); }); }); - - describe("get_Modifier_array__From__KeyModifier_array ", function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const inputFilename = makePathToFixture('../data/Italian.keylayout'); - const read = sut.read(inputFilename); - const converted = sut.convert(read); - - [[[['0', 0]], [['', 'shift? caps? ']]], - [[['0', 1]], [['anyShift caps?', 'shift? rightShift caps? ', 'shift? leftShift caps? ', 'shift leftShift caps ']]], - [[['0', 999]], [null]], - [[['999',]], [null]], - [[['0', -999]], [null]], - [[['0']], [null]], - ].forEach(function (values) { - it((values[1][0] !== null) ? - ("get_Modifier_array__From__KeyModifier_array(['" + values[0][0][0] + "', '" + values[0][0][1] + "'])").padEnd(68, " ") + " should return ['" + values[1][0][0] + "', '" + values[1][0][1] + "']" : - ("get_Modifier_array__From__KeyModifier_array(['" + values[0][0][0] + "', '" + values[0][0][1] + "'])").padEnd(68, " ") + " should return ['" + values[1][0] + "']", async function () { - const result = sut.get_Modifier_array__From__KeyModifier_array(converted.arrayOf_Modifiers, values[0]); - assert.deepStrictEqual(JSON.stringify(result), JSON.stringify(values[1])); - }); + }); + + describe("map_UkeleleKC_To_VK ", function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + + [ + [0x00, "K_A"], + [0x31, "K_SPACE"], + [0x18, "K_EQUAL"], + [0x10, "K_Y"], + [0x18, "K_EQUAL"], + [0x21, "K_LBRKT"], + [0x999, ""], + [-1, ""], + [null, ""], + ].forEach(function (values) { + it(("map_UkeleleKC_To_VK(" + values[0] + ")").padEnd(26, " ") + "should return " + "'" + values[1] + "'", async function () { + const result = sut.map_UkeleleKC_To_VK(values[0] as number); + assert.equal(result, values[1]); }); - - [[[[null]], [null]], - [[[undefined]], [null]], - [[[]], [null]], - ].forEach(function (values) { - it(("get_Modifier_array__From__KeyModifier_array([" + values[0][0] + "])").padEnd(68, " ") + " should return ['" + values[1][0] + "']", async function () { + }); + }); + + describe("checkIfCapsIsUsed ", function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + + it(("checkIfCapsIsUsed([['caps', 'xxx'], ['yyy']])").padEnd(45, " ") + " should return true", async function () { + const result = sut.checkIfCapsIsUsed([["caps", "xxx"], ["yyy"]]); + assert.isTrue(result); + }); + + it(("checkIfCapsIsUsed([['zzz', 'xxx'], ['yyy']])").padEnd(45, " ") + " should return false", async function () { + const result = sut.checkIfCapsIsUsed([["zzz", "xxx"], ["yyy"]]); + assert.isFalse(result); + }); + it(("checkIfCapsIsUsed([['', ''], ['']])").padEnd(45, " ") + " should return false", async function () { + const result = sut.checkIfCapsIsUsed([["", ""], [""]]); + assert.isFalse(result); + }); + it(("checkIfCapsIsUsed([null])").padEnd(45, " ") + " should return false", async function () { + const result = sut.checkIfCapsIsUsed([null]); + assert.isFalse(result); + }); + }); + + describe("get_Modifier_array__From__KeyModifier_array ", function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const inputFilename = makePathToFixture('../data/Italian.keylayout'); + const read = sut.read(inputFilename); + const converted = sut.convert(read); + + [[[['0', 0]], [['', 'shift? caps? ']]], + [[['0', 1]], [['anyShift caps?', 'shift? rightShift caps? ', 'shift? leftShift caps? ', 'shift leftShift caps ']]], + [[['0', 999]], [null]], + [[['999',]], [null]], + [[['0', -999]], [null]], + [[['0']], [null]], + ].forEach(function (values) { + it((values[1][0] !== null) ? + ("get_Modifier_array__From__KeyModifier_array(['" + values[0][0][0] + "', '" + values[0][0][1] + "'])").padEnd(68, " ") + " should return ['" + values[1][0][0] + "', '" + values[1][0][1] + "']" : + ("get_Modifier_array__From__KeyModifier_array(['" + values[0][0][0] + "', '" + values[0][0][1] + "'])").padEnd(68, " ") + " should return ['" + values[1][0] + "']", async function () { const result = sut.get_Modifier_array__From__KeyModifier_array(converted.arrayOf_Modifiers, values[0]); assert.deepStrictEqual(JSON.stringify(result), JSON.stringify(values[1])); }); - }); - }); - - describe("get_KeyModifier_array__From__ActionID ", function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const inputFilename = makePathToFixture('../data/Italian.keylayout'); - const read = sut.read(inputFilename); - - [ - ["a16", [['32', 3]]], - ["a19", [['45', 3]]], - ["a18", [['24', 0], ['24', 3]]], - ["unknown", []], - [undefined, []], - [null, []], - [" ", []], - ["", []], - ].forEach(function (values) { - - let outstring = "[ "; - for (let i = 0; i < values[1].length; i++) { - outstring = outstring + "[ '" + values[1][i][0] + "', " + values[1][i][1].toString() + "], "; - } - - it(("get_KeyModifier_array__From__ActionID('" + values[0] + "')").padEnd(57, " ") + ' should return ' + outstring.substring(0, outstring.lastIndexOf(']') + 2) + " ]", async function () { - const result = sut.get_KeyModifier_array__From__ActionID(read, String(values[0])); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); - }); - }); }); - - describe("get_ActionID__From__ActionNext ", function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const inputFilename = makePathToFixture('../data/Italian.keylayout'); - const read = sut.read(inputFilename); - - [ - ["none", ""], - ["a18", ""], - ["0", ""], - ["1", "a16"], - ["2", "a8"], - ["3", "a17"], - ["", ""], - [" ", ""], - ["99", ""], - [null, ""], - [undefined, ""], - ["unknown", ""], - ].forEach(function (values) { - it(("get_ActionID__From__ActionNext('" + values[0] + "')").padEnd(49, " ") + ' should return ' + "'" + values[1] + "'", async function () { - const result = sut.get_ActionID__From__ActionNext(read, String(values[0])); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); - }); + + [[[[null]], [null]], + [[[undefined]], [null]], + [[[]], [null]], + ].forEach(function (values) { + it(("get_Modifier_array__From__KeyModifier_array([" + values[0][0] + "])").padEnd(68, " ") + " should return ['" + values[1][0] + "']", async function () { + const result = sut.get_Modifier_array__From__KeyModifier_array(converted.arrayOf_Modifiers, values[0]); + assert.deepStrictEqual(JSON.stringify(result), JSON.stringify(values[1])); }); }); - - describe("get_ActionIndex__From__ActionId ", function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const inputFilename = makePathToFixture('../data/Italian.keylayout'); - const read = sut.read(inputFilename); - - [ - ["none", 0], - ["a16", 8], - ["a18", 10], - ["a19", 11], - ["0", 0], - ["", 0], - [" ", 0], - [null, 0], - [undefined, 0], - ["unknown", 0], - ].forEach(function (values) { - it(("get_ActionIndex__From__ActionId('" + values[0] + "')").padEnd(50, " ") + ' should return ' + values[1], async function () { - const result = sut.get_ActionIndex__From__ActionId(read, String(values[0])); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); - }); + }); + + describe("get_KeyModifier_array__From__ActionID ", function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const inputFilename = makePathToFixture('../data/Italian.keylayout'); + const read = sut.read(inputFilename); + + [ + ["a16", [['32', 3]]], + ["a19", [['45', 3]]], + ["a18", [['24', 0], ['24', 3]]], + ["unknown", []], + [undefined, []], + [null, []], + [" ", []], + ["", []], + ].forEach(function (values) { + + let outstring = "[ "; + for (let i = 0; i < values[1].length; i++) { + outstring = outstring + "[ '" + values[1][i][0] + "', " + values[1][i][1].toString() + "], "; + } + + it(("get_KeyModifier_array__From__ActionID('" + values[0] + "')").padEnd(57, " ") + ' should return ' + outstring.substring(0, outstring.lastIndexOf(']') + 2) + " ]", async function () { + const result = sut.get_KeyModifier_array__From__ActionID(read, String(values[0])); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); - - describe("get_Output__From__ActionId_None ", function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const inputFilename = makePathToFixture('../data/Italian.keylayout'); - const read = sut.read(inputFilename); - - [["a14", "u"], + }); + + describe("get_ActionID__From__ActionNext ", function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const inputFilename = makePathToFixture('../data/Italian.keylayout'); + const read = sut.read(inputFilename); + + [ + ["none", ""], + ["a18", ""], + ["0", ""], + ["1", "a16"], + ["2", "a8"], + ["3", "a17"], ["", ""], [" ", ""], - ["a18", undefined], + ["99", ""], + [null, ""], + [undefined, ""], ["unknown", ""], - ].forEach(function (values) { - it( - ("get_Output__From__ActionId_None('" + values[0] + "')").padEnd(56, " ") + ' should return ' + "'" + values[1] + "'", async function () { - const result = sut.get_Output__From__ActionId_None(read, String(values[0])); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); - }); + ].forEach(function (values) { + it(("get_ActionID__From__ActionNext('" + values[0] + "')").padEnd(49, " ") + ' should return ' + "'" + values[1] + "'", async function () { + const result = sut.get_ActionID__From__ActionNext(read, String(values[0])); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); - - [[null, ""], - [undefined, ""], - [99, ""], - ].forEach(function (values) { - it(("get_Output__From__ActionId_None('" + values[0] + "')").padEnd(56, " ") + ' should return ' + values[1], async function () { + }); + }); + + describe("get_ActionIndex__From__ActionId ", function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const inputFilename = makePathToFixture('../data/Italian.keylayout'); + const read = sut.read(inputFilename); + + [ + ["none", 0], + ["a16", 8], + ["a18", 10], + ["a19", 11], + ["0", 0], + ["", 0], + [" ", 0], + [null, 0], + [undefined, 0], + ["unknown", 0], + ].forEach(function (values) { + it(("get_ActionIndex__From__ActionId('" + values[0] + "')").padEnd(50, " ") + ' should return ' + values[1], async function () { + const result = sut.get_ActionIndex__From__ActionId(read, String(values[0])); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); + }); + + describe("get_Output__From__ActionId_None ", function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const inputFilename = makePathToFixture('../data/Italian.keylayout'); + const read = sut.read(inputFilename); + + [["a14", "u"], + ["", ""], + [" ", ""], + ["a18", undefined], + ["unknown", ""], + ].forEach(function (values) { + it( + ("get_Output__From__ActionId_None('" + values[0] + "')").padEnd(56, " ") + ' should return ' + "'" + values[1] + "'", async function () { const result = sut.get_Output__From__ActionId_None(read, String(values[0])); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); - }); }); - - describe("get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array ", function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const inputFilename = makePathToFixture('../data/Italian.keylayout'); - const read = sut.read(inputFilename); - - const b1_keycode_arr = [ - ['49', 'K_SPACE', 'a0', '0', 'ˆ'], - ['49', 'K_SPACE', 'a0', '1', 'ˆ'], - ['49', 'K_SPACE', 'a0', '2', 'ˆ'], - ['6', 'K_Z', 'a0', '4', 'ˆ'], - ['25', 'K_9', 'a0', '4', 'ˆ'], - ['43', 'K_COMMA', 'a0', '4', 'ˆ'], - ['49', 'K_SPACE', 'a0', '7', 'ˆ'], - ['0', 'K_A', 'a1', '1', 'Â'], - ['0', 'K_A', 'a1', '2', 'Â'], - ['14', 'K_E', 'a10', '0', 'ê'], - ['34', 'K_I', 'a11', '0', 'î'], - ['31', 'K_O', 'a13', '0', 'ô'], - ['32', 'K_U', 'a14', '0', 'û'], - ['14', 'K_E', 'a2', '1', 'Ê'], - ['14', 'K_E', 'a2', '2', 'Ê'], - ['34', 'K_I', 'a3', '1', 'Î'], - ['34', 'K_I', 'a3', '2', 'Î'], - ['31', 'K_O', 'a5', '1', 'Ô'], - ['31', 'K_O', 'a5', '2', 'Ô'], - ['32', 'K_U', 'a6', '1', 'Û'], - ['32', 'K_U', 'a6', '2', 'Û'], - ['0', 'K_A', 'a9', '0', 'â'] - ]; - const b1_modifierKey_arr = [ - ['K_SPACE', 'a0', '0', 'NCAPS', 'ˆ'], - ['K_SPACE', 'a0', '1', 'SHIFT NCAPS', 'ˆ'], - ['K_SPACE', 'a0', '1', 'SHIFT CAPS', 'ˆ'], - ['K_SPACE', 'a0', '2', 'CAPS', 'ˆ'], - ['K_Z', 'a0', '4', 'SHIFT NCAPS RALT', 'ˆ'], - ['K_9', 'a0', '4', 'SHIFT NCAPS RALT', 'ˆ'], - ['K_COMMA', 'a0', '4', 'SHIFT NCAPS RALT', 'ˆ'], - ['K_SPACE', 'a0', '7', 'NCAPS CTRL', 'ˆ'], - ['K_SPACE', 'a0', '7', 'NCAPS RALT CTRL', 'ˆ'], - ['K_A', 'a1', '1', 'SHIFT NCAPS', 'Â'], - ['K_A', 'a1', '1', 'SHIFT CAPS', 'Â'], - ['K_A', 'a1', '2', 'CAPS', 'Â'], - ['K_E', 'a10', '0', 'NCAPS', 'ê'], - ['K_I', 'a11', '0', 'NCAPS', 'î'], - ['K_O', 'a13', '0', 'NCAPS', 'ô'], - ['K_U', 'a14', '0', 'NCAPS', 'û'], - ['K_E', 'a2', '1', 'SHIFT NCAPS', 'Ê'], - ['K_E', 'a2', '1', 'SHIFT CAPS', 'Ê'], - ['K_E', 'a2', '2', 'CAPS', 'Ê'], - ['K_I', 'a3', '1', 'SHIFT NCAPS', 'Î'], - ['K_I', 'a3', '1', 'SHIFT CAPS', 'Î'], - ['K_I', 'a3', '2', 'CAPS', 'Î'], - ['K_O', 'a5', '1', 'SHIFT NCAPS', 'Ô'], - ['K_O', 'a5', '1', 'SHIFT CAPS', 'Ô'], - ['K_O', 'a5', '2', 'CAPS', 'Ô'], - ['K_U', 'a6', '1', 'SHIFT NCAPS', 'Û'], - ['K_U', 'a6', '1', 'SHIFT CAPS', 'Û'], - ['K_U', 'a6', '2', 'CAPS', 'Û'], - ['K_A', 'a9', '0', 'NCAPS', 'â'] - ]; - - // isCaps_used === true; input defined - [[b1_keycode_arr, b1_modifierKey_arr], - [[['49', 'K_SPACE', 'a0', '0', 'ˆ']], [['K_SPACE', 'a0', '0', 'NCAPS', 'ˆ']]], - [[['49', 'K_SPACE', 'a0', '0', '']], [['K_SPACE', 'a0', '0', 'NCAPS', '']]], - [[['49', 'K_SPACE', 'a0', '', 'ˆ']], [['K_SPACE', 'a0', '', 'NCAPS', 'ˆ']]], - [[['49', 'K_SPACE', '', '0', 'ˆ']], [['K_SPACE', '', '0', 'NCAPS', 'ˆ']]], - [[['49', '', 'a0', '0', 'ˆ']], [['', 'a0', '0', 'NCAPS', 'ˆ']]], - [[['', 'K_SPACE', 'a0', '0', 'ˆ']], [['K_SPACE', 'a0', '0', 'NCAPS', 'ˆ']]], - [[['', 'K_SPACE', 'a0', '0', 'ˆ']], [['K_SPACE', 'a0', '0', 'NCAPS', 'ˆ']]], - [[['', '', '', '', '']], [['', '', '', 'NCAPS', '']]], - ].forEach(function (values) { - - const isCaps_used = true; - const string_in = "get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(['" + "', '" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "', '" + values[0][0][3] + "', '" + values[0][0][4] + "'])"; - const string_out = "['" + "', '" + values[1][0][0] + "', '" + values[1][0][1] + "', '" + values[1][0][2] + "', '" + values[1][0][3] + "', '" + values[1][0][4] + "']"; - - it((JSON.stringify(values[1]).length > 60) ? 'an array of objects should return an array of objectss' : - string_in.padEnd(74, " ") + ' should return ' + string_out, async function () { - const result = sut.get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(read, values[0], isCaps_used); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); - }); + + [[null, ""], + [undefined, ""], + [99, ""], + ].forEach(function (values) { + it(("get_Output__From__ActionId_None('" + values[0] + "')").padEnd(56, " ") + ' should return ' + values[1], async function () { + const result = sut.get_Output__From__ActionId_None(read, String(values[0])); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); - - // isCaps_used === false; input defined - [[[['49', 'K_SPACE', 'a0', '0', 'ˆ']], [['K_SPACE', 'a0', '0', '', 'ˆ']]], - [[['49', 'K_SPACE', 'a0', '0', '']], [['K_SPACE', 'a0', '0', '', '']]], - [[['', 'K_SPACE', 'a0', '0', 'ˆ']], [['K_SPACE', 'a0', '0', '', 'ˆ']]], - [[['', '', '', '', '']], [['', '', '', '', '']]], - ].forEach(function (values) { - - const isCaps_used = false; - const string_in = "get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(['" + "', '" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "', '" + values[0][0][3] + "', '" + values[0][0][4] + "'])"; - const string_out = "['" + "', '" + values[1][0][0] + "', '" + values[1][0][1] + "', '" + values[1][0][2] + "', '" + values[1][0][3] + "', '" + values[1][0][4] + "']"; - - it(string_in.padEnd(74, " ") + ' should return ' + string_out, async function () { + }); + }); + + describe("get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array ", function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const inputFilename = makePathToFixture('../data/Italian.keylayout'); + const read = sut.read(inputFilename); + + const b1_keycode_arr = [ + ['49', 'K_SPACE', 'a0', '0', 'ˆ'], + ['49', 'K_SPACE', 'a0', '1', 'ˆ'], + ['49', 'K_SPACE', 'a0', '2', 'ˆ'], + ['6', 'K_Z', 'a0', '4', 'ˆ'], + ['25', 'K_9', 'a0', '4', 'ˆ'], + ['43', 'K_COMMA', 'a0', '4', 'ˆ'], + ['49', 'K_SPACE', 'a0', '7', 'ˆ'], + ['0', 'K_A', 'a1', '1', 'Â'], + ['0', 'K_A', 'a1', '2', 'Â'], + ['14', 'K_E', 'a10', '0', 'ê'], + ['34', 'K_I', 'a11', '0', 'î'], + ['31', 'K_O', 'a13', '0', 'ô'], + ['32', 'K_U', 'a14', '0', 'û'], + ['14', 'K_E', 'a2', '1', 'Ê'], + ['14', 'K_E', 'a2', '2', 'Ê'], + ['34', 'K_I', 'a3', '1', 'Î'], + ['34', 'K_I', 'a3', '2', 'Î'], + ['31', 'K_O', 'a5', '1', 'Ô'], + ['31', 'K_O', 'a5', '2', 'Ô'], + ['32', 'K_U', 'a6', '1', 'Û'], + ['32', 'K_U', 'a6', '2', 'Û'], + ['0', 'K_A', 'a9', '0', 'â'] + ]; + const b1_modifierKey_arr = [ + ['K_SPACE', 'a0', '0', 'NCAPS', 'ˆ'], + ['K_SPACE', 'a0', '1', 'SHIFT NCAPS', 'ˆ'], + ['K_SPACE', 'a0', '1', 'SHIFT CAPS', 'ˆ'], + ['K_SPACE', 'a0', '2', 'CAPS', 'ˆ'], + ['K_Z', 'a0', '4', 'SHIFT NCAPS RALT', 'ˆ'], + ['K_9', 'a0', '4', 'SHIFT NCAPS RALT', 'ˆ'], + ['K_COMMA', 'a0', '4', 'SHIFT NCAPS RALT', 'ˆ'], + ['K_SPACE', 'a0', '7', 'NCAPS CTRL', 'ˆ'], + ['K_SPACE', 'a0', '7', 'NCAPS RALT CTRL', 'ˆ'], + ['K_A', 'a1', '1', 'SHIFT NCAPS', 'Â'], + ['K_A', 'a1', '1', 'SHIFT CAPS', 'Â'], + ['K_A', 'a1', '2', 'CAPS', 'Â'], + ['K_E', 'a10', '0', 'NCAPS', 'ê'], + ['K_I', 'a11', '0', 'NCAPS', 'î'], + ['K_O', 'a13', '0', 'NCAPS', 'ô'], + ['K_U', 'a14', '0', 'NCAPS', 'û'], + ['K_E', 'a2', '1', 'SHIFT NCAPS', 'Ê'], + ['K_E', 'a2', '1', 'SHIFT CAPS', 'Ê'], + ['K_E', 'a2', '2', 'CAPS', 'Ê'], + ['K_I', 'a3', '1', 'SHIFT NCAPS', 'Î'], + ['K_I', 'a3', '1', 'SHIFT CAPS', 'Î'], + ['K_I', 'a3', '2', 'CAPS', 'Î'], + ['K_O', 'a5', '1', 'SHIFT NCAPS', 'Ô'], + ['K_O', 'a5', '1', 'SHIFT CAPS', 'Ô'], + ['K_O', 'a5', '2', 'CAPS', 'Ô'], + ['K_U', 'a6', '1', 'SHIFT NCAPS', 'Û'], + ['K_U', 'a6', '1', 'SHIFT CAPS', 'Û'], + ['K_U', 'a6', '2', 'CAPS', 'Û'], + ['K_A', 'a9', '0', 'NCAPS', 'â'] + ]; + + // isCaps_used === true; input defined + [[b1_keycode_arr, b1_modifierKey_arr], + [[['49', 'K_SPACE', 'a0', '0', 'ˆ']], [['K_SPACE', 'a0', '0', 'NCAPS', 'ˆ']]], + [[['49', 'K_SPACE', 'a0', '0', '']], [['K_SPACE', 'a0', '0', 'NCAPS', '']]], + [[['49', 'K_SPACE', 'a0', '', 'ˆ']], [['K_SPACE', 'a0', '', 'NCAPS', 'ˆ']]], + [[['49', 'K_SPACE', '', '0', 'ˆ']], [['K_SPACE', '', '0', 'NCAPS', 'ˆ']]], + [[['49', '', 'a0', '0', 'ˆ']], [['', 'a0', '0', 'NCAPS', 'ˆ']]], + [[['', 'K_SPACE', 'a0', '0', 'ˆ']], [['K_SPACE', 'a0', '0', 'NCAPS', 'ˆ']]], + [[['', 'K_SPACE', 'a0', '0', 'ˆ']], [['K_SPACE', 'a0', '0', 'NCAPS', 'ˆ']]], + [[['', '', '', '', '']], [['', '', '', 'NCAPS', '']]], + ].forEach(function (values) { + + const isCaps_used = true; + const string_in = "get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(['" + "', '" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "', '" + values[0][0][3] + "', '" + values[0][0][4] + "'])"; + const string_out = "['" + "', '" + values[1][0][0] + "', '" + values[1][0][1] + "', '" + values[1][0][2] + "', '" + values[1][0][3] + "', '" + values[1][0][4] + "']"; + + it((JSON.stringify(values[1]).length > 60) ? 'an array of objects should return an array of objectss' : + string_in.padEnd(74, " ") + ' should return ' + string_out, async function () { const result = sut.get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(read, values[0], isCaps_used); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); - }); - - // isCaps_used === true; input undefined/null/empty - [[[], []], - [undefined, []], - [null, []], - ].forEach(function (values) { - const isCaps = true; - it(("get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array([" + values[0] + "])").padEnd(74, " ") + ' should return ' + "[" + values[1] + "]", async function () { - const result = sut.get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(read, values[0], isCaps); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); - }); - }); }); - - describe("writeData_Stores() ", function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const inputFilename = makePathToFixture('../data/Italian.keylayout'); - const read = sut.read(inputFilename); - const converted = sut.convert(read); - - // empty convert_object from unavailable file name - const inputFilename_unavailable = makePathToFixture('X.keylayout'); - const read_unavailable = sut.read(inputFilename_unavailable); - const converted_unavailable = sut.convert(read_unavailable); - - // empty convert_object from empty filename - const inputFilename_empty = makePathToFixture(''); - const read_empty = sut.read(inputFilename_empty); - const converted_empty = sut.convert(read_empty); - - const out_expected_first: string = - "c ......................................................................\n" - + "c ......................................................................\n" - + "c Keyman keyboard generated by kmn-convert\n" - + "c from Ukelele file: "; - - const out_expected_last: string = - "\n" - + "c ......................................................................\n" - + "c ......................................................................\n" - + "\n" - + "store(&VERSION) '10.0'\n" - + "store(&TARGETS) 'any'\n" - + "store(&KEYBOARDVERSION) '1.0'\n" - + "store(©RIGHT) '© 2024 SIL International'\n" - + "\n" - + "begin Unicode > use(main)\n\n" - + "group(main) using keys\n\n" - + "\n"; - - it(('writeData_Stores should return store text with filename ').padEnd(62, " ") + 'on correct input', async function () { - const written_correctName = sut.writeData_Stores(converted); - assert.equal(written_correctName, (out_expected_first + converted.keylayout_filename + out_expected_last)); - }); - - it(('writeData_Stores should return store text without filename ').padEnd(62, " ") + 'on empty input', async function () { - const written_emptyName = sut.writeData_Stores(converted_empty); - assert.equal(written_emptyName, (out_expected_first + out_expected_last)); - }); - - it(('writeData_Stores should return store text without filename ').padEnd(62, " ") + 'on only filename as input', async function () { - const written_onlyName = sut.writeData_Stores(converted_unavailable); - assert.equal(written_onlyName, (out_expected_first + converted_unavailable.keylayout_filename + out_expected_last)); + + // isCaps_used === false; input defined + [[[['49', 'K_SPACE', 'a0', '0', 'ˆ']], [['K_SPACE', 'a0', '0', '', 'ˆ']]], + [[['49', 'K_SPACE', 'a0', '0', '']], [['K_SPACE', 'a0', '0', '', '']]], + [[['', 'K_SPACE', 'a0', '0', 'ˆ']], [['K_SPACE', 'a0', '0', '', 'ˆ']]], + [[['', '', '', '', '']], [['', '', '', '', '']]], + ].forEach(function (values) { + + const isCaps_used = false; + const string_in = "get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(['" + "', '" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "', '" + values[0][0][3] + "', '" + values[0][0][4] + "'])"; + const string_out = "['" + "', '" + values[1][0][0] + "', '" + values[1][0][1] + "', '" + values[1][0][2] + "', '" + values[1][0][3] + "', '" + values[1][0][4] + "']"; + + it(string_in.padEnd(74, " ") + ' should return ' + string_out, async function () { + const result = sut.get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(read, values[0], isCaps_used); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); - - describe("get_ActionStateOutput_array__From__ActionState ", function () { - - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const inputFilename = makePathToFixture('../data/Italian.keylayout'); - const read = sut.read(inputFilename); - - [["1", [ - ['a0', '1', 'ˆ'], - ['a1', '1', 'Â'], - ['a10', '1', 'ê'], - ['a11', '1', 'î'], - ['a13', '1', 'ô'], - ['a14', '1', 'û'], - ['a2', '1', 'Ê'], - ['a3', '1', 'Î'], - ['a5', '1', 'Ô'], - ['a6', '1', 'Û'], - ['a9', '1', 'â']],], - ["2", [ - ['a0', '2', '`'], - ['a1', '2', 'À'], - ['a10', '2', 'è'], - ['a11', '2', 'ì'], - ['a13', '2', 'ò'], - ['a14', '2', 'ù'], - ['a2', '2', 'È'], - ['a3', '2', 'Ì'], - ['a5', '2', 'Ò'], - ['a6', '2', 'Ù'], - ['a9', '2', 'à']],], - ["789", [],], - ["", [],], - [" ", [],], - [123, [],], - [null, [],], - [undefined, [],], - ].forEach(function (values) { - it((JSON.stringify(values[1]).length > 30) ? - ("get_ActionStateOutput_array__From__ActionState('" + values[0] + "')").padEnd(60, " ") + ' should return an array of objects' : - ("get_ActionStateOutput_array__From__ActionState('" + values[0] + "')").padEnd(60, " ") + ' should return ' + "'" + JSON.stringify(values[1]) + "'", async function () { - const result = sut.get_ActionStateOutput_array__From__ActionState(read, String(values[0])); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); - }); + + // isCaps_used === true; input undefined/null/empty + [[[], []], + [undefined, []], + [null, []], + ].forEach(function (values) { + const isCaps = true; + it(("get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array([" + values[0] + "])").padEnd(74, " ") + ' should return ' + "[" + values[1] + "]", async function () { + const result = sut.get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(read, values[0], isCaps); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); - - describe("get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput ", function () { - - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const inputFilename = makePathToFixture('../data/Italian.keylayout'); - const read = sut.read(inputFilename); - const converted = sut.convert(read); - - [ - ["a1", "A", true, [ - ['a1', 'A', 'a1', '1', 'K_A', 'SHIFT NCAPS'], - ['a1', 'A', 'a1', '1', 'K_A', 'SHIFT CAPS'], - ['a1', 'A', 'a1', '2', 'K_A', 'CAPS']] - ], - ["a1", "A", false, [ - ['a1', 'A', 'a1', '1', 'K_A', 'SHIFT'], - ['a1', 'A', 'a1', '1', 'K_A', 'SHIFT CAPS'], - ['a1', 'A', 'a1', '2', 'K_A', 'CAPS']] - ], - ["a9", "a", true, [['a9', 'a', 'a9', '0', 'K_A', 'NCAPS']]], - ["a9", "a", false, [['a9', 'a', 'a9', '0', 'K_A', '']]], - ["a9", "a", , [['a9', 'a', 'a9', '0', 'K_A', '']]], - ["a9", "", true, [["a9", "", "a9", "0", "K_A", "NCAPS"]]], - ["a9", "", false, [["a9", "", "a9", "0", "K_A", ""]]], - ["", "a", true, []], - ["", "a", false, []], - ["", "", , []], - - ].forEach(function (values) { - it((JSON.stringify(values[3]).length > 35) ? - ("get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput('" + values[0] + "', '" + values[1] + "', " + values[2] + ")").padEnd(67, " ") + ' should return an array of objects' : - ("get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput('" + values[0] + "', '" + values[1] + "', " + values[2] + ")").padEnd(67, " ") + ' should return ' + "'" + JSON.stringify(values[3]) + "'", async function () { - const result = sut.get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput(read, converted.arrayOf_Modifiers, String(values[0]), String(values[1]), Boolean(values[2])); - assert.equal(JSON.stringify(result), JSON.stringify(values[3])); - }); - }); + }); + + describe("writeData_Stores() ", function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const inputFilename = makePathToFixture('../data/Italian.keylayout'); + const read = sut.read(inputFilename); + const converted = sut.convert(read); + + // empty convert_object from unavailable file name + const inputFilename_unavailable = makePathToFixture('X.keylayout'); + const read_unavailable = sut.read(inputFilename_unavailable); + const converted_unavailable = sut.convert(read_unavailable); + + // empty convert_object from empty filename + const inputFilename_empty = makePathToFixture(''); + const read_empty = sut.read(inputFilename_empty); + const converted_empty = sut.convert(read_empty); + + const out_expected_first: string = + "c ......................................................................\n" + + "c ......................................................................\n" + + "c Keyman keyboard generated by kmn-convert\n" + + "c from Ukelele file: "; + + const out_expected_last: string = + "\n" + + "c ......................................................................\n" + + "c ......................................................................\n" + + "\n" + + "store(&VERSION) '10.0'\n" + + "store(&TARGETS) 'any'\n" + + "store(&KEYBOARDVERSION) '1.0'\n" + + "store(©RIGHT) '© 2024 SIL International'\n" + + "\n" + + "begin Unicode > use(main)\n\n" + + "group(main) using keys\n\n" + + "\n"; + + it(('writeData_Stores should return store text with filename ').padEnd(62, " ") + 'on correct input', async function () { + const written_correctName = sut.writeData_Stores(converted); + assert.equal(written_correctName, (out_expected_first + converted.keylayout_filename + out_expected_last)); }); - - describe("get_KeyActionOutput_array__From__ActionStateOutput_array ", function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const inputFilename = makePathToFixture('../data/Italian.keylayout'); - const read = sut.read(inputFilename); - - const b6_actionId_arr = [ - ['a0', '1', 'ˆ'], - ['a1', '1', 'Â'], - ['a10', '1', 'ê'], - ['a11', '1', 'î'], - ['a13', '1', 'ô'], - ['a14', '1', 'û'], - ['a2', '1', 'Ê'], - ['a3', '1', 'Î'], - ['a5', '1', 'Ô'], - ['a6', '1', 'Û'], - ['a9', '1', 'â'] - ]; - const b1_keycode_arr = [ - ['49', 'K_SPACE', 'a0', '0', 'ˆ'], - ['49', 'K_SPACE', 'a0', '1', 'ˆ'], - ['49', 'K_SPACE', 'a0', '2', 'ˆ'], - ['6', 'K_Z', 'a0', '4', 'ˆ'], - ['25', 'K_9', 'a0', '4', 'ˆ'], - ['43', 'K_COMMA', 'a0', '4', 'ˆ'], - ['49', 'K_SPACE', 'a0', '7', 'ˆ'], - ['0', 'K_A', 'a1', '1', 'Â'], - ['0', 'K_A', 'a1', '2', 'Â'], - ['14', 'K_E', 'a10', '0', 'ê'], - ['34', 'K_I', 'a11', '0', 'î'], - ['31', 'K_O', 'a13', '0', 'ô'], - ['32', 'K_U', 'a14', '0', 'û'], - ['14', 'K_E', 'a2', '1', 'Ê'], - ['14', 'K_E', 'a2', '2', 'Ê'], - ['34', 'K_I', 'a3', '1', 'Î'], - ['34', 'K_I', 'a3', '2', 'Î'], - ['31', 'K_O', 'a5', '1', 'Ô'], - ['31', 'K_O', 'a5', '2', 'Ô'], - ['32', 'K_U', 'a6', '1', 'Û'], - ['32', 'K_U', 'a6', '2', 'Û'], - ['0', 'K_A', 'a9', '0', 'â'] - ]; - - [[b6_actionId_arr, b1_keycode_arr], - ].forEach(function (values) { - it(("get_KeyActionOutput_array__From__ActionStateOutput_array([['" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "'],..])").padEnd(73, " ") + ' should return an array of objects', async function () { - const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0]); + + it(('writeData_Stores should return store text without filename ').padEnd(62, " ") + 'on empty input', async function () { + const written_emptyName = sut.writeData_Stores(converted_empty); + assert.equal(written_emptyName, (out_expected_first + out_expected_last)); + }); + + it(('writeData_Stores should return store text without filename ').padEnd(62, " ") + 'on only filename as input', async function () { + const written_onlyName = sut.writeData_Stores(converted_unavailable); + assert.equal(written_onlyName, (out_expected_first + converted_unavailable.keylayout_filename + out_expected_last)); + }); + }); + + describe("get_ActionStateOutput_array__From__ActionState ", function () { + + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const inputFilename = makePathToFixture('../data/Italian.keylayout'); + const read = sut.read(inputFilename); + + [["1", [ + ['a0', '1', 'ˆ'], + ['a1', '1', 'Â'], + ['a10', '1', 'ê'], + ['a11', '1', 'î'], + ['a13', '1', 'ô'], + ['a14', '1', 'û'], + ['a2', '1', 'Ê'], + ['a3', '1', 'Î'], + ['a5', '1', 'Ô'], + ['a6', '1', 'Û'], + ['a9', '1', 'â']],], + ["2", [ + ['a0', '2', '`'], + ['a1', '2', 'À'], + ['a10', '2', 'è'], + ['a11', '2', 'ì'], + ['a13', '2', 'ò'], + ['a14', '2', 'ù'], + ['a2', '2', 'È'], + ['a3', '2', 'Ì'], + ['a5', '2', 'Ò'], + ['a6', '2', 'Ù'], + ['a9', '2', 'à']],], + ["789", [],], + ["", [],], + [" ", [],], + [123, [],], + [null, [],], + [undefined, [],], + ].forEach(function (values) { + it((JSON.stringify(values[1]).length > 30) ? + ("get_ActionStateOutput_array__From__ActionState('" + values[0] + "')").padEnd(60, " ") + ' should return an array of objects' : + ("get_ActionStateOutput_array__From__ActionState('" + values[0] + "')").padEnd(60, " ") + ' should return ' + "'" + JSON.stringify(values[1]) + "'", async function () { + const result = sut.get_ActionStateOutput_array__From__ActionState(read, String(values[0])); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); - }); - - //----------------- - const oneEntryResult = [ - ["49", "K_SPACE", "a0", "0", "ˆ"], - ["49", "K_SPACE", "a0", "1", "ˆ"], - ["49", "K_SPACE", "a0", "2", "ˆ"], - ["6", "K_Z", "a0", "4", "ˆ"], - ["25", "K_9", "a0", "4", "ˆ"], - ["43", "K_COMMA", "a0", "4", "ˆ"], - ["49", "K_SPACE", "a0", "7", "ˆ"] - ]; - const oneEntryResultNoOutput = [ - ["49", "K_SPACE", "a0", "0", ""], - ["49", "K_SPACE", "a0", "1", ""], - ["49", "K_SPACE", "a0", "2", ""], - ["6", "K_Z", "a0", "4", ""], - ["25", "K_9", "a0", "4", ""], - ["43", "K_COMMA", "a0", "4", ""], - ["49", "K_SPACE", "a0", "7", ""] - ]; - - [[[['a0', '1', 'ˆ']], oneEntryResult], - [[['a0', '1', '']], oneEntryResultNoOutput], - [[['a0', '', 'ˆ']], oneEntryResult], - ].forEach(function (values) { - it(("get_KeyActionOutput_array__From__ActionStateOutput_array(['" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "'])").padEnd(73, " ") + ' should return an array of objects', async function () { - const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0]); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); + + describe("get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput ", function () { + + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const inputFilename = makePathToFixture('../data/Italian.keylayout'); + const read = sut.read(inputFilename); + const converted = sut.convert(read); + + [ + ["a1", "A", true, [ + ['a1', 'A', 'a1', '1', 'K_A', 'SHIFT NCAPS'], + ['a1', 'A', 'a1', '1', 'K_A', 'SHIFT CAPS'], + ['a1', 'A', 'a1', '2', 'K_A', 'CAPS']] + ], + ["a1", "A", false, [ + ['a1', 'A', 'a1', '1', 'K_A', 'SHIFT'], + ['a1', 'A', 'a1', '1', 'K_A', 'SHIFT CAPS'], + ['a1', 'A', 'a1', '2', 'K_A', 'CAPS']] + ], + ["a9", "a", true, [['a9', 'a', 'a9', '0', 'K_A', 'NCAPS']]], + ["a9", "a", false, [['a9', 'a', 'a9', '0', 'K_A', '']]], + ["a9", "a", , [['a9', 'a', 'a9', '0', 'K_A', '']]], + ["a9", "", true, [["a9", "", "a9", "0", "K_A", "NCAPS"]]], + ["a9", "", false, [["a9", "", "a9", "0", "K_A", ""]]], + ["", "a", true, []], + ["", "a", false, []], + ["", "", , []], + + ].forEach(function (values) { + it((JSON.stringify(values[3]).length > 35) ? + ("get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput('" + values[0] + "', '" + values[1] + "', " + values[2] + ")").padEnd(67, " ") + ' should return an array of objects' : + ("get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput('" + values[0] + "', '" + values[1] + "', " + values[2] + ")").padEnd(67, " ") + ' should return ' + "'" + JSON.stringify(values[3]) + "'", async function () { + const result = sut.get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput(read, converted.arrayOf_Modifiers, String(values[0]), String(values[1]), Boolean(values[2])); + assert.equal(JSON.stringify(result), JSON.stringify(values[3])); }); + }); + }); + + describe("get_KeyActionOutput_array__From__ActionStateOutput_array ", function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const inputFilename = makePathToFixture('../data/Italian.keylayout'); + const read = sut.read(inputFilename); + + const b6_actionId_arr = [ + ['a0', '1', 'ˆ'], + ['a1', '1', 'Â'], + ['a10', '1', 'ê'], + ['a11', '1', 'î'], + ['a13', '1', 'ô'], + ['a14', '1', 'û'], + ['a2', '1', 'Ê'], + ['a3', '1', 'Î'], + ['a5', '1', 'Ô'], + ['a6', '1', 'Û'], + ['a9', '1', 'â'] + ]; + const b1_keycode_arr = [ + ['49', 'K_SPACE', 'a0', '0', 'ˆ'], + ['49', 'K_SPACE', 'a0', '1', 'ˆ'], + ['49', 'K_SPACE', 'a0', '2', 'ˆ'], + ['6', 'K_Z', 'a0', '4', 'ˆ'], + ['25', 'K_9', 'a0', '4', 'ˆ'], + ['43', 'K_COMMA', 'a0', '4', 'ˆ'], + ['49', 'K_SPACE', 'a0', '7', 'ˆ'], + ['0', 'K_A', 'a1', '1', 'Â'], + ['0', 'K_A', 'a1', '2', 'Â'], + ['14', 'K_E', 'a10', '0', 'ê'], + ['34', 'K_I', 'a11', '0', 'î'], + ['31', 'K_O', 'a13', '0', 'ô'], + ['32', 'K_U', 'a14', '0', 'û'], + ['14', 'K_E', 'a2', '1', 'Ê'], + ['14', 'K_E', 'a2', '2', 'Ê'], + ['34', 'K_I', 'a3', '1', 'Î'], + ['34', 'K_I', 'a3', '2', 'Î'], + ['31', 'K_O', 'a5', '1', 'Ô'], + ['31', 'K_O', 'a5', '2', 'Ô'], + ['32', 'K_U', 'a6', '1', 'Û'], + ['32', 'K_U', 'a6', '2', 'Û'], + ['0', 'K_A', 'a9', '0', 'â'] + ]; + + [[b6_actionId_arr, b1_keycode_arr], + ].forEach(function (values) { + it(("get_KeyActionOutput_array__From__ActionStateOutput_array([['" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "'],..])").padEnd(73, " ") + ' should return an array of objects', async function () { + const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0]); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); - - //----------------- - [[[['', '1', 'ˆ']], []], - [[['', '', '']], []], - [[[' ', ' ', '']], []], - ].forEach(function (values) { - it(("get_KeyActionOutput_array__From__ActionStateOutput_array(['" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "'])").padEnd(73, " ") + ' should return ' + "'[" + values[1] + "]'", async function () { - const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0]); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); - }); + }); + + //----------------- + const oneEntryResult = [ + ["49", "K_SPACE", "a0", "0", "ˆ"], + ["49", "K_SPACE", "a0", "1", "ˆ"], + ["49", "K_SPACE", "a0", "2", "ˆ"], + ["6", "K_Z", "a0", "4", "ˆ"], + ["25", "K_9", "a0", "4", "ˆ"], + ["43", "K_COMMA", "a0", "4", "ˆ"], + ["49", "K_SPACE", "a0", "7", "ˆ"] + ]; + const oneEntryResultNoOutput = [ + ["49", "K_SPACE", "a0", "0", ""], + ["49", "K_SPACE", "a0", "1", ""], + ["49", "K_SPACE", "a0", "2", ""], + ["6", "K_Z", "a0", "4", ""], + ["25", "K_9", "a0", "4", ""], + ["43", "K_COMMA", "a0", "4", ""], + ["49", "K_SPACE", "a0", "7", ""] + ]; + + [[[['a0', '1', 'ˆ']], oneEntryResult], + [[['a0', '1', '']], oneEntryResultNoOutput], + [[['a0', '', 'ˆ']], oneEntryResult], + ].forEach(function (values) { + it(("get_KeyActionOutput_array__From__ActionStateOutput_array(['" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "'])").padEnd(73, " ") + ' should return an array of objects', async function () { + const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0]); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); - - //----------------- - [[[], []], - [undefined, []], - [null, []], - ].forEach(function (values) { - it(("get_KeyActionOutput_array__From__ActionStateOutput_array(" + values[0] + ")").padEnd(73, " ") + ' should return ' + "'[" + values[1] + "]'", async function () { - const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0]); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); - }); + }); + + //----------------- + [[[['', '1', 'ˆ']], []], + [[['', '', '']], []], + [[[' ', ' ', '']], []], + ].forEach(function (values) { + it(("get_KeyActionOutput_array__From__ActionStateOutput_array(['" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "'])").padEnd(73, " ") + ' should return ' + "'[" + values[1] + "]'", async function () { + const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0]); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); - + + //----------------- + [[[], []], + [undefined, []], + [null, []], + ].forEach(function (values) { + it(("get_KeyActionOutput_array__From__ActionStateOutput_array(" + values[0] + ")").padEnd(73, " ") + ' should return ' + "'[" + values[1] + "]'", async function () { + const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0]); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); + }); + }); From c9570b501156e11a1e3d9993e5825d9882825fa8 Mon Sep 17 00:00:00 2001 From: Sabine Date: Thu, 27 Mar 2025 18:25:14 +0100 Subject: [PATCH 073/251] feat(developer): order of modifiers, final check prevent unwritten rule in rare cases --- .../data/German_Standard.keylayout | 2783 ++++++++++++++++ .../data/German_complete.keylayout | 2785 +++++++++++++++++ .../keylayout-to-kmn-converter.ts | 296 +- .../test/test-keylayout-to-kmn-converter.ts | 60 +- 4 files changed, 5703 insertions(+), 221 deletions(-) create mode 100644 developer/src/kmc-convert/data/German_Standard.keylayout create mode 100644 developer/src/kmc-convert/data/German_complete.keylayout diff --git a/developer/src/kmc-convert/data/German_Standard.keylayout b/developer/src/kmc-convert/data/German_Standard.keylayout new file mode 100644 index 00000000000..921b7e8c60b --- /dev/null +++ b/developer/src/kmc-convert/data/German_Standard.keylayout @@ -0,0 +1,2783 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/data/German_complete.keylayout b/developer/src/kmc-convert/data/German_complete.keylayout new file mode 100644 index 00000000000..d4f3ff6581c --- /dev/null +++ b/developer/src/kmc-convert/data/German_complete.keylayout @@ -0,0 +1,2785 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 697fda11847..8f026c9a4bb 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -18,8 +18,7 @@ import { ConverterToKmnArtifacts } from "../converter-artifacts.js"; // what if nodes in keylayout file do not exist/ diff name keyboard <-> keyboardA -> new issue // --------------------------------------------------- -// add all tests again& remove data files test -// SHIFT NCAPS <-> NCAPS SHIFT +// add all tests again remove data files test import { XMLParser } from 'fast-xml-parser'; // for reading an xml file @@ -27,7 +26,7 @@ import { readFileSync } from 'fs'; import { util } from '@keymanapp/common-types'; import boxXmlArray = util.boxXmlArray; -function boxArrays(source: any) { +function boxArray(source: any) { boxXmlArray(source.layouts, 'layout'); boxXmlArray(source.terminators, 'when'); boxXmlArray(source, 'keyMapSet'); @@ -70,7 +69,6 @@ export interface convert_object { arrayOf_Rules: rule_object[], }; - export class KeylayoutToKmnConverter { static readonly INPUT_FILE_EXTENSION = '.keylayout'; @@ -89,7 +87,6 @@ export class KeylayoutToKmnConverter { */ async run(inputFilename: string, outputFilename: string = ""): Promise { - //if (!inputFilename || !outputFilename) { if (!inputFilename) { throw new Error('Invalid parameters'); } @@ -107,7 +104,6 @@ export class KeylayoutToKmnConverter { return null; } - //const out_text_ok: boolean = this.write(outArray, outputFilename); const out_text_ok: boolean = this.write(outArray); if (!out_text_ok) { @@ -136,7 +132,7 @@ export class KeylayoutToKmnConverter { xmlFile = readFileSync((process.cwd() + "\\data" + filename.substring(filename.lastIndexOf("\\"))).replace(" ", ""), 'utf8'); const parser = new XMLParser(options); jsonObj = parser.parse(xmlFile); // get plain Object - boxArrays(jsonObj.keyboard); // jsonObj now contains arrays; no single fields + boxArray(jsonObj.keyboard); // jsonObj now contains arrays; no single fields } catch (err) { console.log(err.message); @@ -162,16 +158,19 @@ export class KeylayoutToKmnConverter { arrayOf_Rules: [] }; - // todo check tags + // ToDo in a new PR: check tags if (jsonObj_any.hasOwnProperty("keyboard")) { + data_object.keylayout_filename = jsonObj_any.keyboard['@_name'] + ".keylayout"; + if ((outputfilename === "") || (outputfilename === null)) { data_object.kmn_filename = (process.cwd() + "\\data\\" + data_object.keylayout_filename.substring(0, data_object.keylayout_filename.lastIndexOf(".")) + ".kmn"); } else data_object.kmn_filename = outputfilename; - data_object.keylayout_filename = jsonObj_any.keyboard['@_name'] + ".keylayout"; + console.log("RUN kmc convert - input file: ", (process.cwd() + "\\data\\" + data_object.keylayout_filename), " --> output file: ", data_object.kmn_filename); + data_object.arrayOf_Modifiers = modifierBehavior; // ukelele uses behaviours e.g. 18 modifiersCombinations in 8 KeyMapSelect(behaviors) data_object.arrayOf_Rules = rule_object; @@ -220,8 +219,8 @@ export class KeylayoutToKmnConverter { // ...............e. g. ............................................................................... // ............................................................................................................................... - if ((jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] !== undefined) && (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] !== "") - ) { + if ((jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] !== undefined) + && (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] !== "")) { // loop behaviours for (let l = 0; l < data_ukelele.arrayOf_Modifiers[i].length; l++) { @@ -244,11 +243,7 @@ export class KeylayoutToKmnConverter { /* key */ this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), /* output */ new TextEncoder().encode(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output']), ); - - // ToDo "undefined" or undefined ???? - // if (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] !== "") { object_array.push(rule_obj); - // } } } @@ -292,29 +287,28 @@ export class KeylayoutToKmnConverter { /* key */ b1_modifierKey_arr[m][4], /* output */ new TextEncoder().encode(outputchar) ); - // ToDo "undefined" or undefined ???? - // if (b1_modifierKey_arr[n4][4] !== "undefined") { - object_array.push(rule_obj); + if ((outputchar !== undefined) && (outputchar !== "undefined") && (outputchar !== "")) { + object_array.push(rule_obj); + } } } - } - // ............................................................................................................................... - // case C2: action + none + next ................................................................................................. - // ...............e. g. ............................................................................ - // replace state x with all rules that result in 14 ( ............................................................................ + // replace state x with all rules that result in 14 ( for action id a18 ...................................................................................................................... - for (let l = 0; l < jsonObj.keyboard.actions.action[b1_actionIndex].when.length; l++) { - if ((jsonObj.keyboard.actions.action[b1_actionIndex].when[l]['@_state'] === "none") // find "none" - && (jsonObj.keyboard.actions.action[b1_actionIndex].when[l]['@_next'] !== undefined)) { // find "next" + // with action_id from above loop all 'action' and search for a state(none)-next-pair ............................................................................................................ + // e.g. in Block 5: find for action id a18 ...................................................................................................................... + for (let l = 0; l < jsonObj.keyboard.actions.action[b1_actionIndex].when.length; l++) { + if ((jsonObj.keyboard.actions.action[b1_actionIndex].when[l]['@_state'] === "none") // find "none" + && (jsonObj.keyboard.actions.action[b1_actionIndex].when[l]['@_next'] !== undefined)) { // find "next" // Data of Block Nr 5 ..................................................................................................................................................................... // of this state(none)-next-pair get value of next (next="1") ............................................................................................................................. @@ -340,14 +334,14 @@ export class KeylayoutToKmnConverter { // create array[Keycode,Keyname,action id,actionIndex,output] and array[Keyname,action id,behaviour,modifier,output] ...................................................................... /* eg: ['0','K_A','a9','0','â'] */ const b1_keycode_arr: string[][] = this.get_KeyActionOutput_array__From__ActionStateOutput_array(jsonObj, b6_actionId_arr); /* eg: ['K_A','a9','0','NCAPS','â']*/ const b1_modifierKey_arr: string[][] = this.get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(jsonObj, b1_keycode_arr, isCapsused); - // ....................................................................................................................................................................................... + // ....................................................................................................................................................................................... - for (let n1 = 0; n1 < b4_deadkeyModifier_arr.length; n1++) { - for (let n2 = 0; n2 < b4_deadkeyModifier_arr[n1].length; n2++) { - for (let n3 = 0; n3 < b4_deadkey_arr.length; n3++) { - for (let n4 = 0; n4 < b1_modifierKey_arr.length; n4++) { + for (let n1 = 0; n1 < b4_deadkeyModifier_arr.length; n1++) { + for (let n2 = 0; n2 < b4_deadkeyModifier_arr[n1].length; n2++) { + for (let n3 = 0; n3 < b4_deadkey_arr.length; n3++) { + for (let n4 = 0; n4 < b1_modifierKey_arr.length; n4++) { - rule_obj = new Rules( + rule_obj = new Rules( /* rule_type */ "C2", /* modifier_prev_deadkey*/ "", @@ -363,36 +357,35 @@ export class KeylayoutToKmnConverter { /* modifier_key*/ b1_modifierKey_arr[n4][3], /* key */ b1_modifierKey_arr[n4][0], /* output */ new TextEncoder().encode(b1_modifierKey_arr[n4][4]), - ); - // ToDo "undefined" or undefined ???? - if (b1_modifierKey_arr[n4][4] !== "undefined") { - //if (b1_modifierKey_arr[n4][4] !== undefined) { - // this.writeDatasetSingle(rule_obj) - object_array.push(rule_obj); + ); + if ((b1_modifierKey_arr[n4][4] !== undefined) + && (b1_modifierKey_arr[n4][4] !== "undefined") + && (b1_modifierKey_arr[n4][4] !== "")) { + object_array.push(rule_obj); + } } } } } } } - } - // ............................................................................................................................... - // case C3: action + state Nr + Next ............................................................................................. - // ...............e. g. ................................................................................ - // replace state x with all rules that result in 1 ( ................................................................................ + // replace state x with all rules that result in 1 ( for action id a16 ............................................................................................................................. - for (let l = 0; l < jsonObj.keyboard.actions.action[b1_actionIndex].when.length; l++) { - if ((jsonObj.keyboard.actions.action[b1_actionIndex].when[l]['@_state'] !== "none") - && (jsonObj.keyboard.actions.action[b1_actionIndex].when[l]['@_next'] !== undefined)) { + // with action_id from above loop all 'action' and search for a state-next-pair ................................................................................................................... + // e.g. in Block 5: find for action id a16 ............................................................................................................................. + for (let l = 0; l < jsonObj.keyboard.actions.action[b1_actionIndex].when.length; l++) { + if ((jsonObj.keyboard.actions.action[b1_actionIndex].when[l]['@_state'] !== "none") + && (jsonObj.keyboard.actions.action[b1_actionIndex].when[l]['@_next'] !== undefined)) { // Data of Block Nr 5 ........................................................................................................................................................................ // of this state-next-pair get value of next (next="1") and state="3" ........................................................................................................................ @@ -427,17 +420,17 @@ export class KeylayoutToKmnConverter { // create array[Keycode,Keyname,action id,actionIndex,output] and array[Keyname,action id,behaviour,modifier,output] ......................................................................... /* eg: ['49','K_SPACE','a0','0','Â'] */ const b1_keycode_arr: string[][] = this.get_KeyActionOutput_array__From__ActionStateOutput_array(jsonObj, b6_actionId_arr); /* eg: ['K_SPACE','a0','0','NCAPS','Â'] */ const b1_modifierKey_arr: string[][] = this.get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(jsonObj, b1_keycode_arr, isCapsused); - // ........................................................................................................................................................................................... + // ........................................................................................................................................................................................... - for (let n1 = 0; n1 < b2_prev_deadkeyModifier_arr.length; n1++) { - for (let n2 = 0; n2 < b2_prev_deadkeyModifier_arr[n1].length; n2++) { - for (let n3 = 0; n3 < b2_prev_deadkey_arr.length; n3++) { - for (let n4 = 0; n4 < b4_deadkeyModifier_arr.length; n4++) { - for (let n5 = 0; n5 < b4_deadkeyModifier_arr[n4].length; n5++) { - for (let n6 = 0; n6 < b4_deadkey_arr.length; n6++) { - for (let n7 = 0; n7 < b1_modifierKey_arr.length; n7++) { + for (let n1 = 0; n1 < b2_prev_deadkeyModifier_arr.length; n1++) { + for (let n2 = 0; n2 < b2_prev_deadkeyModifier_arr[n1].length; n2++) { + for (let n3 = 0; n3 < b2_prev_deadkey_arr.length; n3++) { + for (let n4 = 0; n4 < b4_deadkeyModifier_arr.length; n4++) { + for (let n5 = 0; n5 < b4_deadkeyModifier_arr[n4].length; n5++) { + for (let n6 = 0; n6 < b4_deadkey_arr.length; n6++) { + for (let n7 = 0; n7 < b1_modifierKey_arr.length; n7++) { - rule_obj = new Rules( + rule_obj = new Rules( /* rule_type */ "C3", /* modifier_prev_deadkey*/ this.create_kmn_modifier(b2_prev_deadkeyModifier_arr[n1][n2], isCapsused), /* prev_deadkey */ this.map_UkeleleKC_To_VK(Number(b2_prev_deadkey_arr[n3][0])), @@ -452,11 +445,13 @@ export class KeylayoutToKmnConverter { /* modifier_key*/ b1_modifierKey_arr[n7][3], /* key */ b1_modifierKey_arr[n7][0], /* output */ new TextEncoder().encode(b1_modifierKey_arr[n7][4]), - ); + ); - // ToDo "undefined" or undefined ???? - if (b1_modifierKey_arr[n7][4] !== undefined) { - object_array.push(rule_obj); + if ((b1_modifierKey_arr[n7][4] !== undefined) + && (b1_modifierKey_arr[n7][4] !== "undefined") + && (b1_modifierKey_arr[n7][4] !== "")) { + object_array.push(rule_obj); + } } } } @@ -473,17 +468,15 @@ export class KeylayoutToKmnConverter { "\"\" :", jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]); continue; - } } } data_ukelele.arrayOf_Rules = object_array; - return this.reviewRuleInputData(data_ukelele); } /** - * @brief member function to review data in array of Rules[] of data_ukelele: remove duplicate rules and mark first occurace of a rule in object_array + * @brief member function to review data in array of Rules[] of data_ukelele: remove duplicate rules and mark first occurance of a rule in object_array * @param data_ukelele: an object containing the name of the input file, an array of behaviours and an array of Rules * @return an object containing the name of the input file, an array of behaviours and the revised array of Rules[] */ @@ -606,7 +599,7 @@ export class KeylayoutToKmnConverter { this.callbacks.fs.writeFileSync(data_ukelele.kmn_filename, new TextEncoder().encode(data)); return true; } catch (err) { - console.log('Error writing kmn file:' + err.message); + console.log('ERROR writing kmn file:' + err.message); return false; } } @@ -626,16 +619,22 @@ export class KeylayoutToKmnConverter { for (let i = 0; i < modifier_state.length; i++) { + if (isCAPSused && (keylayout_modifier).toUpperCase().indexOf("CAPS?") > 0) { + kmn_ncaps = " NCAPS "; + } + if (isCAPSused && (keylayout_modifier).toUpperCase().indexOf("CAPS") === -1) { kmn_ncaps = " NCAPS "; } - // if we find a modifier containing a '?' e.g. SHIFT? => SHIFT occurs 0 or 1 times so it is not necessary. If it is not necessary we don't write this modifier + // if we find a modifier containing a '?' e.g. SHIFT? => SHIFT occurs 0 or 1 times so it is not necessary. + // If it is not necessary we don't write this modifier if (modifier_state[i].toUpperCase().includes('?') && (!modifier_state[i].toUpperCase().includes('CAPS?'))) { add_modifier = ""; } - // if we find caps? => caps is not necessary. If caps is not necessary and isCAPSused we need to write out NCAPS. + // if we find caps? => caps is not necessary. + // If caps is not necessary and isCAPSused we need to write out NCAPS. else if (isCAPSused && (modifier_state[i].toUpperCase().includes('CAPS?'))) { add_modifier = "NCAPS "; } @@ -683,26 +682,14 @@ export class KeylayoutToKmnConverter { add_modifier = String(modifier_state[i]) + " "; } kmn_modifier += kmn_ncaps + add_modifier; - } - // remove duplicate and empty entries and make sure NCAPS is at the beginning const duplicate_modifier_array: string[] = kmn_modifier.split(" ").filter(item => item); + const unique_modifier: string[] = duplicate_modifier_array.filter(function (item, pos, self) { - /* - console.log("kmn_modifier ", kmn_modifier); - console.log("duplicate_modifier_array ", duplicate_modifier_array); - - - if (kmn_modifier.indexOf("NCAPS") !== -1) { - duplicate_modifier_array.unshift("NCAPS"); - } - console.log(" duplicate_modifier_array", duplicate_modifier_array); - - - */ return self.indexOf(item) === pos; }); + return unique_modifier.flat().toString().replace(/,/g, " "); } @@ -749,7 +736,7 @@ export class KeylayoutToKmnConverter { } /** - * @brief member function to reviev rules for acceptable modifiers, duplicate or ambiguous rules and return an array containing possible warnings + * @brief member function to review rules for acceptable modifiers, duplicate or ambiguous rules and return an array containing possible warnings * definition of comparisons e.g. 1-1, 2-4, 6-6 * see https://docs.google.com/document/d/12J3NGO6RxIthCpZDTR8FYSRjiMgXJDLwPY2z9xqKzJ0/edit?tab=t.0#heading=h.pcz8rjyrl5ug * @param rule : rule_object[] - an array of all rules @@ -779,13 +766,13 @@ export class KeylayoutToKmnConverter { else if (rule[index].rule_type === "C3") { if (!this.isAcceptableKeymanModifier(rule[index].modifier_prev_deadkey)) { - warningTextArray[2] = "unavailable modifier : "; + warningTextArray[0] = "unavailable modifier : "; } if (!this.isAcceptableKeymanModifier(rule[index].modifier_deadkey)) { warningTextArray[1] = "unavailable modifier : "; } if (!this.isAcceptableKeymanModifier(rule[index].modifier_key)) { - warningTextArray[0] = "unavailable modifier : "; + warningTextArray[2] = "unavailable modifier : "; } } @@ -840,7 +827,7 @@ export class KeylayoutToKmnConverter { + " " + amb_4_1[0].prev_deadkey + "] > dk(C" - + amb_4_1[0].unique_prev_deadkey + + amb_2_1[0].id_deadkey + ") "); } @@ -851,7 +838,7 @@ export class KeylayoutToKmnConverter { + " " + amb_2_1[0].deadkey + "] > dk(A" - + amb_2_1[0].unique_deadkey + + amb_2_1[0].id_deadkey + ") "); } @@ -950,7 +937,7 @@ export class KeylayoutToKmnConverter { if (amb_3_3.length > 0) { warningTextArray[2] = warningTextArray[2] - + ("ambiguous rule: earlier: dk(C" + + ("ambiguous rule: earlier: dk(A" + amb_3_3[0].id_deadkey + ") + [" + amb_3_3[0].modifier_key @@ -963,7 +950,7 @@ export class KeylayoutToKmnConverter { if (dup_3_3.length > 0) { warningTextArray[2] = warningTextArray[2] - + ("duplicate rule: earlier: dk(C" + + ("duplicate rule: earlier: dk(A" + dup_3_3[0].id_deadkey + ") + [" + dup_3_3[0].modifier_key @@ -1014,7 +1001,7 @@ export class KeylayoutToKmnConverter { && new TextDecoder().decode(curr.output) === new TextDecoder().decode(rule[index].output) ); - // 4-4 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > 'dk(C1)' + // 4-4 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(C1) const amb_4_4 = rule.filter((curr, idx) => curr.rule_type === "C3" && curr.modifier_prev_deadkey === rule[index].modifier_prev_deadkey @@ -1056,12 +1043,10 @@ export class KeylayoutToKmnConverter { // 6-6 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'B' const amb_6_6 = rule.filter((curr, idx) => (curr.rule_type === "C3") - && curr.id_deadkey === rule[index].id_deadkey - && rule[index].unique_prev_deadkey !== 0 + && curr.id_prev_deadkey === rule[index].id_prev_deadkey && curr.modifier_key === rule[index].modifier_key && curr.key === rule[index].key && (new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output)) - && idx < index ); @@ -1186,15 +1171,30 @@ export class KeylayoutToKmnConverter { + "\' "); } } + // In rare cases a rule might not be written out therefore we need to inform the user + const extra_warning = "PLEASE CHECK THE FOLLOWING RULE AS IT WILL NOT BE WRITTEN ! "; if (warningTextArray[0] !== "") { warningTextArray[0] = "c WARNING: " + warningTextArray[0] + "here: "; + + if ((warningTextArray[0].indexOf("earlier:") > 0) && (warningTextArray[0].indexOf("later:") > 0)) { + warningTextArray[0] = warningTextArray[0] + extra_warning; + } } if (warningTextArray[1] !== "") { warningTextArray[1] = "c WARNING: " + warningTextArray[1] + "here: "; + + if ((warningTextArray[1].indexOf("earlier:") > 0) && (warningTextArray[1].indexOf("later:") > 0)) { + warningTextArray[1] = warningTextArray[1] + extra_warning; + } } + if (warningTextArray[2] !== "") { warningTextArray[2] = "c WARNING: " + warningTextArray[2] + "here: "; + + if ((warningTextArray[2].indexOf("earlier:") > 0) && (warningTextArray[2].indexOf("later:") > 0)) { + warningTextArray[2] = warningTextArray[2] + extra_warning; + } } return warningTextArray; @@ -1275,8 +1275,6 @@ export class KeylayoutToKmnConverter { return unique; }, []); - // this.writeDataset(unique_data_Rules); - //................................................ C0 C1 ................................................................ for (let k = 0; k < unique_data_Rules.length; k++) { @@ -1538,7 +1536,6 @@ export class KeylayoutToKmnConverter { const num_str = instr.substring(instr.indexOf("#") + 1, instr.length - 1); return ("U+" + this.getHexFromString(num_str.slice(-num_length)).padStart(4, "0")); } - else return instr; } @@ -1794,91 +1791,6 @@ export class KeylayoutToKmnConverter { } return mapIndexArray_2D; } - - // console log all entries C3 TODO remove - public writeDataset(dataRules: rule_object[]) { - for (let i = 0; i < dataRules.length; i++) { - //if (dataRules[i].key === "") { - if ((i > 2934) && (i < 2939)) { - // if (true ) { - - - console.log("dataRules[i].outp ", "..", dataRules[i].output, "..", dataRules[i].output === new TextEncoder().encode("")); - - console.log("dataRules ", i, - - dataRules[i].rule_type !== "" ? dataRules[i].rule_type : "--".padEnd(4, " "), - - "| ", (dataRules[i].modifier_prev_deadkey !== "" ? dataRules[i].modifier_prev_deadkey.padEnd(33, " ") : "--".padEnd(33, " ")), - (dataRules[i].prev_deadkey !== "" ? dataRules[i].prev_deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), - (dataRules[i].id_prev_deadkey !== 0 ? ("dk(A" + String(dataRules[i].id_prev_deadkey) + ")").padEnd(11, " ") : "--".padEnd(11, " ")), - (dataRules[i].unique_prev_deadkey !== 0 ? ("unique(A" + String(dataRules[i].unique_prev_deadkey) + ")").padEnd(11, " ") : "--".padEnd(11, " ")), - - (dataRules[i].modifier_deadkey !== "" ? dataRules[i].modifier_deadkey.padEnd(30, " ") : "--".padEnd(30, " ")), - (dataRules[i].deadkey !== "" ? dataRules[i].deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), - dataRules[i].rule_type === "C2" ? (dataRules[i].unique_deadkey !== 0 ? ("unique(C" + String(dataRules[i].unique_deadkey) + ")").padEnd(9, " ") : "--".padEnd(9, " ")) : ((dataRules[i].unique_prev_deadkey !== 0 ? ("unique(B" + dataRules[i].id_deadkey + ")").padEnd(9, " ") : "--".padEnd(9, " "))), - - dataRules[i].id_prev_deadkey, - dataRules[i].id_deadkey, - - "| ", (dataRules[i].modifier_key !== "" ? dataRules[i].modifier_key.padEnd(40, " ") : "--".padEnd(40, " ")), - (dataRules[i].key !== "" ? dataRules[i].key.padEnd(8, " ") : "--".padEnd(8, " ")), - (new TextDecoder().decode(dataRules[i].output) !== "" ? new TextDecoder().decode(dataRules[i].output).padEnd(10, " ") : ("--" + dataRules[i].output) + "--"), - - "| °°"); - } - } - - } - // TODO remove - public writeDatasetSingle(dataRules: rule_object) { - - console.log("dataRules[i].key ", "..", dataRules.key, "..", dataRules.key === ""); - - console.log("dataRules ", - dataRules.rule_type !== "" ? dataRules.rule_type : "--".padEnd(4, " "), - - "| ", (dataRules.modifier_prev_deadkey !== "" ? dataRules.modifier_prev_deadkey.padEnd(33, " ") : "--".padEnd(33, " ")), - (dataRules.prev_deadkey !== "" ? dataRules.prev_deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), - (dataRules.id_prev_deadkey !== 0 ? ("dk(A" + String(dataRules.id_prev_deadkey) + ")").padEnd(11, " ") : "--".padEnd(11, " ")), - (dataRules.unique_prev_deadkey !== 0 ? ("unique(A" + String(dataRules.unique_prev_deadkey) + ")").padEnd(11, " ") : "--".padEnd(11, " ")), - - (dataRules.modifier_deadkey !== "" ? dataRules.modifier_deadkey.padEnd(30, " ") : "--".padEnd(30, " ")), - (dataRules.deadkey !== "" ? dataRules.deadkey.padEnd(8, " ") : "--".padEnd(8, " ")), - dataRules.rule_type === "C2" ? (dataRules.unique_deadkey !== 0 ? ("unique(C" + String(dataRules.unique_deadkey) + ")").padEnd(9, " ") : "--".padEnd(9, " ")) : ((dataRules.unique_prev_deadkey !== 0 ? ("unique(B" + dataRules.id_deadkey + ")").padEnd(9, " ") : "--".padEnd(9, " "))), - - dataRules.id_prev_deadkey, - dataRules.id_deadkey, - - "| ", (dataRules.modifier_key !== "" ? dataRules.modifier_key.padEnd(40, " ") : "--".padEnd(40, " ")), - (dataRules.key !== "" ? dataRules.key.padEnd(8, " ") : "--".padEnd(8, " ")), - (new TextDecoder().decode(dataRules.output) !== "" ? new TextDecoder().decode(dataRules.output).padEnd(10, " ") : ("--" + dataRules.output) + "--"), - - "| °°"); - - } - - - - - public Translate_Allmodifiers(data: convert_object) { - //let i=0; i< data. - console.log("HuRRA ",); - console.log(" ", data.arrayOf_Modifiers); - - const modi_flat = data.arrayOf_Modifiers.flat(); - console.log("modi_flat ", modi_flat); - const cps: boolean = this.checkIfCapsIsUsed(data.arrayOf_Modifiers); - - for (let i = 0; i < modi_flat.length; i++) { - - console.log(" ", this.create_kmn_modifier(modi_flat[i], cps)); - } - - - //const modi= data.arrayOf_Modifiers - - } } /** diff --git a/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts index e7da133e86e..581e18782ad 100644 --- a/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts @@ -7,7 +7,6 @@ import { assert } from 'chai'; import { compilerTestCallbacks, compilerTestOptions } from './helpers/index.js'; import { KeylayoutToKmnConverter } from '../src/keylayout-to-kmn/keylayout-to-kmn-converter.js'; import { makePathToFixture } from './helpers/index.js'; -import { error } from 'console'; //----------------------------------------------------------------------------------------------------------------------- @@ -17,17 +16,16 @@ describe('KeylayoutToKmnConverter', function () { compilerTestCallbacks.clear(); }); -// todo remove - describe('RunOneFile ', function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const inputFilename = makePathToFixture('../data/XX.keylayout'); - console.log(" inputFilename: ", inputFilename); - sut.run(inputFilename); - assert.isTrue(true); - ; - }); + // todo remove + describe('RunOneFile ', function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const inputFilename = makePathToFixture('../data/Italian.keylayout'); + sut.run(inputFilename); + assert.isTrue(true); + ; + }); -// todo remove + // todo remove describe('RunAllFiles ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); [ @@ -41,9 +39,11 @@ describe('KeylayoutToKmnConverter', function () { [makePathToFixture('../data/French.keylayout')], [makePathToFixture('../data/Latin_American.keylayout')], [makePathToFixture('../data/German_complete.keylayout')], - [makePathToFixture('../data/German_Standard.keylayout')], + [makePathToFixture('../data/German_complete_reduced.keylayout')], + // [makePathToFixture('../data/German_Standard.keylayout')], + + ].forEach(function (files_) { - console.log(" inputFilename: ", files_[0]); sut.run(files_[0]); assert.isTrue(true); }); @@ -230,19 +230,16 @@ describe('KeylayoutToKmnConverter', function () { const converted_empty = sut.convert(read_empty); it('should return converted array on correct input', async function () { - // we use 'converted' from above assert.isTrue(converted.arrayOf_Rules.length !== 0); }); it('should return empty on empty input', async function () { - // we use 'converted_empty' from above assert.isTrue((converted_empty.keylayout_filename === '' && converted_empty.arrayOf_Modifiers.length === 0 && converted_empty.arrayOf_Rules.length === 0)); }); it('should return empty on only name as input', async function () { - // we use 'converted_unavailable' from above assert.isTrue((converted_unavailable.keylayout_filename === '' && converted_unavailable.arrayOf_Modifiers.length === 0 && converted_unavailable.arrayOf_Rules.length === 0)); @@ -275,6 +272,14 @@ describe('KeylayoutToKmnConverter', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); [ + ['shift', true, 'NCAPS SHIFT'], + ['leftshift', true, 'NCAPS SHIFT'], + ['rightShift', true, 'NCAPS SHIFT'], + ['shift rightShift?', true, 'NCAPS SHIFT'], + ['rightShift?', true, 'NCAPS'], + ['shift Shift?', true, 'NCAPS SHIFT'], + ['shift rightShift? caps? rightOption? rightControl', true, 'NCAPS SHIFT RCTRL'], + ['leftshift rightShift? caps? rightOption? rightControl', true, 'NCAPS SHIFT RCTRL'], ['anycontrol', true, 'NCAPS CTRL'], ['shift?', true, 'NCAPS'], ['?', true, 'NCAPS'], @@ -595,37 +600,36 @@ describe('KeylayoutToKmnConverter', function () { ]; const b1_modifierKey_arr = [ ['K_SPACE', 'a0', '0', 'NCAPS', 'ˆ'], - ['K_SPACE', 'a0', '1', 'SHIFT NCAPS', 'ˆ'], + ['K_SPACE', 'a0', '1', 'NCAPS SHIFT', 'ˆ'], ['K_SPACE', 'a0', '1', 'SHIFT CAPS', 'ˆ'], ['K_SPACE', 'a0', '2', 'CAPS', 'ˆ'], - ['K_Z', 'a0', '4', 'SHIFT NCAPS RALT', 'ˆ'], - ['K_9', 'a0', '4', 'SHIFT NCAPS RALT', 'ˆ'], - ['K_COMMA', 'a0', '4', 'SHIFT NCAPS RALT', 'ˆ'], + ['K_Z', 'a0', '4', 'NCAPS SHIFT RALT', 'ˆ'], + ['K_9', 'a0', '4', 'NCAPS SHIFT RALT', 'ˆ'], + ['K_COMMA', 'a0', '4', 'NCAPS SHIFT RALT', 'ˆ'], ['K_SPACE', 'a0', '7', 'NCAPS CTRL', 'ˆ'], ['K_SPACE', 'a0', '7', 'NCAPS RALT CTRL', 'ˆ'], - ['K_A', 'a1', '1', 'SHIFT NCAPS', 'Â'], + ['K_A', 'a1', '1', 'NCAPS SHIFT', 'Â'], ['K_A', 'a1', '1', 'SHIFT CAPS', 'Â'], ['K_A', 'a1', '2', 'CAPS', 'Â'], ['K_E', 'a10', '0', 'NCAPS', 'ê'], ['K_I', 'a11', '0', 'NCAPS', 'î'], ['K_O', 'a13', '0', 'NCAPS', 'ô'], ['K_U', 'a14', '0', 'NCAPS', 'û'], - ['K_E', 'a2', '1', 'SHIFT NCAPS', 'Ê'], + ['K_E', 'a2', '1', 'NCAPS SHIFT', 'Ê'], ['K_E', 'a2', '1', 'SHIFT CAPS', 'Ê'], ['K_E', 'a2', '2', 'CAPS', 'Ê'], - ['K_I', 'a3', '1', 'SHIFT NCAPS', 'Î'], + ['K_I', 'a3', '1', 'NCAPS SHIFT', 'Î'], ['K_I', 'a3', '1', 'SHIFT CAPS', 'Î'], ['K_I', 'a3', '2', 'CAPS', 'Î'], - ['K_O', 'a5', '1', 'SHIFT NCAPS', 'Ô'], + ['K_O', 'a5', '1', 'NCAPS SHIFT', 'Ô'], ['K_O', 'a5', '1', 'SHIFT CAPS', 'Ô'], ['K_O', 'a5', '2', 'CAPS', 'Ô'], - ['K_U', 'a6', '1', 'SHIFT NCAPS', 'Û'], + ['K_U', 'a6', '1', 'NCAPS SHIFT', 'Û'], ['K_U', 'a6', '1', 'SHIFT CAPS', 'Û'], ['K_U', 'a6', '2', 'CAPS', 'Û'], ['K_A', 'a9', '0', 'NCAPS', 'â'] ]; - // isCaps_used === true; input defined [[b1_keycode_arr, b1_modifierKey_arr], [[['49', 'K_SPACE', 'a0', '0', 'ˆ']], [['K_SPACE', 'a0', '0', 'NCAPS', 'ˆ']]], [[['49', 'K_SPACE', 'a0', '0', '']], [['K_SPACE', 'a0', '0', 'NCAPS', '']]], @@ -648,7 +652,6 @@ describe('KeylayoutToKmnConverter', function () { }); }); - // isCaps_used === false; input defined [[[['49', 'K_SPACE', 'a0', '0', 'ˆ']], [['K_SPACE', 'a0', '0', '', 'ˆ']]], [[['49', 'K_SPACE', 'a0', '0', '']], [['K_SPACE', 'a0', '0', '', '']]], [[['', 'K_SPACE', 'a0', '0', 'ˆ']], [['K_SPACE', 'a0', '0', '', 'ˆ']]], @@ -665,7 +668,6 @@ describe('KeylayoutToKmnConverter', function () { }); }); - // isCaps_used === true; input undefined/null/empty [[[], []], [undefined, []], [null, []], @@ -785,7 +787,7 @@ describe('KeylayoutToKmnConverter', function () { [ ["a1", "A", true, [ - ['a1', 'A', 'a1', '1', 'K_A', 'SHIFT NCAPS'], + ['a1', 'A', 'a1', '1', 'K_A', 'NCAPS SHIFT'], ['a1', 'A', 'a1', '1', 'K_A', 'SHIFT CAPS'], ['a1', 'A', 'a1', '2', 'K_A', 'CAPS']] ], From 85047d6f77106752e3e05b7c30115500e3b1a1e5 Mon Sep 17 00:00:00 2001 From: SabineSIL <86713187+SabineSIL@users.noreply.github.com> Date: Thu, 27 Mar 2025 18:37:14 +0100 Subject: [PATCH 074/251] Delete developer/src/kmc-convert/data/My_dk_Keyboard.keylayout delete unused input files --- .../kmc-convert/data/My_dk_Keyboard.keylayout | 434 ------------------ 1 file changed, 434 deletions(-) delete mode 100644 developer/src/kmc-convert/data/My_dk_Keyboard.keylayout diff --git a/developer/src/kmc-convert/data/My_dk_Keyboard.keylayout b/developer/src/kmc-convert/data/My_dk_Keyboard.keylayout deleted file mode 100644 index b7c724e0110..00000000000 --- a/developer/src/kmc-convert/data/My_dk_Keyboard.keylayout +++ /dev/null @@ -1,434 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From 734c50b18fd59dac2ef49fc34ba0d8b764a9df23 Mon Sep 17 00:00:00 2001 From: SabineSIL <86713187+SabineSIL@users.noreply.github.com> Date: Thu, 27 Mar 2025 18:38:13 +0100 Subject: [PATCH 075/251] Delete developer/src/kmc-convert/data/MySample.keylayout delete unused input file --- .../src/kmc-convert/data/MySample.keylayout | 106 ------------------ 1 file changed, 106 deletions(-) delete mode 100644 developer/src/kmc-convert/data/MySample.keylayout diff --git a/developer/src/kmc-convert/data/MySample.keylayout b/developer/src/kmc-convert/data/MySample.keylayout deleted file mode 100644 index 2aa7e67fb25..00000000000 --- a/developer/src/kmc-convert/data/MySample.keylayout +++ /dev/null @@ -1,106 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From 8cd457dbcee1170e39ac6d44f78ba72bf657c47f Mon Sep 17 00:00:00 2001 From: Sabine Date: Fri, 28 Mar 2025 07:37:55 +0100 Subject: [PATCH 076/251] feat(developer): add/remove input files --- .../src/kmc-convert/data/Italian.keylayout | 1 - .../data/Italian_CapsAdded.keylayout | 1060 +++++++++++++++++ .../src/kmc-convert/data/MySample.keylayout | 106 -- .../kmc-convert/data/My_dk_Keyboard.keylayout | 434 ------- 4 files changed, 1060 insertions(+), 541 deletions(-) create mode 100644 developer/src/kmc-convert/data/Italian_CapsAdded.keylayout delete mode 100644 developer/src/kmc-convert/data/MySample.keylayout delete mode 100644 developer/src/kmc-convert/data/My_dk_Keyboard.keylayout diff --git a/developer/src/kmc-convert/data/Italian.keylayout b/developer/src/kmc-convert/data/Italian.keylayout index 7d1c75953e1..354a1a7fb3e 100644 --- a/developer/src/kmc-convert/data/Italian.keylayout +++ b/developer/src/kmc-convert/data/Italian.keylayout @@ -28,7 +28,6 @@ - diff --git a/developer/src/kmc-convert/data/Italian_CapsAdded.keylayout b/developer/src/kmc-convert/data/Italian_CapsAdded.keylayout new file mode 100644 index 00000000000..7d1c75953e1 --- /dev/null +++ b/developer/src/kmc-convert/data/Italian_CapsAdded.keylayout @@ -0,0 +1,1060 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/data/MySample.keylayout b/developer/src/kmc-convert/data/MySample.keylayout deleted file mode 100644 index 2aa7e67fb25..00000000000 --- a/developer/src/kmc-convert/data/MySample.keylayout +++ /dev/null @@ -1,106 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/developer/src/kmc-convert/data/My_dk_Keyboard.keylayout b/developer/src/kmc-convert/data/My_dk_Keyboard.keylayout deleted file mode 100644 index b7c724e0110..00000000000 --- a/developer/src/kmc-convert/data/My_dk_Keyboard.keylayout +++ /dev/null @@ -1,434 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From f24ee130c9aa82b257a7f56d335e874c1d95bb12 Mon Sep 17 00:00:00 2001 From: Sabine Date: Fri, 28 Mar 2025 17:47:50 +0100 Subject: [PATCH 077/251] feat(developer): add warning for superior rules --- .../keylayout-to-kmn-converter.ts | 79 +++++++++++-------- 1 file changed, 48 insertions(+), 31 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 8f026c9a4bb..dc17dfdf7d0 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -8,14 +8,6 @@ import { ConverterToKmnArtifacts } from "../converter-artifacts.js"; // Todo remove these todos - -// use cmdl parameters -> new issue/PR - -// TODO what about using actions twice in a row??? -> error msg if chain >4 -> new issue -// Todo prevent break for output ="" -> new issue - -// what if keylayout file is not correct e.g missing '>' -> new issue -// what if nodes in keylayout file do not exist/ diff name keyboard <-> keyboardA -> new issue // --------------------------------------------------- // add all tests again remove data files test @@ -158,7 +150,7 @@ export class KeylayoutToKmnConverter { arrayOf_Rules: [] }; - // ToDo in a new PR: check tags + // ToDo in a new PR: check tags ( issue # 13599) if (jsonObj_any.hasOwnProperty("keyboard")) { data_object.keylayout_filename = jsonObj_any.keyboard['@_name'] + ".keylayout"; @@ -758,6 +750,12 @@ export class KeylayoutToKmnConverter { else if (rule[index].rule_type === "C2") { if (!this.isAcceptableKeymanModifier(rule[index].modifier_deadkey)) { warningTextArray[1] = "unavailable modifier : "; + warningTextArray[2] = "unavailable superior rule ( [" + + rule[index].modifier_deadkey + " " + + rule[index].deadkey + + "] > dk(A" + + rule[index].id_deadkey + + ") ) : "; } if (!this.isAcceptableKeymanModifier(rule[index].modifier_key)) { warningTextArray[2] = "unavailable modifier : "; @@ -765,12 +763,34 @@ export class KeylayoutToKmnConverter { } else if (rule[index].rule_type === "C3") { + if (!this.isAcceptableKeymanModifier(rule[index].modifier_prev_deadkey)) { warningTextArray[0] = "unavailable modifier : "; + warningTextArray[1] = "unavailable superior rule ( [" + + rule[index].modifier_prev_deadkey + " " + + rule[index].prev_deadkey + + "] > dk(A" + + rule[index].id_prev_deadkey + + ") ) : "; + + warningTextArray[2] = "unavailable superior rule ( [" + + rule[index].modifier_deadkey + " " + + rule[index].deadkey + + "] > dk(A" + + rule[index].id_deadkey + + ") ) : "; } + if (!this.isAcceptableKeymanModifier(rule[index].modifier_deadkey)) { warningTextArray[1] = "unavailable modifier : "; + warningTextArray[2] = "unavailable superior rule ( [" + + rule[index].modifier_deadkey + " " + + rule[index].deadkey + + "] > dk(A" + + rule[index].id_deadkey + + ") ) : "; } + if (!this.isAcceptableKeymanModifier(rule[index].modifier_key)) { warningTextArray[2] = "unavailable modifier : "; } @@ -822,7 +842,7 @@ export class KeylayoutToKmnConverter { if (amb_4_1.length > 0) { warningTextArray[2] = warningTextArray[2] - + ("ambiguous rule: later: [" + + ("ambiguous 4-1 rule: later: [" + amb_4_1[0].modifier_prev_deadkey + " " + amb_4_1[0].prev_deadkey @@ -833,7 +853,7 @@ export class KeylayoutToKmnConverter { if (amb_2_1.length > 0) { warningTextArray[2] = warningTextArray[2] - + ("ambiguous rule: later: [" + + ("ambiguous 2-1 rule: later: [" + amb_2_1[0].modifier_deadkey + " " + amb_2_1[0].deadkey @@ -844,7 +864,7 @@ export class KeylayoutToKmnConverter { if (amb_1_1.length > 0) { warningTextArray[2] = warningTextArray[2] - + ("ambiguous rule: earlier: [" + + ("ambiguous 1-1 rule: earlier: [" + amb_1_1[0].modifier_key + " " + amb_1_1[0].key @@ -915,7 +935,7 @@ export class KeylayoutToKmnConverter { if (amb_2_2.length > 0) { warningTextArray[1] = warningTextArray[1] - + ("ambiguous rule: earlier: [" + + ("ambiguous 2-2 rule: earlier: [" + amb_2_2[0].modifier_deadkey + " " + amb_2_2[0].deadkey @@ -937,7 +957,7 @@ export class KeylayoutToKmnConverter { if (amb_3_3.length > 0) { warningTextArray[2] = warningTextArray[2] - + ("ambiguous rule: earlier: dk(A" + + ("ambiguous 3-3 rule: earlier: dk(A" + amb_3_3[0].id_deadkey + ") + [" + amb_3_3[0].modifier_key @@ -963,7 +983,7 @@ export class KeylayoutToKmnConverter { if (amb_4_2.length > 0) { warningTextArray[0] = warningTextArray[0] - + ("ambiguous rule: later: [" + + ("ambiguous 4-2 rule: later: [" + amb_4_2[0].modifier_prev_deadkey + " " + amb_4_2[0].prev_deadkey @@ -1062,7 +1082,7 @@ export class KeylayoutToKmnConverter { if (amb_2_4.length > 0) { warningTextArray[0] = warningTextArray[0] - + ("ambiguous rule: earlier: [" + + ("ambiguous 2-4 rule: earlier: [" + amb_2_4[0].modifier_deadkey + " " + amb_2_4[0].deadkey @@ -1073,7 +1093,7 @@ export class KeylayoutToKmnConverter { if (amb_6_3.length > 0) { warningTextArray[1] = warningTextArray[1] - + ("ambiguous rule: earlier: dk(C" + + ("ambiguous 6-3 rule: earlier: dk(C" + amb_6_3[0].id_deadkey + ") + [" + amb_6_3[0].modifier_key @@ -1099,7 +1119,7 @@ export class KeylayoutToKmnConverter { if (amb_4_4.length > 0) { warningTextArray[0] = warningTextArray[0] - + ("ambiguous rule: earlier: [" + + ("ambiguous 4-4 rule: earlier: [" + amb_4_4[0].modifier_prev_deadkey + " " + amb_4_4[0].prev_deadkey @@ -1121,7 +1141,7 @@ export class KeylayoutToKmnConverter { if (amb_5_5.length > 0) { warningTextArray[1] = warningTextArray[1] - + ("ambiguous rule: earlier: dk(B" + + ("ambiguous 5-5 rule: earlier: dk(B" + amb_5_5[0].id_prev_deadkey + ") + [" + amb_5_5[0].modifier_deadkey @@ -1147,7 +1167,7 @@ export class KeylayoutToKmnConverter { if (amb_6_6.length > 0) { warningTextArray[2] = warningTextArray[2] - + ("ambiguous rule: earlier: dk(B" + + ("ambiguous 6-6 rule: earlier: dk(B" + amb_6_6[0].id_deadkey + ") + [" + amb_6_6[0].modifier_key @@ -1313,10 +1333,9 @@ export class KeylayoutToKmnConverter { if (warn_text[2] == "") warn_text[2] = warn_text[2] + "c WARNING: use of a control character "; else - warn_text[2] = warn_text[2] + "; Use of a control character "; + warn_text[2] = warn_text[2] + " Use of a control character "; } - // add a warning in front of rules in case unavailable modifiers or ambiguous rules are used // if warning contains duplicate rules we do not write out the whole rule // (even if there are other warnings for the same rule) since that rule had been written before @@ -1331,6 +1350,7 @@ export class KeylayoutToKmnConverter { } } + data += "c #################### C2 \n"; //................................................ C2 ................................................................... for (let k = 0; k < unique_data_Rules.length; k++) { @@ -1375,7 +1395,7 @@ export class KeylayoutToKmnConverter { } } } - + data += "c #################### C3 \n"; //................................................ C3 ................................................................... for (let k = 0; k < unique_data_Rules.length; k++) { @@ -1398,20 +1418,18 @@ export class KeylayoutToKmnConverter { // add a warning in front of rules in case unavailable modifiers or ambiguous rules are used // if warning contains duplicate rules we do not write out the whole rule // (even if there are other warnings for the same rule) since that rule had been written before - if ((warn_text[0].indexOf("duplicate") < 0) - ) { + if ((warn_text[0].indexOf("duplicate") < 0)) { data += warn_text[0] + "+ [" + (unique_data_Rules[k].modifier_prev_deadkey + " " + unique_data_Rules[k].prev_deadkey).trim() - + "] > dk(C" + + "] > dk(A" + String(unique_data_Rules[k].id_prev_deadkey) + ")\n"; } - if ((warn_text[1].indexOf("duplicate") < 0) - ) { + if ((warn_text[1].indexOf("duplicate") < 0)) { data += warn_text[1] - + "dk(C" + (String(unique_data_Rules[k].id_prev_deadkey) + ") + [" + + "dk(A" + (String(unique_data_Rules[k].id_prev_deadkey) + ") + [" + unique_data_Rules[k].modifier_deadkey).trim() + " " + unique_data_Rules[k].deadkey @@ -1420,8 +1438,7 @@ export class KeylayoutToKmnConverter { + ")\n"; } - if ((warn_text[2].indexOf("duplicate") < 0) - ) { + if ((warn_text[2].indexOf("duplicate") < 0)) { data += warn_text[2] + "dk(B" + (String(unique_data_Rules[k].id_deadkey) + ") + [" From 91153a3eaa4aa2a9ece898642a570c68ea055b19 Mon Sep 17 00:00:00 2001 From: Sabine Date: Fri, 28 Mar 2025 20:12:00 +0100 Subject: [PATCH 078/251] feat(developer): switch to write/not write rules with associated warnings --- .../data/Italian_CapsAdded.keylayout | 2 +- .../keylayout-to-kmn-converter.ts | 136 ++++++++++++------ 2 files changed, 95 insertions(+), 43 deletions(-) diff --git a/developer/src/kmc-convert/data/Italian_CapsAdded.keylayout b/developer/src/kmc-convert/data/Italian_CapsAdded.keylayout index 7d1c75953e1..14f1f2d2d25 100644 --- a/developer/src/kmc-convert/data/Italian_CapsAdded.keylayout +++ b/developer/src/kmc-convert/data/Italian_CapsAdded.keylayout @@ -8,7 +8,7 @@ --> - + diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index dc17dfdf7d0..0d5bb6cd65a 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -67,6 +67,7 @@ export class KeylayoutToKmnConverter { static readonly OUTPUT_FILE_EXTENSION = '.kmn'; static readonly USED_KEYS_COUNT = 51; static readonly MAX_CTRL_CHARACTER = 32; + static readonly SKIP_COMMENTED_LINES = true; constructor(private callbacks: CompilerCallbacks, options: CompilerOptions) { }; @@ -1340,12 +1341,20 @@ export class KeylayoutToKmnConverter { // if warning contains duplicate rules we do not write out the whole rule // (even if there are other warnings for the same rule) since that rule had been written before if ((warn_text[2].indexOf("duplicate") < 0)) { - data += warn_text[2] - + "+ [" - + (unique_data_Rules[k].modifier_key + ' ' + unique_data_Rules[k].key).trim() - + `] > \'` - + output_character_unicode - + '\'\n'; + + let warningTextToWrite = ""; + if (!KeylayoutToKmnConverter.SKIP_COMMENTED_LINES && (warn_text[2].length > 0)) { + warningTextToWrite = warn_text[2]; + } + + if (!((warn_text[2].length > 0) && KeylayoutToKmnConverter.SKIP_COMMENTED_LINES)) { + data += warningTextToWrite + + "+ [" + + (unique_data_Rules[k].modifier_key + ' ' + unique_data_Rules[k].key).trim() + + `] > \'` + + output_character_unicode + + '\'\n'; + } } } } @@ -1374,23 +1383,38 @@ export class KeylayoutToKmnConverter { // if warning contains duplicate rules we do not write out the whole rule // (even if there are other warnings for the same rule) since that rule had been written before if ((warn_text[1].indexOf("duplicate") < 0)) { - data += warn_text[1] - + "+ [" + (unique_data_Rules[k].modifier_deadkey + " " - + unique_data_Rules[k].deadkey).trim() - + "] > dk(A" + String(unique_data_Rules[k].id_deadkey) - + ")\n"; + + let warningTextToWrite = ""; + if (!KeylayoutToKmnConverter.SKIP_COMMENTED_LINES && (warn_text[1].length > 0)) { + warningTextToWrite = warn_text[1]; + } + + if (!((warn_text[1].length > 0) && KeylayoutToKmnConverter.SKIP_COMMENTED_LINES)) { + data += warningTextToWrite + + "+ [" + (unique_data_Rules[k].modifier_deadkey + " " + + unique_data_Rules[k].deadkey).trim() + + "] > dk(A" + String(unique_data_Rules[k].id_deadkey) + + ")\n"; + } } if ((warn_text[2].indexOf("duplicate") < 0)) { - data += warn_text[2] - + "dk(A" - + (String(unique_data_Rules[k].id_deadkey) + ") + [" - + unique_data_Rules[k].modifier_key).trim() - + " " - + unique_data_Rules[k].key + "] > \'" - + output_character_unicode - + "\'\n"; + let warningTextToWrite = ""; + if (!KeylayoutToKmnConverter.SKIP_COMMENTED_LINES && (warn_text[2].length > 0)) { + warningTextToWrite = warn_text[2]; + } + + if (!((warn_text[2].length > 0) && KeylayoutToKmnConverter.SKIP_COMMENTED_LINES)) { + data += warningTextToWrite + + "dk(A" + + (String(unique_data_Rules[k].id_deadkey) + ") + [" + + unique_data_Rules[k].modifier_key).trim() + + " " + + unique_data_Rules[k].key + "] > \'" + + output_character_unicode + + "\'\n"; + } data += "\n"; } } @@ -1419,35 +1443,63 @@ export class KeylayoutToKmnConverter { // if warning contains duplicate rules we do not write out the whole rule // (even if there are other warnings for the same rule) since that rule had been written before if ((warn_text[0].indexOf("duplicate") < 0)) { - data += warn_text[0] - + "+ [" - + (unique_data_Rules[k].modifier_prev_deadkey + " " - + unique_data_Rules[k].prev_deadkey).trim() - + "] > dk(A" - + String(unique_data_Rules[k].id_prev_deadkey) + ")\n"; + + + let warningTextToWrite = ""; + if (!KeylayoutToKmnConverter.SKIP_COMMENTED_LINES && (warn_text[0].length > 0)) { + warningTextToWrite = warn_text[0]; + } + + if (!((warn_text[0].length > 0) && KeylayoutToKmnConverter.SKIP_COMMENTED_LINES)) { + data += warningTextToWrite + + "+ [" + + (unique_data_Rules[k].modifier_prev_deadkey + " " + + unique_data_Rules[k].prev_deadkey).trim() + + "] > dk(A" + + String(unique_data_Rules[k].id_prev_deadkey) + ")\n"; + } } + + + if ((warn_text[1].indexOf("duplicate") < 0)) { - data += warn_text[1] - + "dk(A" + (String(unique_data_Rules[k].id_prev_deadkey) + ") + [" - + unique_data_Rules[k].modifier_deadkey).trim() - + " " - + unique_data_Rules[k].deadkey - + "] > dk(B" - + String(unique_data_Rules[k].id_deadkey) - + ")\n"; + + let warningTextToWrite = ""; + if (!KeylayoutToKmnConverter.SKIP_COMMENTED_LINES && (warn_text[1].length > 0)) { + warningTextToWrite = warn_text[1]; + } + + if (!((warn_text[1].length > 0) && KeylayoutToKmnConverter.SKIP_COMMENTED_LINES)) { + data += warningTextToWrite + + "dk(A" + (String(unique_data_Rules[k].id_prev_deadkey) + ") + [" + + unique_data_Rules[k].modifier_deadkey).trim() + + " " + + unique_data_Rules[k].deadkey + + "] > dk(B" + + String(unique_data_Rules[k].id_deadkey) + + ")\n"; + } } if ((warn_text[2].indexOf("duplicate") < 0)) { - data += warn_text[2] + "dk(B" - + (String(unique_data_Rules[k].id_deadkey) - + ") + [" - + unique_data_Rules[k].modifier_key).trim() - + " " - + unique_data_Rules[k].key - + "] > \'" - + output_character_unicode - + "\'\n"; + + let warningTextToWrite = ""; + if (!KeylayoutToKmnConverter.SKIP_COMMENTED_LINES && (warn_text[2].length > 0)) { + warningTextToWrite = warn_text[2]; + } + + if (!((warn_text[2].length > 0) && KeylayoutToKmnConverter.SKIP_COMMENTED_LINES)) { + data += warningTextToWrite + "dk(B" + + (String(unique_data_Rules[k].id_deadkey) + + ") + [" + + unique_data_Rules[k].modifier_key).trim() + + " " + + unique_data_Rules[k].key + + "] > \'" + + output_character_unicode + + "\'\n"; + } } if ((warn_text[0].indexOf("duplicate") < 0) || (warn_text[1].indexOf("duplicate") < 0) || (warn_text[2].indexOf("duplicate") < 0)) { From 0fe56a4d883a2184dd7aec457d8a367687323dde Mon Sep 17 00:00:00 2001 From: Sabine Date: Mon, 31 Mar 2025 10:07:05 +0200 Subject: [PATCH 079/251] feat(developer): change use of Backslash as Path Separator; remove all markers --- .../keylayout-to-kmn-converter.ts | 46 ++++++++----------- .../test/test-keylayout-to-kmn-converter.ts | 40 ++-------------- 2 files changed, 23 insertions(+), 63 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 0d5bb6cd65a..3f7d791f894 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -5,14 +5,7 @@ */ import { CompilerCallbacks, CompilerOptions } from "@keymanapp/developer-utils"; import { ConverterToKmnArtifacts } from "../converter-artifacts.js"; - - -// Todo remove these todos -// --------------------------------------------------- - -// add all tests again remove data files test - - +import path from 'path'; import { XMLParser } from 'fast-xml-parser'; // for reading an xml file import { readFileSync } from 'fs'; import { util } from '@keymanapp/common-types'; @@ -67,7 +60,7 @@ export class KeylayoutToKmnConverter { static readonly OUTPUT_FILE_EXTENSION = '.kmn'; static readonly USED_KEYS_COUNT = 51; static readonly MAX_CTRL_CHARACTER = 32; - static readonly SKIP_COMMENTED_LINES = true; + static readonly SKIP_COMMENTED_LINES = false; constructor(private callbacks: CompilerCallbacks, options: CompilerOptions) { }; @@ -108,10 +101,10 @@ export class KeylayoutToKmnConverter { /** * @brief member function to parse data from a .keylayout-file and store to a json object - * @param filename the ukelele .keylayout-file to be parsed + * @param absolutefilename the ukelele .keylayout-file to be parsed * @return in case of success: json object containing data of the .keylayout file; else null */ - public read(filename: string): Object { + public read(absolutefilename: string): Object { let xmlFile; let jsonObj = []; @@ -122,10 +115,10 @@ export class KeylayoutToKmnConverter { }; try { - xmlFile = readFileSync((process.cwd() + "\\data" + filename.substring(filename.lastIndexOf("\\"))).replace(" ", ""), 'utf8'); + xmlFile = readFileSync(path.join(process.cwd(), "data", absolutefilename.replace(/^.*[\\/]/, '')), 'utf8'); const parser = new XMLParser(options); jsonObj = parser.parse(xmlFile); // get plain Object - boxArray(jsonObj.keyboard); // jsonObj now contains arrays; no single fields + boxArray(jsonObj.keyboard); // jsonObj now contains arrays; no single fields } catch (err) { console.log(err.message); @@ -865,7 +858,7 @@ export class KeylayoutToKmnConverter { if (amb_1_1.length > 0) { warningTextArray[2] = warningTextArray[2] - + ("ambiguous 1-1 rule: earlier: [" + + ("ambiguous rule: earlier: [" + amb_1_1[0].modifier_key + " " + amb_1_1[0].key @@ -936,7 +929,7 @@ export class KeylayoutToKmnConverter { if (amb_2_2.length > 0) { warningTextArray[1] = warningTextArray[1] - + ("ambiguous 2-2 rule: earlier: [" + + ("ambiguous rule: earlier: [" + amb_2_2[0].modifier_deadkey + " " + amb_2_2[0].deadkey @@ -958,7 +951,7 @@ export class KeylayoutToKmnConverter { if (amb_3_3.length > 0) { warningTextArray[2] = warningTextArray[2] - + ("ambiguous 3-3 rule: earlier: dk(A" + + ("ambiguous rule: earlier: dk(A" + amb_3_3[0].id_deadkey + ") + [" + amb_3_3[0].modifier_key @@ -984,7 +977,7 @@ export class KeylayoutToKmnConverter { if (amb_4_2.length > 0) { warningTextArray[0] = warningTextArray[0] - + ("ambiguous 4-2 rule: later: [" + + ("ambiguous rule: later: [" + amb_4_2[0].modifier_prev_deadkey + " " + amb_4_2[0].prev_deadkey @@ -1083,7 +1076,7 @@ export class KeylayoutToKmnConverter { if (amb_2_4.length > 0) { warningTextArray[0] = warningTextArray[0] - + ("ambiguous 2-4 rule: earlier: [" + + ("ambiguous rule: earlier: [" + amb_2_4[0].modifier_deadkey + " " + amb_2_4[0].deadkey @@ -1094,7 +1087,7 @@ export class KeylayoutToKmnConverter { if (amb_6_3.length > 0) { warningTextArray[1] = warningTextArray[1] - + ("ambiguous 6-3 rule: earlier: dk(C" + + ("ambiguous rule: earlier: dk(C" + amb_6_3[0].id_deadkey + ") + [" + amb_6_3[0].modifier_key @@ -1120,7 +1113,7 @@ export class KeylayoutToKmnConverter { if (amb_4_4.length > 0) { warningTextArray[0] = warningTextArray[0] - + ("ambiguous 4-4 rule: earlier: [" + + ("ambiguous rule: earlier: [" + amb_4_4[0].modifier_prev_deadkey + " " + amb_4_4[0].prev_deadkey @@ -1142,7 +1135,7 @@ export class KeylayoutToKmnConverter { if (amb_5_5.length > 0) { warningTextArray[1] = warningTextArray[1] - + ("ambiguous 5-5 rule: earlier: dk(B" + + ("ambiguous rule: earlier: dk(B" + amb_5_5[0].id_prev_deadkey + ") + [" + amb_5_5[0].modifier_deadkey @@ -1168,7 +1161,7 @@ export class KeylayoutToKmnConverter { if (amb_6_6.length > 0) { warningTextArray[2] = warningTextArray[2] - + ("ambiguous 6-6 rule: earlier: dk(B" + + ("ambiguous rule: earlier: dk(B" + amb_6_6[0].id_deadkey + ") + [" + amb_6_6[0].modifier_key @@ -1338,7 +1331,7 @@ export class KeylayoutToKmnConverter { } // add a warning in front of rules in case unavailable modifiers or ambiguous rules are used - // if warning contains duplicate rules we do not write out the whole rule + // if warning contains duplicate rules we do not write out the entire rule // (even if there are other warnings for the same rule) since that rule had been written before if ((warn_text[2].indexOf("duplicate") < 0)) { @@ -1359,7 +1352,6 @@ export class KeylayoutToKmnConverter { } } - data += "c #################### C2 \n"; //................................................ C2 ................................................................... for (let k = 0; k < unique_data_Rules.length; k++) { @@ -1380,7 +1372,7 @@ export class KeylayoutToKmnConverter { } // add a warning in front of rules in case unavailable modifiers or ambiguous rules are used - // if warning contains duplicate rules we do not write out the whole rule + // if warning contains duplicate rules we do not write out the entire rule // (even if there are other warnings for the same rule) since that rule had been written before if ((warn_text[1].indexOf("duplicate") < 0)) { @@ -1419,7 +1411,7 @@ export class KeylayoutToKmnConverter { } } } - data += "c #################### C3 \n"; + //................................................ C3 ................................................................... for (let k = 0; k < unique_data_Rules.length; k++) { @@ -1440,7 +1432,7 @@ export class KeylayoutToKmnConverter { } // add a warning in front of rules in case unavailable modifiers or ambiguous rules are used - // if warning contains duplicate rules we do not write out the whole rule + // if warning contains duplicate rules we do not write out the entire rule // (even if there are other warnings for the same rule) since that rule had been written before if ((warn_text[0].indexOf("duplicate") < 0)) { diff --git a/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts index 581e18782ad..e1720738a73 100644 --- a/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts @@ -16,38 +16,6 @@ describe('KeylayoutToKmnConverter', function () { compilerTestCallbacks.clear(); }); - // todo remove - describe('RunOneFile ', function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const inputFilename = makePathToFixture('../data/Italian.keylayout'); - sut.run(inputFilename); - assert.isTrue(true); - ; - }); - - // todo remove - describe('RunAllFiles ', function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - [ - [makePathToFixture('../data/Italian.keylayout')], - [makePathToFixture('../data/Italian_command.keylayout')], - [makePathToFixture('../data/Swiss_French.keylayout')], - [makePathToFixture('../data/Spanish.keylayout')], - [makePathToFixture('../data/Swiss_German.keylayout')], - [makePathToFixture('../data/US.keylayout')], - [makePathToFixture('../data/Polish.keylayout')], - [makePathToFixture('../data/French.keylayout')], - [makePathToFixture('../data/Latin_American.keylayout')], - [makePathToFixture('../data/German_complete.keylayout')], - [makePathToFixture('../data/German_complete_reduced.keylayout')], - // [makePathToFixture('../data/German_Standard.keylayout')], - - - ].forEach(function (files_) { - sut.run(files_[0]); - assert.isTrue(true); - }); - }); describe("run() ", function () { @@ -96,7 +64,7 @@ describe('KeylayoutToKmnConverter', function () { }); it('run() should return on correct input file name and empty output file name ', async function () { - const inputFilename = makePathToFixture('../data/Italian_command.keylayout'); + const inputFilename = makePathToFixture('../data/Italian.keylayout'); let threw = false; try { await sut.run(inputFilename, ""); @@ -107,7 +75,7 @@ describe('KeylayoutToKmnConverter', function () { }); it('run() should return on correct input file name and null output file name', async function () { - const inputFilename = makePathToFixture('../data/Italian_command.keylayout'); + const inputFilename = makePathToFixture('../data/Italian.keylayout'); let threw = false; try { await sut.run(inputFilename, null); @@ -118,7 +86,7 @@ describe('KeylayoutToKmnConverter', function () { }); it('run() should return on correct input file name and given output file name ', async function () { - const inputFilename = makePathToFixture('../data/Italian_command.keylayout'); + const inputFilename = makePathToFixture('../data/Italian.keylayout'); const outputFilename = makePathToFixture('../../data/OutputName.kmn'); let threw = false; try { @@ -142,7 +110,7 @@ describe('KeylayoutToKmnConverter', function () { }); it('run() return on correct input file extention and unsupperted output file extention', async function () { - const inputFilename = makePathToFixture('../data/Italian_command.keylayout'); + const inputFilename = makePathToFixture('../data/Italian.keylayout'); const outputFilename = makePathToFixture('../../data/OutputXName.B'); let threw = false; try { From e3e887409145ea520316cb32aa3d06d90a0e1a30 Mon Sep 17 00:00:00 2001 From: Sabine Date: Mon, 31 Mar 2025 17:50:10 +0200 Subject: [PATCH 080/251] feat(developer): rename test files according to new standard --- developer/src/kmc-convert/data/US.keylayout | 2 +- developer/src/kmc-convert/package.json | 2 +- .../{test-converter-messages.ts => converter-messages.tests.ts} | 0 .../kmc-convert/test/{test-converter.ts => converter.tests.ts} | 0 ...-to-kmn-converter.ts => keylayout-to-kmn-converter.tests.ts} | 2 -- developer/src/kmc-convert/test/tsconfig.json | 2 +- 6 files changed, 3 insertions(+), 5 deletions(-) rename developer/src/kmc-convert/test/{test-converter-messages.ts => converter-messages.tests.ts} (100%) rename developer/src/kmc-convert/test/{test-converter.ts => converter.tests.ts} (100%) rename developer/src/kmc-convert/test/{test-keylayout-to-kmn-converter.ts => keylayout-to-kmn-converter.tests.ts} (99%) diff --git a/developer/src/kmc-convert/data/US.keylayout b/developer/src/kmc-convert/data/US.keylayout index eaf4fbb4195..aca8dbf6f0c 100644 --- a/developer/src/kmc-convert/data/US.keylayout +++ b/developer/src/kmc-convert/data/US.keylayout @@ -8,7 +8,7 @@ --> - + diff --git a/developer/src/kmc-convert/package.json b/developer/src/kmc-convert/package.json index 1a46fb63b18..93ea8999f43 100644 --- a/developer/src/kmc-convert/package.json +++ b/developer/src/kmc-convert/package.json @@ -43,7 +43,7 @@ "typescript": "^5.4.5" }, "mocha": { - "spec": "build/test/**/test-*.js", + "spec": "build/test/**/*.tests.js", "require": [ "source-map-support/register" ] diff --git a/developer/src/kmc-convert/test/test-converter-messages.ts b/developer/src/kmc-convert/test/converter-messages.tests.ts similarity index 100% rename from developer/src/kmc-convert/test/test-converter-messages.ts rename to developer/src/kmc-convert/test/converter-messages.tests.ts diff --git a/developer/src/kmc-convert/test/test-converter.ts b/developer/src/kmc-convert/test/converter.tests.ts similarity index 100% rename from developer/src/kmc-convert/test/test-converter.ts rename to developer/src/kmc-convert/test/converter.tests.ts diff --git a/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts similarity index 99% rename from developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts rename to developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index e1720738a73..58ab254cfcc 100644 --- a/developer/src/kmc-convert/test/test-keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -16,8 +16,6 @@ describe('KeylayoutToKmnConverter', function () { compilerTestCallbacks.clear(); }); - - describe("run() ", function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); diff --git a/developer/src/kmc-convert/test/tsconfig.json b/developer/src/kmc-convert/test/tsconfig.json index ae9de6c9a5f..78127d66db9 100644 --- a/developer/src/kmc-convert/test/tsconfig.json +++ b/developer/src/kmc-convert/test/tsconfig.json @@ -8,7 +8,7 @@ "baseUrl": ".", }, "include": [ - "**/test-*.ts", + "**/*.tests.ts", "./helpers/index.ts", ], "references": [ From c39eeff7c6e51fa989c14d580dcbf4ee30928019 Mon Sep 17 00:00:00 2001 From: Sabine Date: Tue, 1 Apr 2025 12:30:14 +0200 Subject: [PATCH 081/251] feat(developer): use fs and path from callbacks --- .../src/keylayout-to-kmn/keylayout-to-kmn-converter.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 3f7d791f894..db38b90d940 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -5,9 +5,7 @@ */ import { CompilerCallbacks, CompilerOptions } from "@keymanapp/developer-utils"; import { ConverterToKmnArtifacts } from "../converter-artifacts.js"; -import path from 'path'; import { XMLParser } from 'fast-xml-parser'; // for reading an xml file -import { readFileSync } from 'fs'; import { util } from '@keymanapp/common-types'; import boxXmlArray = util.boxXmlArray; @@ -115,7 +113,7 @@ export class KeylayoutToKmnConverter { }; try { - xmlFile = readFileSync(path.join(process.cwd(), "data", absolutefilename.replace(/^.*[\\/]/, '')), 'utf8'); + xmlFile = this.callbacks.fs.readFileSync(this.callbacks.path.join(process.cwd(), "data", absolutefilename.replace(/^.*[\\/]/, '')), 'utf8'); const parser = new XMLParser(options); jsonObj = parser.parse(xmlFile); // get plain Object boxArray(jsonObj.keyboard); // jsonObj now contains arrays; no single fields From c08642f5699e8c4b65e3953fcf70d3608093f8f3 Mon Sep 17 00:00:00 2001 From: Sabine Date: Wed, 2 Apr 2025 17:20:56 +0200 Subject: [PATCH 082/251] feat(developer): move read() and write() to modules --- .../keylayout-to-kmn/keylayout-file-reader.ts | 69 ++++ .../keylayout-to-kmn-converter.ts | 391 +----------------- .../src/keylayout-to-kmn/kmn-file-writer.ts | 318 ++++++++++++++ .../test/keylayout-to-kmn-converter.tests.ts | 90 ++-- 4 files changed, 462 insertions(+), 406 deletions(-) create mode 100644 developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts create mode 100644 developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts new file mode 100644 index 00000000000..d759227947e --- /dev/null +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts @@ -0,0 +1,69 @@ +/* + * Keyman is 2025 copyright (C) SIL International. MIT License. + * + * Read macOS/Ukelele .keylayout files + * + */ + +import { CompilerCallbacks } from "@keymanapp/developer-utils"; +import { XMLParser } from 'fast-xml-parser'; +import { util } from '@keymanapp/common-types'; +import boxXmlArray = util.boxXmlArray; + +export class KeylayoutFileReader { + + constructor(private callbacks: CompilerCallbacks /*,private options: CompilerOptions*/) { }; + + /** + * @brief member function to box single-entry objects into arrays + * @param source the object to be changed + * @return objects that contain only boxed arrays + */ + public boxArray(source: any) { + boxXmlArray(source.layouts, 'layout'); + boxXmlArray(source.terminators, 'when'); + boxXmlArray(source, 'keyMapSet'); + boxXmlArray(source.keyMapSet, 'keyMap'); + boxXmlArray(source.action, 'actions'); + + boxXmlArray(source?.modifierMap, 'keyMapSelect'); + for (const keyMapSelect of source?.modifierMap?.keyMapSelect) { + boxXmlArray(keyMapSelect, 'modifier'); + } + boxXmlArray(source?.actions, 'action'); + for (const action of source?.actions?.action) { + boxXmlArray(action, 'when'); + } + return source; + } + + /** + * @brief member function to parse data from a .keylayout-file and store to a json object + * @param absolutefilename the ukelele .keylayout-file to be parsed + * @return in case of success: json object containing data of the .keylayout file; else null + */ + public read(absolutefilename: string): Object { + + let xmlFile; + let jsonObj = []; + + const options = { + ignoreAttributes: false, + trimValues: false, // preserve spaces + attributeNamePrefix: '@_' // to access the attribute + }; + + try { + xmlFile = this.callbacks.fs.readFileSync(this.callbacks.path.join(process.cwd(), "data", absolutefilename.replace(/^.*[\\/]/, '')), 'utf8'); + const parser = new XMLParser(options); + jsonObj = parser.parse(xmlFile); // get plain Object + this.boxArray(jsonObj.keyboard); // jsonObj now contains arrays; no single fields + } + catch (err) { + console.log(err.message); + } + return jsonObj; + } +} + + diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index db38b90d940..b4e94d3c710 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -1,31 +1,14 @@ /* - * Keyman is copyright (C) SIL International. MIT License. + * Keyman is 2025 copyright (C) SIL International. MIT License. + * + * Convert macOS/Ukelele .keylayout files to Keyman .kmn * - * Converts macOS/Ukelele .keylayout files to Keyman .kmn */ + import { CompilerCallbacks, CompilerOptions } from "@keymanapp/developer-utils"; import { ConverterToKmnArtifacts } from "../converter-artifacts.js"; -import { XMLParser } from 'fast-xml-parser'; // for reading an xml file -import { util } from '@keymanapp/common-types'; -import boxXmlArray = util.boxXmlArray; - -function boxArray(source: any) { - boxXmlArray(source.layouts, 'layout'); - boxXmlArray(source.terminators, 'when'); - boxXmlArray(source, 'keyMapSet'); - boxXmlArray(source.keyMapSet, 'keyMap'); - boxXmlArray(source.action, 'actions'); - - boxXmlArray(source?.modifierMap, 'keyMapSelect'); - for (const keyMapSelect of source?.modifierMap?.keyMapSelect) { - boxXmlArray(keyMapSelect, 'modifier'); - } - boxXmlArray(source?.actions, 'action'); - for (const action of source?.actions?.action) { - boxXmlArray(action, 'when'); - } - return source; -} +import { KmnFileWriter } from './kmn-file-writer.js'; +import { KeylayoutFileReader } from './keylayout-file-reader.js'; export interface rule_object { rule_type: string, /* rule type C0-C4 */ @@ -60,8 +43,16 @@ export class KeylayoutToKmnConverter { static readonly MAX_CTRL_CHARACTER = 32; static readonly SKIP_COMMENTED_LINES = false; - constructor(private callbacks: CompilerCallbacks, options: CompilerOptions) { - }; + //private callbacks: CompilerCallbacks; + private options: CompilerOptions; + + async init(callbacks: CompilerCallbacks, options: CompilerOptions): Promise { + this.options = { ...options }; + this.callbacks = callbacks; + return true; + } + + constructor(private callbacks: CompilerCallbacks, options: CompilerOptions) { }; /** * @brief member function to run read/convert/write @@ -74,21 +65,22 @@ export class KeylayoutToKmnConverter { if (!inputFilename) { throw new Error('Invalid parameters'); } - const jsonO: object = this.read(inputFilename); + const KeylayoutReader = new KeylayoutFileReader(this.callbacks/*, this.options*/); + const jsonO: object = KeylayoutReader.read(inputFilename); if (!jsonO) { throw new Error('Error while processing read()'); return null; } const outArray: convert_object = await this.convert(jsonO, outputFilename); - if (!outArray) { throw new Error('Error while processing convert()'); return null; } - const out_text_ok: boolean = this.write(outArray); + const kmnFileWriter = new KmnFileWriter(this.callbacks, this.options); + const out_text_ok: boolean = kmnFileWriter.write(outArray); if (!out_text_ok) { throw new Error('Error while processing write()'); @@ -97,33 +89,6 @@ export class KeylayoutToKmnConverter { return null; } - /** - * @brief member function to parse data from a .keylayout-file and store to a json object - * @param absolutefilename the ukelele .keylayout-file to be parsed - * @return in case of success: json object containing data of the .keylayout file; else null - */ - public read(absolutefilename: string): Object { - let xmlFile; - let jsonObj = []; - - const options = { - ignoreAttributes: false, - trimValues: false, // preserve spaces - attributeNamePrefix: '@_' // to access the attribute - }; - - try { - xmlFile = this.callbacks.fs.readFileSync(this.callbacks.path.join(process.cwd(), "data", absolutefilename.replace(/^.*[\\/]/, '')), 'utf8'); - const parser = new XMLParser(options); - jsonObj = parser.parse(xmlFile); // get plain Object - boxArray(jsonObj.keyboard); // jsonObj now contains arrays; no single fields - } - catch (err) { - console.log(err.message); - } - return jsonObj; - } - /** * @brief member function to read filename and behaviour of a json object into a convert_object * @param jsonObj containing filename, behaviour and rules of a json object @@ -501,7 +466,6 @@ export class KeylayoutToKmnConverter { unique_dkB_count++; list_of_unique_Text2_rules.push(ruleArray); } - } } @@ -543,7 +507,6 @@ export class KeylayoutToKmnConverter { ruleArray.push(String(unique_dkB_count)); unique_dkB_count++; list_of_unique_Text2_rules.push(ruleArray); - } } } @@ -563,30 +526,6 @@ export class KeylayoutToKmnConverter { return data_ukelele; } - /** - * @brief member function to write data from object to a kmn file - * @param data_ukelele the array holding all keyboard data - * @param outputfilename the file that will be written; if no outputfilename is given an outputfilename will be created from data_ukelele.keylayout_filename - * @return true if data has been written; false if not - */ - public write(data_ukelele: convert_object): boolean { - - let data: string = "\n"; - - // add top part of kmn file: STORES - data += this.writeData_Stores(data_ukelele); - - // add bottom part of kmn file: RULES - data += this.writeData_Rules(data_ukelele); - - try { - this.callbacks.fs.writeFileSync(data_ukelele.kmn_filename, new TextEncoder().encode(data)); - return true; - } catch (err) { - console.log('ERROR writing kmn file:' + err.message); - return false; - } - } /** * @brief member function to create a kmn modifier from a keylayout modifier @@ -878,6 +817,7 @@ export class KeylayoutToKmnConverter { } if (rule[index].rule_type === "C2") { + // 2-2: + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(C3) const amb_2_2 = rule.filter((curr, idx) => curr.rule_type === "C2" @@ -1208,298 +1148,9 @@ export class KeylayoutToKmnConverter { warningTextArray[2] = warningTextArray[2] + extra_warning; } } - return warningTextArray; } - - /** - * @brief member function to create data for stores that will be printed to the resulting kmn file - * @param data_ukelele an object containing all data read from a .keylayout file - * @return string - all stores to be printed - */ - public writeData_Stores(data_ukelele: convert_object): string { - - let data: string = ""; - data += "c ......................................................................\n"; - data += "c ......................................................................\n"; - data += "c Keyman keyboard generated by kmn-convert\n"; - data += "c from Ukelele file: " + data_ukelele.keylayout_filename + "\n"; - data += "c ......................................................................\n"; - data += "c ......................................................................\n"; - data += "\n"; - - data += "store(&VERSION) \'10.0\'\n"; - data += "store(&TARGETS) \'any\'\n"; - data += "store(&KEYBOARDVERSION) \'1.0\'\n"; - data += "store(©RIGHT) '© 2024 SIL International\'\n"; - - data += "\n"; - data += "begin Unicode > use(main)\n\n"; - data += "group(main) using keys\n\n"; - - data += "\n"; - return data; - } - - /** - * @brief member function to create data from rules that will be printed to the resulting kmn file - * @param data_ukelele an object containing all data read from a .keylayout file - * @return string - all rules to be printed - */ - public writeData_Rules(data_ukelele: convert_object): string { - - let data: string = ""; - - // filter array of all rules and remove duplicates - const unique_data_Rules: rule_object[] = data_ukelele.arrayOf_Rules.filter((curr) => { - return (!(curr.output === new TextEncoder().encode("") || curr.output === undefined) - && (curr.key !== "") - && ((curr.rule_type === "C0") - || (curr.rule_type === "C1") - || (curr.rule_type === "C2" && (curr.deadkey !== "")) - || (curr.rule_type === "C3" && (curr.deadkey !== "") && (curr.prev_deadkey !== ""))) - ); - }).reduce((unique, o) => { - if (!unique.some((obj: { - modifier_prev_deadkey: string; prev_deadkey: string; - modifier_deadkey: string; deadkey: string; - modifier_key: string; key: string; - rule_type: string; - output: Uint8Array; - }) => - new TextDecoder().decode(obj.output) === new TextDecoder().decode(o.output) - - && obj.output !== new TextEncoder().encode("") - - && obj.rule_type === o.rule_type - && obj.modifier_key === o.modifier_key - && obj.key === o.key - - && obj.modifier_deadkey === o.modifier_deadkey - && obj.deadkey === o.deadkey - - && obj.modifier_prev_deadkey === o.modifier_prev_deadkey - && obj.prev_deadkey === o.prev_deadkey) - ) { - unique.push(o); - } - return unique; - }, []); - - //................................................ C0 C1 ................................................................ - - for (let k = 0; k < unique_data_Rules.length; k++) { - - if ((unique_data_Rules[k].rule_type === "C0") || (unique_data_Rules[k].rule_type === "C1")) { - - // lookup key nr of the key which is being processed - let keyNr: number = 0; - for (let j = 0; j < KeylayoutToKmnConverter.USED_KEYS_COUNT; j++) { - if (this.map_UkeleleKC_To_VK(j) === unique_data_Rules[k].key) { - keyNr = j; - break; - } - } - - // skip keyNr 48 (K_TAB) and 36 (K_ENTER) - if ((keyNr === 48) || (keyNr === 36)) { - continue; - } - - //--------------------------------------------------------------------------------------------- - - // add a line after rules of each key - if ((k > 1) && (unique_data_Rules[k - 1].key !== unique_data_Rules[k].key) && (unique_data_Rules[k - 1].rule_type === unique_data_Rules[k].rule_type)) { - data += '\n'; - } - - const warn_text = this.reviewRules(unique_data_Rules, k); - - const output_character = new TextDecoder().decode(unique_data_Rules[k].output); - const output_character_unicode = this.convertToUnicodeCodePoint(output_character); - - // if we are about to print a unicode codepoint instead of a single character we need to check if it is a control character - if ((output_character_unicode.length > 1) - && (Number("0x" + output_character_unicode.substring(2, output_character_unicode.length)) < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER)) { - if (warn_text[2] == "") - warn_text[2] = warn_text[2] + "c WARNING: use of a control character "; - else - warn_text[2] = warn_text[2] + " Use of a control character "; - } - - // add a warning in front of rules in case unavailable modifiers or ambiguous rules are used - // if warning contains duplicate rules we do not write out the entire rule - // (even if there are other warnings for the same rule) since that rule had been written before - if ((warn_text[2].indexOf("duplicate") < 0)) { - - let warningTextToWrite = ""; - if (!KeylayoutToKmnConverter.SKIP_COMMENTED_LINES && (warn_text[2].length > 0)) { - warningTextToWrite = warn_text[2]; - } - - if (!((warn_text[2].length > 0) && KeylayoutToKmnConverter.SKIP_COMMENTED_LINES)) { - data += warningTextToWrite - + "+ [" - + (unique_data_Rules[k].modifier_key + ' ' + unique_data_Rules[k].key).trim() - + `] > \'` - + output_character_unicode - + '\'\n'; - } - } - } - } - - //................................................ C2 ................................................................... - for (let k = 0; k < unique_data_Rules.length; k++) { - - if (unique_data_Rules[k].rule_type === "C2") { - - const warn_text = this.reviewRules(unique_data_Rules, k); - - const output_character = new TextDecoder().decode(unique_data_Rules[k].output); - const output_character_unicode = this.convertToUnicodeCodePoint(output_character); - - // if we are about to print a unicode codepoint instead of a single character we need to check if it is a control character - if ((output_character_unicode.length > 1) - && (Number("0x" + output_character_unicode.substring(2, output_character_unicode.length)) < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER)) { - if (warn_text[2] == "") - warn_text[2] = warn_text[2] + "c WARNING: use of a control character "; - else - warn_text[2] = warn_text[2] + "; Use of a control character "; - } - - // add a warning in front of rules in case unavailable modifiers or ambiguous rules are used - // if warning contains duplicate rules we do not write out the entire rule - // (even if there are other warnings for the same rule) since that rule had been written before - if ((warn_text[1].indexOf("duplicate") < 0)) { - - let warningTextToWrite = ""; - if (!KeylayoutToKmnConverter.SKIP_COMMENTED_LINES && (warn_text[1].length > 0)) { - warningTextToWrite = warn_text[1]; - } - - if (!((warn_text[1].length > 0) && KeylayoutToKmnConverter.SKIP_COMMENTED_LINES)) { - data += warningTextToWrite - + "+ [" + (unique_data_Rules[k].modifier_deadkey + " " - + unique_data_Rules[k].deadkey).trim() - + "] > dk(A" + String(unique_data_Rules[k].id_deadkey) - + ")\n"; - } - } - - if ((warn_text[2].indexOf("duplicate") < 0)) { - - let warningTextToWrite = ""; - if (!KeylayoutToKmnConverter.SKIP_COMMENTED_LINES && (warn_text[2].length > 0)) { - warningTextToWrite = warn_text[2]; - } - - if (!((warn_text[2].length > 0) && KeylayoutToKmnConverter.SKIP_COMMENTED_LINES)) { - data += warningTextToWrite - + "dk(A" - + (String(unique_data_Rules[k].id_deadkey) + ") + [" - + unique_data_Rules[k].modifier_key).trim() - + " " - + unique_data_Rules[k].key + "] > \'" - + output_character_unicode - + "\'\n"; - } - data += "\n"; - } - } - } - - //................................................ C3 ................................................................... - - for (let k = 0; k < unique_data_Rules.length; k++) { - if (unique_data_Rules[k].rule_type === "C3") { - - const warn_text = this.reviewRules(unique_data_Rules, k); - - const output_character = new TextDecoder().decode(unique_data_Rules[k].output); - const output_character_unicode = this.convertToUnicodeCodePoint(output_character); - - // if we are about to print a unicode codepoint instead of a single character we need to check if a control character is to be used - if ((output_character_unicode.length > 1) - && (Number("0x" + output_character_unicode.substring(2, output_character_unicode.length)) < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER)) { - if (warn_text[2] == "") - warn_text[2] = warn_text[2] + "c WARNING: use of a control character "; - else - warn_text[2] = warn_text[2] + "; Use of a control character "; - } - - // add a warning in front of rules in case unavailable modifiers or ambiguous rules are used - // if warning contains duplicate rules we do not write out the entire rule - // (even if there are other warnings for the same rule) since that rule had been written before - if ((warn_text[0].indexOf("duplicate") < 0)) { - - - let warningTextToWrite = ""; - if (!KeylayoutToKmnConverter.SKIP_COMMENTED_LINES && (warn_text[0].length > 0)) { - warningTextToWrite = warn_text[0]; - } - - if (!((warn_text[0].length > 0) && KeylayoutToKmnConverter.SKIP_COMMENTED_LINES)) { - data += warningTextToWrite - + "+ [" - + (unique_data_Rules[k].modifier_prev_deadkey + " " - + unique_data_Rules[k].prev_deadkey).trim() - + "] > dk(A" - + String(unique_data_Rules[k].id_prev_deadkey) + ")\n"; - } - } - - - - - if ((warn_text[1].indexOf("duplicate") < 0)) { - - let warningTextToWrite = ""; - if (!KeylayoutToKmnConverter.SKIP_COMMENTED_LINES && (warn_text[1].length > 0)) { - warningTextToWrite = warn_text[1]; - } - - if (!((warn_text[1].length > 0) && KeylayoutToKmnConverter.SKIP_COMMENTED_LINES)) { - data += warningTextToWrite - + "dk(A" + (String(unique_data_Rules[k].id_prev_deadkey) + ") + [" - + unique_data_Rules[k].modifier_deadkey).trim() - + " " - + unique_data_Rules[k].deadkey - + "] > dk(B" - + String(unique_data_Rules[k].id_deadkey) - + ")\n"; - } - } - - if ((warn_text[2].indexOf("duplicate") < 0)) { - - let warningTextToWrite = ""; - if (!KeylayoutToKmnConverter.SKIP_COMMENTED_LINES && (warn_text[2].length > 0)) { - warningTextToWrite = warn_text[2]; - } - - if (!((warn_text[2].length > 0) && KeylayoutToKmnConverter.SKIP_COMMENTED_LINES)) { - data += warningTextToWrite + "dk(B" - + (String(unique_data_Rules[k].id_deadkey) - + ") + [" - + unique_data_Rules[k].modifier_key).trim() - + " " - + unique_data_Rules[k].key - + "] > \'" - + output_character_unicode - + "\'\n"; - } - } - - if ((warn_text[0].indexOf("duplicate") < 0) || (warn_text[1].indexOf("duplicate") < 0) || (warn_text[2].indexOf("duplicate") < 0)) { - data += "\n"; - } - } - } - return data; - } - /** * @brief member function to map Ukelele keycodes to Windows Keycodes * @param pos Ukelele (=mac) keycodes diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts new file mode 100644 index 00000000000..2a7702ea384 --- /dev/null +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts @@ -0,0 +1,318 @@ +/* + * Keyman is 2025 copyright (C) SIL International. MIT License. + * + * Write Keyman .kmn files + * + */ + +import { CompilerCallbacks, CompilerOptions } from "@keymanapp/developer-utils"; +import { KeylayoutToKmnConverter, convert_object, rule_object } from './keylayout-to-kmn-converter.js'; + +export class KmnFileWriter { + + constructor(private callbacks: CompilerCallbacks, private options: CompilerOptions) { }; + + /** + * @brief member function to write data from object to a kmn file + * @param data_ukelele the array holding all keyboard data + * @param outputfilename the file that will be written; if no outputfilename is given an outputfilename will be created from data_ukelele.keylayout_filename + * @return true if data has been written; false if not + */ + public write(data_ukelele: convert_object): boolean { + + let data: string = "\n"; + + // add top part of kmn file: STORES + data += this.writeData_Stores(data_ukelele); + + // add bottom part of kmn file: RULES + data += this.writeData_Rules(data_ukelele); + + try { + this.callbacks.fs.writeFileSync(data_ukelele.kmn_filename, new TextEncoder().encode(data)); + return true; + } catch (err) { + console.log('ERROR writing kmn file:' + err.message); + return false; + } + } + + /** + * @brief member function to create data for stores that will be printed to the resulting kmn file + * @param data_ukelele an object containing all data read from a .keylayout file + * @return string - all stores to be printed + */ + public writeData_Stores(data_ukelele: convert_object): string { + + let data: string = ""; + data += "c ......................................................................\n"; + data += "c ......................................................................\n"; + data += "c Keyman keyboard generated by kmn-convert\n"; + data += "c from Ukelele file: " + data_ukelele.keylayout_filename + "\n"; + data += "c ......................................................................\n"; + data += "c ......................................................................\n"; + data += "\n"; + + data += "store(&VERSION) \'10.0\'\n"; + data += "store(&TARGETS) \'any\'\n"; + data += "store(&KEYBOARDVERSION) \'1.0\'\n"; + data += "store(©RIGHT) '© 2024 SIL International\'\n"; + + data += "\n"; + data += "begin Unicode > use(main)\n\n"; + data += "group(main) using keys\n\n"; + + data += "\n"; + return data; + } + + /** + * @brief member function to create data from rules that will be printed to the resulting kmn file + * @param data_ukelele an object containing all data read from a .keylayout file + * @return string - all rules to be printed + */ + public writeData_Rules(data_ukelele: convert_object): string { + + const keylayoutKmnConverter = new KeylayoutToKmnConverter(this.callbacks, this.options); + let data: string = ""; + + // filter array of all rules and remove duplicates + const unique_data_Rules: rule_object[] = data_ukelele.arrayOf_Rules.filter((curr) => { + return (!(curr.output === new TextEncoder().encode("") || curr.output === undefined) + && (curr.key !== "") + && ((curr.rule_type === "C0") + || (curr.rule_type === "C1") + || (curr.rule_type === "C2" && (curr.deadkey !== "")) + || (curr.rule_type === "C3" && (curr.deadkey !== "") && (curr.prev_deadkey !== ""))) + ); + }).reduce((unique, o) => { + if (!unique.some((obj: rule_object) => + new TextDecoder().decode(obj.output) === new TextDecoder().decode(o.output) + + && obj.output !== new TextEncoder().encode("") + + && obj.rule_type === o.rule_type + && obj.modifier_key === o.modifier_key + && obj.key === o.key + + && obj.modifier_deadkey === o.modifier_deadkey + && obj.deadkey === o.deadkey + + && obj.modifier_prev_deadkey === o.modifier_prev_deadkey + && obj.prev_deadkey === o.prev_deadkey) + ) { + unique.push(o); + } + return unique; + }, []); + + //................................................ C0 C1 ................................................................ + + for (let k = 0; k < unique_data_Rules.length; k++) { + + if ((unique_data_Rules[k].rule_type === "C0") || (unique_data_Rules[k].rule_type === "C1")) { + + // lookup key nr of the key which is being processed + let keyNr: number = 0; + for (let j = 0; j < KeylayoutToKmnConverter.USED_KEYS_COUNT; j++) { + if (keylayoutKmnConverter.map_UkeleleKC_To_VK(j) === unique_data_Rules[k].key) { + keyNr = j; + break; + } + } + + // skip keyNr 48 (K_TAB) and 36 (K_ENTER) + if ((keyNr === 48) || (keyNr === 36)) { + continue; + } + + //--------------------------------------------------------------------------------------------- + + // add a line after rules of each key + if ((k > 1) && (unique_data_Rules[k - 1].key !== unique_data_Rules[k].key) && (unique_data_Rules[k - 1].rule_type === unique_data_Rules[k].rule_type)) { + data += '\n'; + } + + const warn_text = keylayoutKmnConverter.reviewRules(unique_data_Rules, k); + + const output_character = new TextDecoder().decode(unique_data_Rules[k].output); + const output_character_unicode = keylayoutKmnConverter.convertToUnicodeCodePoint(output_character); + + // if we are about to print a unicode codepoint instead of a single character we need to check if it is a control character + if ((output_character_unicode.length > 1) + && (Number("0x" + output_character_unicode.substring(2, output_character_unicode.length)) < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER)) { + if (warn_text[2] == "") + warn_text[2] = warn_text[2] + "c WARNING: use of a control character "; + else + warn_text[2] = warn_text[2] + " Use of a control character "; + } + + // add a warning in front of rules in case unavailable modifiers or ambiguous rules are used + // if warning contains duplicate rules we do not write out the entire rule + // (even if there are other warnings for the same rule) since that rule had been written before + if ((warn_text[2].indexOf("duplicate") < 0)) { + + let warningTextToWrite = ""; + if (!KeylayoutToKmnConverter.SKIP_COMMENTED_LINES && (warn_text[2].length > 0)) { + warningTextToWrite = warn_text[2]; + } + + if (!((warn_text[2].length > 0) && KeylayoutToKmnConverter.SKIP_COMMENTED_LINES)) { + data += warningTextToWrite + + "+ [" + + (unique_data_Rules[k].modifier_key + ' ' + unique_data_Rules[k].key).trim() + + `] > \'` + + output_character_unicode + + '\'\n'; + } + } + } + } + + //................................................ C2 ................................................................... + for (let k = 0; k < unique_data_Rules.length; k++) { + + if (unique_data_Rules[k].rule_type === "C2") { + + const warn_text = keylayoutKmnConverter.reviewRules(unique_data_Rules, k); + + const output_character = new TextDecoder().decode(unique_data_Rules[k].output); + const output_character_unicode = keylayoutKmnConverter.convertToUnicodeCodePoint(output_character); + + // if we are about to print a unicode codepoint instead of a single character we need to check if it is a control character + if ((output_character_unicode.length > 1) + && (Number("0x" + output_character_unicode.substring(2, output_character_unicode.length)) < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER)) { + if (warn_text[2] == "") + warn_text[2] = warn_text[2] + "c WARNING: use of a control character "; + else + warn_text[2] = warn_text[2] + "; Use of a control character "; + } + + // add a warning in front of rules in case unavailable modifiers or ambiguous rules are used + // if warning contains duplicate rules we do not write out the entire rule + // (even if there are other warnings for the same rule) since that rule had been written before + if ((warn_text[1].indexOf("duplicate") < 0)) { + + let warningTextToWrite = ""; + if (!KeylayoutToKmnConverter.SKIP_COMMENTED_LINES && (warn_text[1].length > 0)) { + warningTextToWrite = warn_text[1]; + } + + if (!((warn_text[1].length > 0) && KeylayoutToKmnConverter.SKIP_COMMENTED_LINES)) { + data += warningTextToWrite + + "+ [" + (unique_data_Rules[k].modifier_deadkey + " " + + unique_data_Rules[k].deadkey).trim() + + "] > dk(A" + String(unique_data_Rules[k].id_deadkey) + + ")\n"; + } + } + + if ((warn_text[2].indexOf("duplicate") < 0)) { + + let warningTextToWrite = ""; + if (!KeylayoutToKmnConverter.SKIP_COMMENTED_LINES && (warn_text[2].length > 0)) { + warningTextToWrite = warn_text[2]; + } + + if (!((warn_text[2].length > 0) && KeylayoutToKmnConverter.SKIP_COMMENTED_LINES)) { + data += warningTextToWrite + + "dk(A" + + (String(unique_data_Rules[k].id_deadkey) + ") + [" + + unique_data_Rules[k].modifier_key).trim() + + " " + + unique_data_Rules[k].key + "] > \'" + + output_character_unicode + + "\'\n"; + } + data += "\n"; + } + } + } + + //................................................ C3 ................................................................... + + for (let k = 0; k < unique_data_Rules.length; k++) { + if (unique_data_Rules[k].rule_type === "C3") { + + const warn_text = keylayoutKmnConverter.reviewRules(unique_data_Rules, k); + + const output_character = new TextDecoder().decode(unique_data_Rules[k].output); + const output_character_unicode = keylayoutKmnConverter.convertToUnicodeCodePoint(output_character); + + // if we are about to print a unicode codepoint instead of a single character we need to check if a control character is to be used + if ((output_character_unicode.length > 1) + && (Number("0x" + output_character_unicode.substring(2, output_character_unicode.length)) < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER)) { + if (warn_text[2] == "") + warn_text[2] = warn_text[2] + "c WARNING: use of a control character "; + else + warn_text[2] = warn_text[2] + "; Use of a control character "; + } + + // add a warning in front of rules in case unavailable modifiers or ambiguous rules are used + // if warning contains duplicate rules we do not write out the entire rule + // (even if there are other warnings for the same rule) since that rule had been written before + if ((warn_text[0].indexOf("duplicate") < 0)) { + + + let warningTextToWrite = ""; + if (!KeylayoutToKmnConverter.SKIP_COMMENTED_LINES && (warn_text[0].length > 0)) { + warningTextToWrite = warn_text[0]; + } + + if (!((warn_text[0].length > 0) && KeylayoutToKmnConverter.SKIP_COMMENTED_LINES)) { + data += warningTextToWrite + + "+ [" + + (unique_data_Rules[k].modifier_prev_deadkey + " " + + unique_data_Rules[k].prev_deadkey).trim() + + "] > dk(A" + + String(unique_data_Rules[k].id_prev_deadkey) + ")\n"; + } + } + + if ((warn_text[1].indexOf("duplicate") < 0)) { + + let warningTextToWrite = ""; + if (!KeylayoutToKmnConverter.SKIP_COMMENTED_LINES && (warn_text[1].length > 0)) { + warningTextToWrite = warn_text[1]; + } + + if (!((warn_text[1].length > 0) && KeylayoutToKmnConverter.SKIP_COMMENTED_LINES)) { + data += warningTextToWrite + + "dk(A" + (String(unique_data_Rules[k].id_prev_deadkey) + ") + [" + + unique_data_Rules[k].modifier_deadkey).trim() + + " " + + unique_data_Rules[k].deadkey + + "] > dk(B" + + String(unique_data_Rules[k].id_deadkey) + + ")\n"; + } + } + + if ((warn_text[2].indexOf("duplicate") < 0)) { + + let warningTextToWrite = ""; + if (!KeylayoutToKmnConverter.SKIP_COMMENTED_LINES && (warn_text[2].length > 0)) { + warningTextToWrite = warn_text[2]; + } + + if (!((warn_text[2].length > 0) && KeylayoutToKmnConverter.SKIP_COMMENTED_LINES)) { + data += warningTextToWrite + "dk(B" + + (String(unique_data_Rules[k].id_deadkey) + + ") + [" + + unique_data_Rules[k].modifier_key).trim() + + " " + + unique_data_Rules[k].key + + "] > \'" + + output_character_unicode + + "\'\n"; + } + } + + if ((warn_text[0].indexOf("duplicate") < 0) || (warn_text[1].indexOf("duplicate") < 0) || (warn_text[2].indexOf("duplicate") < 0)) { + data += "\n"; + } + } + } + return data; + } +} diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index 58ab254cfcc..4e17ab91898 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -1,5 +1,8 @@ /* - * Keyman is copyright (C) SIL International. MIT License. + * Keyman is 2025 copyright (C) SIL International. MIT License. + * + * Tests for KeylayoutToKmnConverter, KeylayoutFileReader, KmnFileWriter + * */ import 'mocha'; @@ -7,6 +10,8 @@ import { assert } from 'chai'; import { compilerTestCallbacks, compilerTestOptions } from './helpers/index.js'; import { KeylayoutToKmnConverter } from '../src/keylayout-to-kmn/keylayout-to-kmn-converter.js'; import { makePathToFixture } from './helpers/index.js'; +import { KmnFileWriter } from '../src/keylayout-to-kmn/kmn-file-writer.js'; +import { KeylayoutFileReader } from '../src/keylayout-to-kmn/keylayout-file-reader.js'; //----------------------------------------------------------------------------------------------------------------------- @@ -122,77 +127,81 @@ describe('KeylayoutToKmnConverter', function () { }); describe("read() ", function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename_unavailable = makePathToFixture('X.keylayout'); it('read() should return filled array on correct input', async function () { const inputFilename = makePathToFixture('../data/Italian.keylayout'); - const result = sut.read(inputFilename); + const result = sut_r.read(inputFilename); assert.isNotEmpty(result); }); it('read() should return empty array on null input', async function () { - const result = sut.read(null); + const result = sut_r.read(null); assert.isEmpty(result); }); it('read() should return empty array on empty input', async function () { - const result = sut.read(""); + const result = sut_r.read(""); assert.isEmpty(result); }); it('read() should return empty array on space as input', async function () { - const result = sut.read(" "); + const result = sut_r.read(" "); assert.isEmpty(result); }); it('read() should return empty array on unavailable file name', async function () { - const result = sut.read(inputFilename_unavailable); + const result = sut_r.read(inputFilename_unavailable); assert.isEmpty(result); }); it('read() should return empty array on typo in path', async function () { - const result = sut.read('../data|Italian.keylayout'); + const result = sut_r.read('../data|Italian.keylayout'); assert.isEmpty(result); }); }); describe("write() ", function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const inputFilename = makePathToFixture('../data/Italian.keylayout'); - const read = sut.read(inputFilename); + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sut_r = new KeylayoutFileReader(compilerTestCallbacks); + const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); + const read = sut_r.read(inputFilename); const converted = sut.convert(read); // empty convert_object from unavailable file name const inputFilename_unavailable = makePathToFixture('X.keylayout'); - const read_unavailable = sut.read(inputFilename_unavailable); + const read_unavailable = sut_r.read(inputFilename_unavailable); const converted_unavailable = sut.convert(read_unavailable); + it('write() should return true (no error) if written', async function () { + const result = sut_w.write(converted); + assert.isTrue(result); + }); + it('write() should return false if no inputfile', async function () { - const result = sut.write(converted_unavailable); + const result = sut_w.write(converted_unavailable); assert.isFalse(result); }); - it('write() should return true (no error) if written', async function () { - const result = sut.write(converted); - assert.isTrue(result); - }); }); describe("convert() ", function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Italian.keylayout'); - const read = sut.read(inputFilename); + const read = sut_r.read(inputFilename); const converted = sut.convert(read); // empty convert_object from unavailable file name const inputFilename_unavailable = makePathToFixture('X.keylayout'); - const read_unavailable = sut.read(inputFilename_unavailable); + const read_unavailable = sut_r.read(inputFilename_unavailable); const converted_unavailable = sut.convert(read_unavailable); // empty convert_object from empty filename const inputFilename_empty = makePathToFixture(''); - const read_empty = sut.read(inputFilename_empty); + const read_empty = sut_r.read(inputFilename_empty); const converted_empty = sut.convert(read_empty); it('should return converted array on correct input', async function () { @@ -398,8 +407,9 @@ describe('KeylayoutToKmnConverter', function () { describe("get_Modifier_array__From__KeyModifier_array ", function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Italian.keylayout'); - const read = sut.read(inputFilename); + const read = sut_r.read(inputFilename); const converted = sut.convert(read); [[[['0', 0]], [['', 'shift? caps? ']]], @@ -430,8 +440,9 @@ describe('KeylayoutToKmnConverter', function () { describe("get_KeyModifier_array__From__ActionID ", function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Italian.keylayout'); - const read = sut.read(inputFilename); + const read = sut_r.read(inputFilename); [ ["a16", [['32', 3]]], @@ -458,8 +469,9 @@ describe('KeylayoutToKmnConverter', function () { describe("get_ActionID__From__ActionNext ", function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Italian.keylayout'); - const read = sut.read(inputFilename); + const read = sut_r.read(inputFilename); [ ["none", ""], @@ -484,8 +496,9 @@ describe('KeylayoutToKmnConverter', function () { describe("get_ActionIndex__From__ActionId ", function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Italian.keylayout'); - const read = sut.read(inputFilename); + const read = sut_r.read(inputFilename); [ ["none", 0], @@ -508,8 +521,9 @@ describe('KeylayoutToKmnConverter', function () { describe("get_Output__From__ActionId_None ", function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Italian.keylayout'); - const read = sut.read(inputFilename); + const read = sut_r.read(inputFilename); [["a14", "u"], ["", ""], @@ -537,8 +551,9 @@ describe('KeylayoutToKmnConverter', function () { describe("get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array ", function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Italian.keylayout'); - const read = sut.read(inputFilename); + const read = sut_r.read(inputFilename); const b1_keycode_arr = [ ['49', 'K_SPACE', 'a0', '0', 'ˆ'], @@ -648,18 +663,20 @@ describe('KeylayoutToKmnConverter', function () { describe("writeData_Stores() ", function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sut_r = new KeylayoutFileReader(compilerTestCallbacks); + const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); const inputFilename = makePathToFixture('../data/Italian.keylayout'); - const read = sut.read(inputFilename); + const read = sut_r.read(inputFilename); const converted = sut.convert(read); // empty convert_object from unavailable file name const inputFilename_unavailable = makePathToFixture('X.keylayout'); - const read_unavailable = sut.read(inputFilename_unavailable); + const read_unavailable = sut_r.read(inputFilename_unavailable); const converted_unavailable = sut.convert(read_unavailable); // empty convert_object from empty filename const inputFilename_empty = makePathToFixture(''); - const read_empty = sut.read(inputFilename_empty); + const read_empty = sut_r.read(inputFilename_empty); const converted_empty = sut.convert(read_empty); const out_expected_first: string = @@ -683,26 +700,26 @@ describe('KeylayoutToKmnConverter', function () { + "\n"; it(('writeData_Stores should return store text with filename ').padEnd(62, " ") + 'on correct input', async function () { - const written_correctName = sut.writeData_Stores(converted); + const written_correctName = sut_w.writeData_Stores(converted); assert.equal(written_correctName, (out_expected_first + converted.keylayout_filename + out_expected_last)); }); it(('writeData_Stores should return store text without filename ').padEnd(62, " ") + 'on empty input', async function () { - const written_emptyName = sut.writeData_Stores(converted_empty); + const written_emptyName = sut_w.writeData_Stores(converted_empty); assert.equal(written_emptyName, (out_expected_first + out_expected_last)); }); it(('writeData_Stores should return store text without filename ').padEnd(62, " ") + 'on only filename as input', async function () { - const written_onlyName = sut.writeData_Stores(converted_unavailable); + const written_onlyName = sut_w.writeData_Stores(converted_unavailable); assert.equal(written_onlyName, (out_expected_first + converted_unavailable.keylayout_filename + out_expected_last)); }); }); describe("get_ActionStateOutput_array__From__ActionState ", function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Italian.keylayout'); - const read = sut.read(inputFilename); + const read = sut_r.read(inputFilename); [["1", [ ['a0', '1', 'ˆ'], @@ -745,10 +762,10 @@ describe('KeylayoutToKmnConverter', function () { }); describe("get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput ", function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Italian.keylayout'); - const read = sut.read(inputFilename); + const read = sut_r.read(inputFilename); const converted = sut.convert(read); [ @@ -783,8 +800,9 @@ describe('KeylayoutToKmnConverter', function () { describe("get_KeyActionOutput_array__From__ActionStateOutput_array ", function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Italian.keylayout'); - const read = sut.read(inputFilename); + const read = sut_r.read(inputFilename); const b6_actionId_arr = [ ['a0', '1', 'ˆ'], From ba129201953e747855995d946ceafffb52e5679c Mon Sep 17 00:00:00 2001 From: Sabine Date: Thu, 3 Apr 2025 15:10:19 +0200 Subject: [PATCH 083/251] feat(developer): move tests for kmn-file-writer and keylayout-file-reader in separate testfiles --- .../keylayout-to-kmn-converter.ts | 527 +---------------- .../src/keylayout-to-kmn/kmn-file-writer.ts | 531 +++++++++++++++++- .../test/keylayout-to-kmn-converter.tests.ts | 311 +++++----- .../kmc-convert/test/kmn-file-reader.tests.ts | 56 ++ .../kmc-convert/test/kmn-file-writer.tests.ts | 181 ++++++ 5 files changed, 900 insertions(+), 706 deletions(-) create mode 100644 developer/src/kmc-convert/test/kmn-file-reader.tests.ts create mode 100644 developer/src/kmc-convert/test/kmn-file-writer.tests.ts diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index b4e94d3c710..2e67db0978d 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -112,6 +112,7 @@ export class KeylayoutToKmnConverter { data_object.keylayout_filename = jsonObj_any.keyboard['@_name'] + ".keylayout"; + //use join as in this.callbacks.path.join(process.cwd(), "data", absolutefilename.replace(/^.*[\\/]/, '')), 'utf8' if ((outputfilename === "") || (outputfilename === null)) { data_object.kmn_filename = (process.cwd() + "\\data\\" + data_object.keylayout_filename.substring(0, data_object.keylayout_filename.lastIndexOf(".")) + ".kmn"); } @@ -658,499 +659,6 @@ export class KeylayoutToKmnConverter { return iskKeymanModifier; } - /** - * @brief member function to review rules for acceptable modifiers, duplicate or ambiguous rules and return an array containing possible warnings - * definition of comparisons e.g. 1-1, 2-4, 6-6 - * see https://docs.google.com/document/d/12J3NGO6RxIthCpZDTR8FYSRjiMgXJDLwPY2z9xqKzJ0/edit?tab=t.0#heading=h.pcz8rjyrl5ug - * @param rule : rule_object[] - an array of all rules - * @param index the index of a rule in array[rule] - * @return a string[] containing possible warnings for a rule - */ - public reviewRules(rule: rule_object[], index: number): string[] { - - const warningTextArray: string[] = Array(3).fill(""); - - // ------------------------- check unavailable modifiers ------------------------- - - if ((rule[index].rule_type === "C0") || (rule[index].rule_type === "C1")) { - if (!this.isAcceptableKeymanModifier(rule[index].modifier_key)) { - warningTextArray[2] = "unavailable modifier : "; - } - } - - else if (rule[index].rule_type === "C2") { - if (!this.isAcceptableKeymanModifier(rule[index].modifier_deadkey)) { - warningTextArray[1] = "unavailable modifier : "; - warningTextArray[2] = "unavailable superior rule ( [" - + rule[index].modifier_deadkey + " " - + rule[index].deadkey - + "] > dk(A" - + rule[index].id_deadkey - + ") ) : "; - } - if (!this.isAcceptableKeymanModifier(rule[index].modifier_key)) { - warningTextArray[2] = "unavailable modifier : "; - } - } - - else if (rule[index].rule_type === "C3") { - - if (!this.isAcceptableKeymanModifier(rule[index].modifier_prev_deadkey)) { - warningTextArray[0] = "unavailable modifier : "; - warningTextArray[1] = "unavailable superior rule ( [" - + rule[index].modifier_prev_deadkey + " " - + rule[index].prev_deadkey - + "] > dk(A" - + rule[index].id_prev_deadkey - + ") ) : "; - - warningTextArray[2] = "unavailable superior rule ( [" - + rule[index].modifier_deadkey + " " - + rule[index].deadkey - + "] > dk(A" - + rule[index].id_deadkey - + ") ) : "; - } - - if (!this.isAcceptableKeymanModifier(rule[index].modifier_deadkey)) { - warningTextArray[1] = "unavailable modifier : "; - warningTextArray[2] = "unavailable superior rule ( [" - + rule[index].modifier_deadkey + " " - + rule[index].deadkey - + "] > dk(A" - + rule[index].id_deadkey - + ") ) : "; - } - - if (!this.isAcceptableKeymanModifier(rule[index].modifier_key)) { - warningTextArray[2] = "unavailable modifier : "; - } - } - - // ------------------------- check ambiguous/duplicate rules ------------------------- - - if ((rule[index].rule_type === "C0") || (rule[index].rule_type === "C1")) { - - // 1-1: + [CAPS K_N] > 'N' <-> + [CAPS K_N] > 'A' - const amb_1_1 = rule.filter((curr, idx) => - (curr.rule_type === "C0" || curr.rule_type === "C1") - && curr.modifier_prev_deadkey === "" - && curr.prev_deadkey === "" - && curr.modifier_deadkey === "" - && curr.deadkey === "" - && curr.modifier_key === rule[index].modifier_key - && curr.key === rule[index].key - && new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output) - && idx < index - ); - - // 1-1: + [CAPS K_N] > 'N' <-> + [CAPS K_N] > 'N' - const dup_1_1 = rule.filter((curr, idx) => - (curr.rule_type === "C0" || curr.rule_type === "C1") - && curr.modifier_prev_deadkey === "" - && curr.prev_deadkey === "" - && curr.modifier_deadkey === "" - && curr.deadkey === "" - && curr.modifier_key === rule[index].modifier_key - && curr.key === rule[index].key - && new TextDecoder().decode(curr.output) === new TextDecoder().decode(rule[index].output) - && idx < index - ); - - // 4-1: + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > 'Ñ' - const amb_4_1 = rule.filter((curr, idx) => - ((curr.rule_type === "C3")) - && curr.modifier_prev_deadkey === rule[index].modifier_key - && curr.prev_deadkey === rule[index].key - ); - - // 2-1: + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > 'Ñ' - const amb_2_1 = rule.filter((curr, idx) => - ((curr.rule_type === "C2")) - && curr.modifier_deadkey === rule[index].modifier_key - && curr.deadkey === rule[index].key - ); - - if (amb_4_1.length > 0) { - warningTextArray[2] = warningTextArray[2] - + ("ambiguous 4-1 rule: later: [" - + amb_4_1[0].modifier_prev_deadkey - + " " - + amb_4_1[0].prev_deadkey - + "] > dk(C" - + amb_2_1[0].id_deadkey - + ") "); - } - - if (amb_2_1.length > 0) { - warningTextArray[2] = warningTextArray[2] - + ("ambiguous 2-1 rule: later: [" - + amb_2_1[0].modifier_deadkey - + " " - + amb_2_1[0].deadkey - + "] > dk(A" - + amb_2_1[0].id_deadkey - + ") "); - } - - if (amb_1_1.length > 0) { - warningTextArray[2] = warningTextArray[2] - + ("ambiguous rule: earlier: [" - + amb_1_1[0].modifier_key - + " " - + amb_1_1[0].key - + "] > \'" - + new TextDecoder().decode(amb_1_1[0].output) - + "\' "); - } - - if (dup_1_1.length > 0) { - warningTextArray[2] = warningTextArray[2] - + ("duplicate rule: earlier: [" - + dup_1_1[0].modifier_key - + " " - + dup_1_1[0].key - + "] > \'" - + new TextDecoder().decode(dup_1_1[0].output) - + "\' "); - } - } - - if (rule[index].rule_type === "C2") { - - // 2-2: + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(C3) - const amb_2_2 = rule.filter((curr, idx) => - curr.rule_type === "C2" - && curr.modifier_deadkey === rule[index].modifier_deadkey - && curr.deadkey === rule[index].deadkey - && curr.id_deadkey !== rule[index].id_deadkey - && idx < index - ); - - // 2-2: + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(C11) - const dup_2_2 = rule.filter((curr, idx) => - curr.rule_type === "C2" - && curr.modifier_deadkey === rule[index].modifier_deadkey - && curr.deadkey === rule[index].deadkey - && curr.id_deadkey === rule[index].id_deadkey - && idx < index - ); - - //3-3: dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'B' - const amb_3_3 = rule.filter((curr, idx) => - (curr.rule_type === "C2") - && curr.id_deadkey === rule[index].id_deadkey - && curr.modifier_key === rule[index].modifier_key - && curr.key === rule[index].key - && new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output) - && idx < index - ); - - //3-3: dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'Ã' - const dup_3_3 = rule.filter((curr, idx) => - (curr.rule_type === "C2") - && curr.id_deadkey === rule[index].id_deadkey - && rule[index].unique_deadkey === 0 - && curr.modifier_key === rule[index].modifier_key - && curr.key === rule[index].key - && new TextDecoder().decode(curr.output) === new TextDecoder().decode(rule[index].output) - && idx < index - ); - - // 4-2: + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(B11) - const amb_4_2 = rule.filter((curr, idx) => - ((curr.rule_type === "C3")) - && curr.modifier_prev_deadkey === rule[index].modifier_deadkey - && curr.prev_deadkey === rule[index].deadkey - && curr.id_prev_deadkey === rule[index].id_deadkey - ); - - if (amb_2_2.length > 0) { - warningTextArray[1] = warningTextArray[1] - + ("ambiguous rule: earlier: [" - + amb_2_2[0].modifier_deadkey - + " " - + amb_2_2[0].deadkey - + "] > dk(C" - + amb_2_2[0].id_deadkey - + ") "); - } - - if (dup_2_2.length > 0) { - warningTextArray[1] = warningTextArray[1] - + ("duplicate rule: earlier: [" - + dup_2_2[0].modifier_deadkey - + " " - + dup_2_2[0].deadkey - + "] > dk(C" - + dup_2_2[0].id_deadkey - + ") "); - } - - if (amb_3_3.length > 0) { - warningTextArray[2] = warningTextArray[2] - + ("ambiguous rule: earlier: dk(A" - + amb_3_3[0].id_deadkey - + ") + [" - + amb_3_3[0].modifier_key - + " " - + amb_3_3[0].key - + "] > \'" - + new TextDecoder().decode(amb_3_3[0].output) - + "\' "); - } - - if (dup_3_3.length > 0) { - warningTextArray[2] = warningTextArray[2] - + ("duplicate rule: earlier: dk(A" - + dup_3_3[0].id_deadkey - + ") + [" - + dup_3_3[0].modifier_key - + " " - + dup_3_3[0].key - + "] > \'" - + new TextDecoder().decode(dup_3_3[0].output) - + "\' "); - } - - if (amb_4_2.length > 0) { - warningTextArray[0] = warningTextArray[0] - + ("ambiguous rule: later: [" - + amb_4_2[0].modifier_prev_deadkey - + " " - + amb_4_2[0].prev_deadkey - + "] > dk(C" - + amb_4_2[0].id_prev_deadkey - + ") "); - } - } - - if (rule[index].rule_type === "C3") { - - // 2-4 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(B11) - const amb_2_4 = rule.filter((curr, idx) => - ((curr.rule_type === "C2")) - && curr.modifier_deadkey === rule[index].modifier_prev_deadkey - && curr.deadkey === rule[index].prev_deadkey - && curr.id_deadkey === rule[index].id_prev_deadkey - ); - - // 6-3 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'B' - const amb_6_3 = rule.filter((curr, idx) => - (curr.rule_type === "C2") - && curr.id_prev_deadkey === rule[index].id_prev_deadkey - && curr.modifier_key === rule[index].modifier_key - && curr.key === rule[index].key - && (new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output)) - ); - - // 6-3 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'Ã' - const dup_6_3 = rule.filter((curr, idx) => - (curr.rule_type === "C2") - && curr.id_prev_deadkey === rule[index].id_prev_deadkey - && curr.modifier_key === rule[index].modifier_key - && curr.key === rule[index].key - && new TextDecoder().decode(curr.output) === new TextDecoder().decode(rule[index].output) - ); - - // 4-4 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(C1) - const amb_4_4 = rule.filter((curr, idx) => - curr.rule_type === "C3" - && curr.modifier_prev_deadkey === rule[index].modifier_prev_deadkey - && curr.id_prev_deadkey !== rule[index].id_prev_deadkey - && curr.prev_deadkey === rule[index].prev_deadkey - && rule[index].unique_prev_deadkey !== 0 - && idx < index - ); - - // 4-4 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(C11) - const dup_4_4 = rule.filter((curr, idx) => - curr.rule_type === "C3" - && curr.modifier_prev_deadkey === rule[index].modifier_prev_deadkey - && curr.prev_deadkey === rule[index].prev_deadkey - && curr.id_prev_deadkey === rule[index].id_prev_deadkey - && idx < index - ); - - // 5-5 - const amb_5_5 = rule.filter((curr, idx) => - (curr.rule_type === "C3") - && curr.modifier_key === rule[index].modifier_key - && curr.key === rule[index].key - && curr.id_deadkey === rule[index].id_deadkey - && (new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output)) - && idx < index - ); - - // 5-5 - const dup_5_5 = rule.filter((curr, idx) => - (curr.rule_type === "C3") - && curr.modifier_deadkey === rule[index].modifier_deadkey - && curr.deadkey === rule[index].deadkey - && curr.id_prev_deadkey === rule[index].id_prev_deadkey - && curr.id_deadkey === rule[index].id_deadkey - && rule[index].unique_deadkey === 0 - ); - - // 6-6 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'B' - const amb_6_6 = rule.filter((curr, idx) => - (curr.rule_type === "C3") - && curr.id_prev_deadkey === rule[index].id_prev_deadkey - && curr.modifier_key === rule[index].modifier_key - && curr.key === rule[index].key - && (new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output)) - && idx < index - ); - - // 6-6 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'Ã' - const dup_6_6 = rule.filter((curr, idx) => - (curr.rule_type === "C3") - && curr.id_deadkey === rule[index].id_deadkey - && curr.modifier_key === rule[index].modifier_key - && curr.key === rule[index].key - && (new TextDecoder().decode(curr.output) === new TextDecoder().decode(rule[index].output)) - && idx < index - ); - - if (amb_2_4.length > 0) { - warningTextArray[0] = warningTextArray[0] - + ("ambiguous rule: earlier: [" - + amb_2_4[0].modifier_deadkey - + " " - + amb_2_4[0].deadkey - + "] > dk(A" - + amb_2_4[0].id_deadkey - + ") "); - } - - if (amb_6_3.length > 0) { - warningTextArray[1] = warningTextArray[1] - + ("ambiguous rule: earlier: dk(C" - + amb_6_3[0].id_deadkey - + ") + [" - + amb_6_3[0].modifier_key - + " " - + amb_6_3[0].key - + "] > \'" - + new TextDecoder().decode(amb_6_3[0].output) - + "\' "); - } - - if (dup_6_3.length > 0) { - warningTextArray[1] = warningTextArray[1] - + ("duplicate rule: earlier: dk(C" - + dup_6_3[0].id_deadkey - + ") + [" - + dup_6_3[0].modifier_key - + " " - + dup_6_3[0].key - + "] > \'" - + new TextDecoder().decode(dup_6_3[0].output) - + "\' "); - } - - if (amb_4_4.length > 0) { - warningTextArray[0] = warningTextArray[0] - + ("ambiguous rule: earlier: [" - + amb_4_4[0].modifier_prev_deadkey - + " " - + amb_4_4[0].prev_deadkey - + "] > dk(C" - + amb_4_4[0].id_prev_deadkey - + ") "); - } - - if (dup_4_4.length > 0) { - warningTextArray[0] = warningTextArray[0] - + ("duplicate rule: earlier: [" - + dup_4_4[0].modifier_prev_deadkey - + " " - + dup_4_4[0].prev_deadkey - + "] > dk(C" - + dup_4_4[0].id_prev_deadkey - + ") "); - } - - if (amb_5_5.length > 0) { - warningTextArray[1] = warningTextArray[1] - + ("ambiguous rule: earlier: dk(B" - + amb_5_5[0].id_prev_deadkey - + ") + [" - + amb_5_5[0].modifier_deadkey - + " " - + amb_5_5[0].deadkey - + "] > dk(B" - + amb_5_5[0].id_deadkey - + ") "); - } - - if (dup_5_5.length > 0) { - warningTextArray[1] = warningTextArray[1] - + ("duplicate rule: earlier: dk(B" - + dup_5_5[0].id_prev_deadkey - + ") + [" - + dup_5_5[0].modifier_deadkey - + " " - + dup_5_5[0].deadkey - + "] > dk(B" - + dup_5_5[0].id_deadkey - + ") "); - } - - if (amb_6_6.length > 0) { - warningTextArray[2] = warningTextArray[2] - + ("ambiguous rule: earlier: dk(B" - + amb_6_6[0].id_deadkey - + ") + [" - + amb_6_6[0].modifier_key - + " " - + amb_6_6[0].key - + "] > \'" - + new TextDecoder().decode(amb_6_6[0].output) - + "\' "); - } - - if (dup_6_6.length > 0) { - warningTextArray[2] = warningTextArray[2] - + ("duplicate rule: earlier: dk(B" - + dup_6_6[0].id_deadkey - + ") + [" - + dup_6_6[0].modifier_key - + " " - + dup_6_6[0].key - + "] > \'" - + new TextDecoder().decode(dup_6_6[0].output) - + "\' "); - } - } - // In rare cases a rule might not be written out therefore we need to inform the user - const extra_warning = "PLEASE CHECK THE FOLLOWING RULE AS IT WILL NOT BE WRITTEN ! "; - - if (warningTextArray[0] !== "") { - warningTextArray[0] = "c WARNING: " + warningTextArray[0] + "here: "; - - if ((warningTextArray[0].indexOf("earlier:") > 0) && (warningTextArray[0].indexOf("later:") > 0)) { - warningTextArray[0] = warningTextArray[0] + extra_warning; - } - } - if (warningTextArray[1] !== "") { - warningTextArray[1] = "c WARNING: " + warningTextArray[1] + "here: "; - - if ((warningTextArray[1].indexOf("earlier:") > 0) && (warningTextArray[1].indexOf("later:") > 0)) { - warningTextArray[1] = warningTextArray[1] + extra_warning; - } - } - - if (warningTextArray[2] !== "") { - warningTextArray[2] = "c WARNING: " + warningTextArray[2] + "here: "; - - if ((warningTextArray[2].indexOf("earlier:") > 0) && (warningTextArray[2].indexOf("later:") > 0)) { - warningTextArray[2] = warningTextArray[2] + extra_warning; - } - } - return warningTextArray; - } - /** * @brief member function to map Ukelele keycodes to Windows Keycodes * @param pos Ukelele (=mac) keycodes @@ -1217,39 +725,6 @@ export class KeylayoutToKmnConverter { else return ""; } - /** - * @brief member function to return the unicode value - * @param instr the string that will converted - * @return hexadecimal value of a character - */ - public getHexFromString(instr: string): string { - return Number(instr).toString(16).slice(-6).toUpperCase().padStart(4, "0"); - } - - /** - * @brief member function to convert a numeric character reference to a unicode codepoint - * @param instr the value that will converted - * @return a unicode codepoint if instr is a numeric character reference - * instr if instr is not a numeric character reference - */ - public convertToUnicodeCodePoint(instr: string): string { - - if (instr.substring(0, 3) === "&#x") { - const num_length = instr.length - instr.indexOf("x") - 1; - const num_str = instr.substring(instr.indexOf("x") + 1, instr.length - 1); - return ("U+" + num_str.slice(-num_length).padStart(4, "0")); - } - - // if not hex: convert to hex - if ((instr.substring(0, 2) === "&#")) { - const num_length = instr.length - instr.indexOf("#") - 1; - const num_str = instr.substring(instr.indexOf("#") + 1, instr.length - 1); - return ("U+" + this.getHexFromString(num_str.slice(-num_length)).padStart(4, "0")); - } - else - return instr; - } - /** * @brief member function to return an index for a given actionID * @param data :any - an object containing all data read from a .keylayout file diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts index 2a7702ea384..a78bf68ff69 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts @@ -133,10 +133,10 @@ export class KmnFileWriter { data += '\n'; } - const warn_text = keylayoutKmnConverter.reviewRules(unique_data_Rules, k); + const warn_text = this.reviewRules(unique_data_Rules, k); const output_character = new TextDecoder().decode(unique_data_Rules[k].output); - const output_character_unicode = keylayoutKmnConverter.convertToUnicodeCodePoint(output_character); + const output_character_unicode = this.convertToUnicodeCodePoint(output_character); // if we are about to print a unicode codepoint instead of a single character we need to check if it is a control character if ((output_character_unicode.length > 1) @@ -174,10 +174,10 @@ export class KmnFileWriter { if (unique_data_Rules[k].rule_type === "C2") { - const warn_text = keylayoutKmnConverter.reviewRules(unique_data_Rules, k); + const warn_text = this.reviewRules(unique_data_Rules, k); const output_character = new TextDecoder().decode(unique_data_Rules[k].output); - const output_character_unicode = keylayoutKmnConverter.convertToUnicodeCodePoint(output_character); + const output_character_unicode = this.convertToUnicodeCodePoint(output_character); // if we are about to print a unicode codepoint instead of a single character we need to check if it is a control character if ((output_character_unicode.length > 1) @@ -234,10 +234,10 @@ export class KmnFileWriter { for (let k = 0; k < unique_data_Rules.length; k++) { if (unique_data_Rules[k].rule_type === "C3") { - const warn_text = keylayoutKmnConverter.reviewRules(unique_data_Rules, k); + const warn_text = this.reviewRules(unique_data_Rules, k); const output_character = new TextDecoder().decode(unique_data_Rules[k].output); - const output_character_unicode = keylayoutKmnConverter.convertToUnicodeCodePoint(output_character); + const output_character_unicode = this.convertToUnicodeCodePoint(output_character); // if we are about to print a unicode codepoint instead of a single character we need to check if a control character is to be used if ((output_character_unicode.length > 1) @@ -315,4 +315,523 @@ export class KmnFileWriter { } return data; } + + /** + * @brief member function to review rules for acceptable modifiers, duplicate or ambiguous rules and return an array containing possible warnings + * definition of comparisons e.g. 1-1, 2-4, 6-6 + * see https://docs.google.com/document/d/12J3NGO6RxIthCpZDTR8FYSRjiMgXJDLwPY2z9xqKzJ0/edit?tab=t.0#heading=h.pcz8rjyrl5ug + * @param rule : rule_object[] - an array of all rules + * @param index the index of a rule in array[rule] + * @return a string[] containing possible warnings for a rule + */ + public reviewRules(rule: rule_object[], index: number): string[] { + + const keylayoutKmnConverter = new KeylayoutToKmnConverter(this.callbacks, this.options); + const warningTextArray: string[] = Array(3).fill(""); + + // ------------------------- check unavailable modifiers ------------------------- + + if ((rule[index].rule_type === "C0") || (rule[index].rule_type === "C1")) { + if (!keylayoutKmnConverter.isAcceptableKeymanModifier(rule[index].modifier_key)) { + warningTextArray[2] = "unavailable modifier : "; + } + } + + else if (rule[index].rule_type === "C2") { + if (!keylayoutKmnConverter.isAcceptableKeymanModifier(rule[index].modifier_deadkey)) { + warningTextArray[1] = "unavailable modifier : "; + warningTextArray[2] = "unavailable superior rule ( [" + + rule[index].modifier_deadkey + " " + + rule[index].deadkey + + "] > dk(A" + + rule[index].id_deadkey + + ") ) : "; + } + if (!keylayoutKmnConverter.isAcceptableKeymanModifier(rule[index].modifier_key)) { + warningTextArray[2] = "unavailable modifier : "; + } + } + + else if (rule[index].rule_type === "C3") { + + if (!keylayoutKmnConverter.isAcceptableKeymanModifier(rule[index].modifier_prev_deadkey)) { + warningTextArray[0] = "unavailable modifier : "; + warningTextArray[1] = "unavailable superior rule ( [" + + rule[index].modifier_prev_deadkey + " " + + rule[index].prev_deadkey + + "] > dk(A" + + rule[index].id_prev_deadkey + + ") ) : "; + + warningTextArray[2] = "unavailable superior rule ( [" + + rule[index].modifier_deadkey + " " + + rule[index].deadkey + + "] > dk(A" + + rule[index].id_deadkey + + ") ) : "; + } + + if (!keylayoutKmnConverter.isAcceptableKeymanModifier(rule[index].modifier_deadkey)) { + warningTextArray[1] = "unavailable modifier : "; + warningTextArray[2] = "unavailable superior rule ( [" + + rule[index].modifier_deadkey + " " + + rule[index].deadkey + + "] > dk(A" + + rule[index].id_deadkey + + ") ) : "; + } + + if (!keylayoutKmnConverter.isAcceptableKeymanModifier(rule[index].modifier_key)) { + warningTextArray[2] = "unavailable modifier : "; + } + } + + // ------------------------- check ambiguous/duplicate rules ------------------------- + + if ((rule[index].rule_type === "C0") || (rule[index].rule_type === "C1")) { + + // 1-1: + [CAPS K_N] > 'N' <-> + [CAPS K_N] > 'A' + const amb_1_1 = rule.filter((curr, idx) => + (curr.rule_type === "C0" || curr.rule_type === "C1") + && curr.modifier_prev_deadkey === "" + && curr.prev_deadkey === "" + && curr.modifier_deadkey === "" + && curr.deadkey === "" + && curr.modifier_key === rule[index].modifier_key + && curr.key === rule[index].key + && new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output) + && idx < index + ); + + // 1-1: + [CAPS K_N] > 'N' <-> + [CAPS K_N] > 'N' + const dup_1_1 = rule.filter((curr, idx) => + (curr.rule_type === "C0" || curr.rule_type === "C1") + && curr.modifier_prev_deadkey === "" + && curr.prev_deadkey === "" + && curr.modifier_deadkey === "" + && curr.deadkey === "" + && curr.modifier_key === rule[index].modifier_key + && curr.key === rule[index].key + && new TextDecoder().decode(curr.output) === new TextDecoder().decode(rule[index].output) + && idx < index + ); + + // 4-1: + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > 'Ñ' + const amb_4_1 = rule.filter((curr, idx) => + ((curr.rule_type === "C3")) + && curr.modifier_prev_deadkey === rule[index].modifier_key + && curr.prev_deadkey === rule[index].key + ); + + // 2-1: + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > 'Ñ' + const amb_2_1 = rule.filter((curr, idx) => + ((curr.rule_type === "C2")) + && curr.modifier_deadkey === rule[index].modifier_key + && curr.deadkey === rule[index].key + ); + + if (amb_4_1.length > 0) { + warningTextArray[2] = warningTextArray[2] + + ("ambiguous 4-1 rule: later: [" + + amb_4_1[0].modifier_prev_deadkey + + " " + + amb_4_1[0].prev_deadkey + + "] > dk(C" + + amb_2_1[0].id_deadkey + + ") "); + } + + if (amb_2_1.length > 0) { + warningTextArray[2] = warningTextArray[2] + + ("ambiguous 2-1 rule: later: [" + + amb_2_1[0].modifier_deadkey + + " " + + amb_2_1[0].deadkey + + "] > dk(A" + + amb_2_1[0].id_deadkey + + ") "); + } + + if (amb_1_1.length > 0) { + warningTextArray[2] = warningTextArray[2] + + ("ambiguous rule: earlier: [" + + amb_1_1[0].modifier_key + + " " + + amb_1_1[0].key + + "] > \'" + + new TextDecoder().decode(amb_1_1[0].output) + + "\' "); + } + + if (dup_1_1.length > 0) { + warningTextArray[2] = warningTextArray[2] + + ("duplicate rule: earlier: [" + + dup_1_1[0].modifier_key + + " " + + dup_1_1[0].key + + "] > \'" + + new TextDecoder().decode(dup_1_1[0].output) + + "\' "); + } + } + + if (rule[index].rule_type === "C2") { + + // 2-2: + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(C3) + const amb_2_2 = rule.filter((curr, idx) => + curr.rule_type === "C2" + && curr.modifier_deadkey === rule[index].modifier_deadkey + && curr.deadkey === rule[index].deadkey + && curr.id_deadkey !== rule[index].id_deadkey + && idx < index + ); + + // 2-2: + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(C11) + const dup_2_2 = rule.filter((curr, idx) => + curr.rule_type === "C2" + && curr.modifier_deadkey === rule[index].modifier_deadkey + && curr.deadkey === rule[index].deadkey + && curr.id_deadkey === rule[index].id_deadkey + && idx < index + ); + + //3-3: dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'B' + const amb_3_3 = rule.filter((curr, idx) => + (curr.rule_type === "C2") + && curr.id_deadkey === rule[index].id_deadkey + && curr.modifier_key === rule[index].modifier_key + && curr.key === rule[index].key + && new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output) + && idx < index + ); + + //3-3: dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'Ã' + const dup_3_3 = rule.filter((curr, idx) => + (curr.rule_type === "C2") + && curr.id_deadkey === rule[index].id_deadkey + && rule[index].unique_deadkey === 0 + && curr.modifier_key === rule[index].modifier_key + && curr.key === rule[index].key + && new TextDecoder().decode(curr.output) === new TextDecoder().decode(rule[index].output) + && idx < index + ); + + // 4-2: + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(B11) + const amb_4_2 = rule.filter((curr, idx) => + ((curr.rule_type === "C3")) + && curr.modifier_prev_deadkey === rule[index].modifier_deadkey + && curr.prev_deadkey === rule[index].deadkey + && curr.id_prev_deadkey === rule[index].id_deadkey + ); + + if (amb_2_2.length > 0) { + warningTextArray[1] = warningTextArray[1] + + ("ambiguous rule: earlier: [" + + amb_2_2[0].modifier_deadkey + + " " + + amb_2_2[0].deadkey + + "] > dk(C" + + amb_2_2[0].id_deadkey + + ") "); + } + + if (dup_2_2.length > 0) { + warningTextArray[1] = warningTextArray[1] + + ("duplicate rule: earlier: [" + + dup_2_2[0].modifier_deadkey + + " " + + dup_2_2[0].deadkey + + "] > dk(C" + + dup_2_2[0].id_deadkey + + ") "); + } + + if (amb_3_3.length > 0) { + warningTextArray[2] = warningTextArray[2] + + ("ambiguous rule: earlier: dk(A" + + amb_3_3[0].id_deadkey + + ") + [" + + amb_3_3[0].modifier_key + + " " + + amb_3_3[0].key + + "] > \'" + + new TextDecoder().decode(amb_3_3[0].output) + + "\' "); + } + + if (dup_3_3.length > 0) { + warningTextArray[2] = warningTextArray[2] + + ("duplicate rule: earlier: dk(A" + + dup_3_3[0].id_deadkey + + ") + [" + + dup_3_3[0].modifier_key + + " " + + dup_3_3[0].key + + "] > \'" + + new TextDecoder().decode(dup_3_3[0].output) + + "\' "); + } + + if (amb_4_2.length > 0) { + warningTextArray[0] = warningTextArray[0] + + ("ambiguous rule: later: [" + + amb_4_2[0].modifier_prev_deadkey + + " " + + amb_4_2[0].prev_deadkey + + "] > dk(C" + + amb_4_2[0].id_prev_deadkey + + ") "); + } + } + + if (rule[index].rule_type === "C3") { + + // 2-4 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(B11) + const amb_2_4 = rule.filter((curr, idx) => + ((curr.rule_type === "C2")) + && curr.modifier_deadkey === rule[index].modifier_prev_deadkey + && curr.deadkey === rule[index].prev_deadkey + && curr.id_deadkey === rule[index].id_prev_deadkey + ); + + // 6-3 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'B' + const amb_6_3 = rule.filter((curr, idx) => + (curr.rule_type === "C2") + && curr.id_prev_deadkey === rule[index].id_prev_deadkey + && curr.modifier_key === rule[index].modifier_key + && curr.key === rule[index].key + && (new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output)) + ); + + // 6-3 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'Ã' + const dup_6_3 = rule.filter((curr, idx) => + (curr.rule_type === "C2") + && curr.id_prev_deadkey === rule[index].id_prev_deadkey + && curr.modifier_key === rule[index].modifier_key + && curr.key === rule[index].key + && new TextDecoder().decode(curr.output) === new TextDecoder().decode(rule[index].output) + ); + + // 4-4 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(C1) + const amb_4_4 = rule.filter((curr, idx) => + curr.rule_type === "C3" + && curr.modifier_prev_deadkey === rule[index].modifier_prev_deadkey + && curr.id_prev_deadkey !== rule[index].id_prev_deadkey + && curr.prev_deadkey === rule[index].prev_deadkey + && rule[index].unique_prev_deadkey !== 0 + && idx < index + ); + + // 4-4 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(C11) + const dup_4_4 = rule.filter((curr, idx) => + curr.rule_type === "C3" + && curr.modifier_prev_deadkey === rule[index].modifier_prev_deadkey + && curr.prev_deadkey === rule[index].prev_deadkey + && curr.id_prev_deadkey === rule[index].id_prev_deadkey + && idx < index + ); + + // 5-5 + const amb_5_5 = rule.filter((curr, idx) => + (curr.rule_type === "C3") + && curr.modifier_key === rule[index].modifier_key + && curr.key === rule[index].key + && curr.id_deadkey === rule[index].id_deadkey + && (new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output)) + && idx < index + ); + + // 5-5 + const dup_5_5 = rule.filter((curr, idx) => + (curr.rule_type === "C3") + && curr.modifier_deadkey === rule[index].modifier_deadkey + && curr.deadkey === rule[index].deadkey + && curr.id_prev_deadkey === rule[index].id_prev_deadkey + && curr.id_deadkey === rule[index].id_deadkey + && rule[index].unique_deadkey === 0 + ); + + // 6-6 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'B' + const amb_6_6 = rule.filter((curr, idx) => + (curr.rule_type === "C3") + && curr.id_prev_deadkey === rule[index].id_prev_deadkey + && curr.modifier_key === rule[index].modifier_key + && curr.key === rule[index].key + && (new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output)) + && idx < index + ); + + // 6-6 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'Ã' + const dup_6_6 = rule.filter((curr, idx) => + (curr.rule_type === "C3") + && curr.id_deadkey === rule[index].id_deadkey + && curr.modifier_key === rule[index].modifier_key + && curr.key === rule[index].key + && (new TextDecoder().decode(curr.output) === new TextDecoder().decode(rule[index].output)) + && idx < index + ); + + if (amb_2_4.length > 0) { + warningTextArray[0] = warningTextArray[0] + + ("ambiguous rule: earlier: [" + + amb_2_4[0].modifier_deadkey + + " " + + amb_2_4[0].deadkey + + "] > dk(A" + + amb_2_4[0].id_deadkey + + ") "); + } + + if (amb_6_3.length > 0) { + warningTextArray[1] = warningTextArray[1] + + ("ambiguous rule: earlier: dk(C" + + amb_6_3[0].id_deadkey + + ") + [" + + amb_6_3[0].modifier_key + + " " + + amb_6_3[0].key + + "] > \'" + + new TextDecoder().decode(amb_6_3[0].output) + + "\' "); + } + + if (dup_6_3.length > 0) { + warningTextArray[1] = warningTextArray[1] + + ("duplicate rule: earlier: dk(C" + + dup_6_3[0].id_deadkey + + ") + [" + + dup_6_3[0].modifier_key + + " " + + dup_6_3[0].key + + "] > \'" + + new TextDecoder().decode(dup_6_3[0].output) + + "\' "); + } + + if (amb_4_4.length > 0) { + warningTextArray[0] = warningTextArray[0] + + ("ambiguous rule: earlier: [" + + amb_4_4[0].modifier_prev_deadkey + + " " + + amb_4_4[0].prev_deadkey + + "] > dk(C" + + amb_4_4[0].id_prev_deadkey + + ") "); + } + + if (dup_4_4.length > 0) { + warningTextArray[0] = warningTextArray[0] + + ("duplicate rule: earlier: [" + + dup_4_4[0].modifier_prev_deadkey + + " " + + dup_4_4[0].prev_deadkey + + "] > dk(C" + + dup_4_4[0].id_prev_deadkey + + ") "); + } + + if (amb_5_5.length > 0) { + warningTextArray[1] = warningTextArray[1] + + ("ambiguous rule: earlier: dk(B" + + amb_5_5[0].id_prev_deadkey + + ") + [" + + amb_5_5[0].modifier_deadkey + + " " + + amb_5_5[0].deadkey + + "] > dk(B" + + amb_5_5[0].id_deadkey + + ") "); + } + + if (dup_5_5.length > 0) { + warningTextArray[1] = warningTextArray[1] + + ("duplicate rule: earlier: dk(B" + + dup_5_5[0].id_prev_deadkey + + ") + [" + + dup_5_5[0].modifier_deadkey + + " " + + dup_5_5[0].deadkey + + "] > dk(B" + + dup_5_5[0].id_deadkey + + ") "); + } + + if (amb_6_6.length > 0) { + warningTextArray[2] = warningTextArray[2] + + ("ambiguous rule: earlier: dk(B" + + amb_6_6[0].id_deadkey + + ") + [" + + amb_6_6[0].modifier_key + + " " + + amb_6_6[0].key + + "] > \'" + + new TextDecoder().decode(amb_6_6[0].output) + + "\' "); + } + + if (dup_6_6.length > 0) { + warningTextArray[2] = warningTextArray[2] + + ("duplicate rule: earlier: dk(B" + + dup_6_6[0].id_deadkey + + ") + [" + + dup_6_6[0].modifier_key + + " " + + dup_6_6[0].key + + "] > \'" + + new TextDecoder().decode(dup_6_6[0].output) + + "\' "); + } + } + // In rare cases a rule might not be written out therefore we need to inform the user + const extra_warning = "PLEASE CHECK THE FOLLOWING RULE AS IT WILL NOT BE WRITTEN ! "; + + if (warningTextArray[0] !== "") { + warningTextArray[0] = "c WARNING: " + warningTextArray[0] + "here: "; + + if ((warningTextArray[0].indexOf("earlier:") > 0) && (warningTextArray[0].indexOf("later:") > 0)) { + warningTextArray[0] = warningTextArray[0] + extra_warning; + } + } + if (warningTextArray[1] !== "") { + warningTextArray[1] = "c WARNING: " + warningTextArray[1] + "here: "; + + if ((warningTextArray[1].indexOf("earlier:") > 0) && (warningTextArray[1].indexOf("later:") > 0)) { + warningTextArray[1] = warningTextArray[1] + extra_warning; + } + } + + if (warningTextArray[2] !== "") { + warningTextArray[2] = "c WARNING: " + warningTextArray[2] + "here: "; + + if ((warningTextArray[2].indexOf("earlier:") > 0) && (warningTextArray[2].indexOf("later:") > 0)) { + warningTextArray[2] = warningTextArray[2] + extra_warning; + } + } + return warningTextArray; + } + + /** + * @brief member function to convert a numeric character reference to a unicode codepoint e.g. &#c -> U+0063; 􏘁 -> U+10F601 + * @param instr the value that will converted + * @return a unicode codepoint if instr is a numeric character reference + * instr if instr is not a numeric character reference + */ + public convertToUnicodeCodePoint(instr: string): string { + + if (instr.substring(0, 3) === "&#x") { + const num_length = instr.length - instr.indexOf("x") - 1; + const num_str = instr.substring(instr.indexOf("x") + 1, instr.length - 1); + return ("U+" + num_str.slice(-num_length).padStart(4, "0")); + } + + // if not hex: convert to hex + if ((instr.substring(0, 2) === "&#")) { + const num_length = instr.length - instr.indexOf("#") - 1; + const num_str = instr.substring(instr.indexOf("#") + 1, instr.length - 1); + return "U+" + Number(num_str.slice(-num_length)).toString(16).slice(-6).toUpperCase().padStart(4, "0"); + } + else + return instr; + } + } diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index 4e17ab91898..dc403d2ba13 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -7,11 +7,10 @@ import 'mocha'; import { assert } from 'chai'; -import { compilerTestCallbacks, compilerTestOptions } from './helpers/index.js'; +import { compilerTestCallbacks, compilerTestOptions, makePathToFixture } from './helpers/index.js'; import { KeylayoutToKmnConverter } from '../src/keylayout-to-kmn/keylayout-to-kmn-converter.js'; -import { makePathToFixture } from './helpers/index.js'; -import { KmnFileWriter } from '../src/keylayout-to-kmn/kmn-file-writer.js'; import { KeylayoutFileReader } from '../src/keylayout-to-kmn/keylayout-file-reader.js'; +//import { rejects, doesNotReject } from "node:assert"; //----------------------------------------------------------------------------------------------------------------------- @@ -20,6 +19,140 @@ describe('KeylayoutToKmnConverter', function () { before(function () { compilerTestCallbacks.clear(); }); + /* + // always fails - the FAIL-or + async function failor() { throw Error('Foo'); } + + // always passes - the PASS-or + async function passor() { return 3; } + + describe('test of node:assert', async () => { + it('should be able test reject or not reject', async () => { + await rejects(failor); // as function + await doesNotReject(async () => await passor()); // or as async arrow function + }); + + // this should fail + it('FAILS: show that doesNotReject() works', async () => { + await doesNotReject(async () => await failor()); + }); + // this should also fail + it('FAILS: show that rejects() works', async () => { + await rejects(passor); + }); + + it('it should pass if 1+1=2', async () => { + const a = 1 + 1; + if (a === 2) + await doesNotReject(passor); + else + await rejects(failor); + }); + //------------------------------------------ + it('irgendwas', async () => { + await assert.rejects( + async () => { + throw new TypeError('Wrong value'); + }, + { + name: 'TypeError', + message: 'Wrong value', + }, + ); + }); + + + + it("should fail but it's not", async () => { + const itemId = 77; + const x = 77; + await assert.rejects( + (itemId !== x), + { message: 'abracadabra' } + ); + } + ); + + + it('rejects when given foobar', () => { + return fxnThatShouldReject(foobar) + .then( + (val) => { + assert.fail(`Should have rejected, returned with ${val} instead`) + , + (err) => { assert.equal(err.message, "Rejection reason I was expecting"); } + ); + }) ; + + const assert = require('assert').strict; + + (async () => { + assert.strictEqual(45, 46); + await assert.rejects( + async () => { + throw new TypeError('This is an Error!'); + }, + (err: any) => { + assert.strictEqual(err.name, 'TypeError'); + assert.strictEqual(err.message, 'This is an Error!'); + return true; + } + ); + })(); + + + + + (async () => { + assert.strictEqual(46, 46); + await assert.rejects( + async () => { + throw new TypeError('This is an Error!'); + }, + (error: any) => { + assert.strictEqual(error.name, 'TypeError'); + assert.strictEqual(error.message, 'This is an Error!'); + return true; + } + ); + })(); + + + + }); + */ + + // todo remove + describe('RunOneFile ', function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const inputFilename = makePathToFixture('../data/Italian.keylayout'); + sut.run(inputFilename); + assert.isTrue(true); + ; + }); + + // todo remove + describe('RunAllFiles ', function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + [ + [makePathToFixture('../data/Italian.keylayout')], + [makePathToFixture('../data/Italian_command.keylayout')], + [makePathToFixture('../data/Swiss_French.keylayout')], + [makePathToFixture('../data/Spanish.keylayout')], + [makePathToFixture('../data/Swiss_German.keylayout')], + [makePathToFixture('../data/US.keylayout')], + [makePathToFixture('../data/Polish.keylayout')], + [makePathToFixture('../data/French.keylayout')], + [makePathToFixture('../data/Latin_American.keylayout')], + /* [makePathToFixture('../data/German_complete.keylayout')],*/ + // [makePathToFixture('../data/German_complete_reduced.keylayout')], + // [makePathToFixture('../data/German_Standard.keylayout')], + ].forEach(function (files_) { + sut.run(files_[0]); + assert.isTrue(true); + }); + }); + describe("run() ", function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); @@ -33,6 +166,7 @@ describe('KeylayoutToKmnConverter', function () { threw = true; } assert.isTrue(threw); + //await rejects(async () => sut.run(null, null)); }); it('run() should throw on null input file name and empty output file name', async function () { @@ -126,67 +260,6 @@ describe('KeylayoutToKmnConverter', function () { }); - describe("read() ", function () { - const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename_unavailable = makePathToFixture('X.keylayout'); - - it('read() should return filled array on correct input', async function () { - const inputFilename = makePathToFixture('../data/Italian.keylayout'); - const result = sut_r.read(inputFilename); - assert.isNotEmpty(result); - }); - - it('read() should return empty array on null input', async function () { - const result = sut_r.read(null); - assert.isEmpty(result); - }); - - it('read() should return empty array on empty input', async function () { - const result = sut_r.read(""); - assert.isEmpty(result); - }); - - it('read() should return empty array on space as input', async function () { - const result = sut_r.read(" "); - assert.isEmpty(result); - }); - - it('read() should return empty array on unavailable file name', async function () { - const result = sut_r.read(inputFilename_unavailable); - assert.isEmpty(result); - }); - - it('read() should return empty array on typo in path', async function () { - const result = sut_r.read('../data|Italian.keylayout'); - assert.isEmpty(result); - }); - }); - - describe("write() ", function () { - const inputFilename = makePathToFixture('../data/Italian.keylayout'); - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); - const read = sut_r.read(inputFilename); - const converted = sut.convert(read); - - // empty convert_object from unavailable file name - const inputFilename_unavailable = makePathToFixture('X.keylayout'); - const read_unavailable = sut_r.read(inputFilename_unavailable); - const converted_unavailable = sut.convert(read_unavailable); - - it('write() should return true (no error) if written', async function () { - const result = sut_w.write(converted); - assert.isTrue(result); - }); - - it('write() should return false if no inputfile', async function () { - const result = sut_w.write(converted_unavailable); - assert.isFalse(result); - }); - - }); - describe("convert() ", function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); @@ -281,62 +354,6 @@ describe('KeylayoutToKmnConverter', function () { }); }); - describe('getHexFromString ', function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - - [ - ['0009', '0009'], - ['000027', '001B'], - ['00027', '001B'], - ['0027', '001B'], - ['027', '001B'], - ['27', '001B'], - ['001C', '0NAN'], - ['0000', '0000'], - ['X', '0NAN'], - ['', '0000'], - [' ', '0000'], - [123, '007B'], - [null, '0000'], - ].forEach(function (values) { - it(('should convert "' + values[0] + '"').padEnd(25, " ") + 'to "' + values[1] + '"', async function () { - const result = sut.getHexFromString(values[0] as string); - assert.equal(result, values[1]); - }); - }); - }); - - describe('convertToUnicodeCodePoint ', function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - - [ - ["􏘁", 'U+10F601'], - ["😁", 'U+1F601'], - [" ", 'U+0009'], - ["™", 'U+0099'], - ["ঙ", 'U+0999'], - ["香", 'U+9999'], - ["򙦙", 'U+99999'], - ["􏘁", 'U+10F601'], - ["😁", 'U+1F601'], - [" ", 'U+0009'], - ["c", 'U+0063'], - ["ϧ", 'U+03E7'], - ["✏", 'U+270F'], - ["𘚟", 'U+1869F'], - ['0000;', '0000;'], - ['X;', 'X;'], - ['123;', '123;'], - [';', ';'], - [' ;', ' ;'] - ].forEach(function (values) { - it(('should convert "' + values[0] + '"').padEnd(25, " ") + 'to "' + values[1] + '"', async function () { - const result = sut.convertToUnicodeCodePoint(values[0] as string); - assert.equal(result, values[1]); - }); - }); - }); - describe("isAcceptableKeymanModifier ", function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); @@ -661,60 +678,6 @@ describe('KeylayoutToKmnConverter', function () { }); }); - describe("writeData_Stores() ", function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); - const inputFilename = makePathToFixture('../data/Italian.keylayout'); - const read = sut_r.read(inputFilename); - const converted = sut.convert(read); - - // empty convert_object from unavailable file name - const inputFilename_unavailable = makePathToFixture('X.keylayout'); - const read_unavailable = sut_r.read(inputFilename_unavailable); - const converted_unavailable = sut.convert(read_unavailable); - - // empty convert_object from empty filename - const inputFilename_empty = makePathToFixture(''); - const read_empty = sut_r.read(inputFilename_empty); - const converted_empty = sut.convert(read_empty); - - const out_expected_first: string = - "c ......................................................................\n" - + "c ......................................................................\n" - + "c Keyman keyboard generated by kmn-convert\n" - + "c from Ukelele file: "; - - const out_expected_last: string = - "\n" - + "c ......................................................................\n" - + "c ......................................................................\n" - + "\n" - + "store(&VERSION) '10.0'\n" - + "store(&TARGETS) 'any'\n" - + "store(&KEYBOARDVERSION) '1.0'\n" - + "store(©RIGHT) '© 2024 SIL International'\n" - + "\n" - + "begin Unicode > use(main)\n\n" - + "group(main) using keys\n\n" - + "\n"; - - it(('writeData_Stores should return store text with filename ').padEnd(62, " ") + 'on correct input', async function () { - const written_correctName = sut_w.writeData_Stores(converted); - assert.equal(written_correctName, (out_expected_first + converted.keylayout_filename + out_expected_last)); - }); - - it(('writeData_Stores should return store text without filename ').padEnd(62, " ") + 'on empty input', async function () { - const written_emptyName = sut_w.writeData_Stores(converted_empty); - assert.equal(written_emptyName, (out_expected_first + out_expected_last)); - }); - - it(('writeData_Stores should return store text without filename ').padEnd(62, " ") + 'on only filename as input', async function () { - const written_onlyName = sut_w.writeData_Stores(converted_unavailable); - assert.equal(written_onlyName, (out_expected_first + converted_unavailable.keylayout_filename + out_expected_last)); - }); - }); - describe("get_ActionStateOutput_array__From__ActionState ", function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); diff --git a/developer/src/kmc-convert/test/kmn-file-reader.tests.ts b/developer/src/kmc-convert/test/kmn-file-reader.tests.ts new file mode 100644 index 00000000000..1cc81983b38 --- /dev/null +++ b/developer/src/kmc-convert/test/kmn-file-reader.tests.ts @@ -0,0 +1,56 @@ +/* + * Keyman is 2025 copyright (C) SIL International. MIT License. + * + * Tests for KeylayoutToKmnConverter, KeylayoutFileReader, KmnFileWriter + * + */ + +import 'mocha'; +import { assert } from 'chai'; +import { compilerTestCallbacks, makePathToFixture } from './helpers/index.js'; +import { KeylayoutFileReader } from '../src/keylayout-to-kmn/keylayout-file-reader.js'; + +//----------------------------------------------------------------------------------------------------------------------- + +describe('KeylayoutFileReader', function () { + + before(function () { + compilerTestCallbacks.clear(); + }); + + describe("read() ", function () { + const sut_r = new KeylayoutFileReader(compilerTestCallbacks); + const inputFilename_unavailable = makePathToFixture('X.keylayout'); + + it('read() should return filled array on correct input', async function () { + const inputFilename = makePathToFixture('../data/Italian.keylayout'); + const result = sut_r.read(inputFilename); + assert.isNotEmpty(result); + }); + + it('read() should return empty array on null input', async function () { + const result = sut_r.read(null); + assert.isEmpty(result); + }); + + it('read() should return empty array on empty input', async function () { + const result = sut_r.read(""); + assert.isEmpty(result); + }); + + it('read() should return empty array on space as input', async function () { + const result = sut_r.read(" "); + assert.isEmpty(result); + }); + + it('read() should return empty array on unavailable file name', async function () { + const result = sut_r.read(inputFilename_unavailable); + assert.isEmpty(result); + }); + + it('read() should return empty array on typo in path', async function () { + const result = sut_r.read('../data|Italian.keylayout'); + assert.isEmpty(result); + }); + }); +}); diff --git a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts new file mode 100644 index 00000000000..e4c83027ea6 --- /dev/null +++ b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts @@ -0,0 +1,181 @@ +/* + * Keyman is 2025 copyright (C) SIL International. MIT License. + * + * Tests for KeylayoutToKmnConverter, KeylayoutFileReader, KmnFileWriter + * + */ + +import 'mocha'; +import { assert } from 'chai'; +import { compilerTestCallbacks, compilerTestOptions, makePathToFixture } from './helpers/index.js'; +import { KeylayoutToKmnConverter } from '../src/keylayout-to-kmn/keylayout-to-kmn-converter.js'; +import { KmnFileWriter } from '../src/keylayout-to-kmn/kmn-file-writer.js'; +import { KeylayoutFileReader } from '../src/keylayout-to-kmn/keylayout-file-reader.js'; +//import { rejects, doesNotReject } from "node:assert"; + +//----------------------------------------------------------------------------------------------------------------------- + +describe('KmnFileWriter', function () { + + before(function () { + compilerTestCallbacks.clear(); + }); + + describe("write() ", function () { + const inputFilename = makePathToFixture('../data/Italian.keylayout'); + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sut_r = new KeylayoutFileReader(compilerTestCallbacks); + const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); + const read = sut_r.read(inputFilename); + const converted = sut.convert(read); + + // empty convert_object from unavailable file name + const inputFilename_unavailable = makePathToFixture('X.keylayout'); + const read_unavailable = sut_r.read(inputFilename_unavailable); + const converted_unavailable = sut.convert(read_unavailable); + + it('write() should return true (no error) if written', async function () { + const result = sut_w.write(converted); + assert.isTrue(result); + }); + + it('write() should return false if no inputfile', async function () { + const result = sut_w.write(converted_unavailable); + assert.isFalse(result); + }); + + }); + + describe("writeData_Rules() ", function () { + const inputFilename = makePathToFixture('../data/Italian.keylayout'); + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sut_r = new KeylayoutFileReader(compilerTestCallbacks); + const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); + const read = sut_r.read(inputFilename); + const converted = sut.convert(read); + + // empty convert_object from unavailable file name + const inputFilename_unavailable = makePathToFixture('X.keylayout'); + const read_unavailable = sut_r.read(inputFilename_unavailable); + const converted_unavailable = sut.convert(read_unavailable); + + it('writeData_Rules() should return true (no error) if written', async function () { + const result = sut_w.writeData_Rules(converted); + assert.isTrue(result.length>0); + }); + + it('writeData_Rules() should return false if no inputfile', async function () { + const result = sut_w.writeData_Rules(converted_unavailable); + assert.isFalse(result.length>0); + }); + + }); + + describe("writeData_Stores() ", function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sut_r = new KeylayoutFileReader(compilerTestCallbacks); + const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); + const inputFilename = makePathToFixture('../data/Italian.keylayout'); + const read = sut_r.read(inputFilename); + const converted = sut.convert(read); + + // empty convert_object from unavailable file name + const inputFilename_unavailable = makePathToFixture('X.keylayout'); + const read_unavailable = sut_r.read(inputFilename_unavailable); + const converted_unavailable = sut.convert(read_unavailable); + + // empty convert_object from empty filename + const inputFilename_empty = makePathToFixture(''); + const read_empty = sut_r.read(inputFilename_empty); + const converted_empty = sut.convert(read_empty); + + const out_expected_first: string = + "c ......................................................................\n" + + "c ......................................................................\n" + + "c Keyman keyboard generated by kmn-convert\n" + + "c from Ukelele file: "; + + const out_expected_last: string = + "\n" + + "c ......................................................................\n" + + "c ......................................................................\n" + + "\n" + + "store(&VERSION) '10.0'\n" + + "store(&TARGETS) 'any'\n" + + "store(&KEYBOARDVERSION) '1.0'\n" + + "store(©RIGHT) '© 2024 SIL International'\n" + + "\n" + + "begin Unicode > use(main)\n\n" + + "group(main) using keys\n\n" + + "\n"; + + it(('writeData_Stores should return store text with filename ').padEnd(62, " ") + 'on correct input', async function () { + const written_correctName = sut_w.writeData_Stores(converted); + assert.equal(written_correctName, (out_expected_first + converted.keylayout_filename + out_expected_last)); + }); + + it(('writeData_Stores should return store text without filename ').padEnd(62, " ") + 'on empty input', async function () { + const written_emptyName = sut_w.writeData_Stores(converted_empty); + assert.equal(written_emptyName, (out_expected_first + out_expected_last)); + }); + + it(('writeData_Stores should return store text without filename ').padEnd(62, " ") + 'on only filename as input', async function () { + const written_onlyName = sut_w.writeData_Stores(converted_unavailable); + assert.equal(written_onlyName, (out_expected_first + converted_unavailable.keylayout_filename + out_expected_last)); + }); + }); + + describe("reviewRules() ", function () { + const inputFilename = makePathToFixture('../data/Italian.keylayout'); + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sut_r = new KeylayoutFileReader(compilerTestCallbacks); + const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); + const read = sut_r.read(inputFilename); + const converted = sut.convert(read); + + // empty convert_object from unavailable file name + const inputFilename_unavailable = makePathToFixture('X.keylayout'); + const read_unavailable = sut_r.read(inputFilename_unavailable); + const converted_unavailable = sut.convert(read_unavailable); + + it('write() should return true (no error) if written', async function () { + const result = sut_w.write(converted); + assert.isTrue(result); + }); + + it('write() should return false if no inputfile', async function () { + const result = sut_w.write(converted_unavailable); + assert.isFalse(result); + }); + }); + + describe('convertToUnicodeCodePoint ', function () { + const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); + [ + ["􏘁", 'U+10F601'], + ["😁", 'U+1F601'], + [" ", 'U+0009'], + ["™", 'U+0099'], + ["ঙ", 'U+0999'], + ["香", 'U+9999'], + ["򙦙", 'U+99999'], + ["􏘁", 'U+10F601'], + ["😁", 'U+1F601'], + [" ", 'U+0009'], + ["c", 'U+0063'], + ["ϧ", 'U+03E7'], + ["✏", 'U+270F'], + ["𘚟", 'U+1869F'], + ['0000;', '0000;'], + ['X;', 'X;'], + ['123;', '123;'], + [';', ';'], + [' ;', ' ;'] + ].forEach(function (values) { + it(('should convert "' + values[0] + '"').padEnd(25, " ") + 'to "' + values[1] + '"', async function () { + const result = sut_w.convertToUnicodeCodePoint(values[0] as string); + assert.equal(result, values[1]); + }); + }); + }); +}); From 91bdddf7147c945a1f00e957f0096e0062544fd8 Mon Sep 17 00:00:00 2001 From: Sabine Date: Thu, 3 Apr 2025 16:04:22 +0200 Subject: [PATCH 084/251] feat(developer): move convertToUnicodeCodePoint to util.ts --- common/web/types/src/util/util.ts | 23 +++++++++++++ .../src/keylayout-to-kmn/kmn-file-writer.ts | 32 +++---------------- .../kmc-convert/test/kmn-file-writer.tests.ts | 11 ++++--- 3 files changed, 33 insertions(+), 33 deletions(-) diff --git a/common/web/types/src/util/util.ts b/common/web/types/src/util/util.ts index 70e1077cc5a..753718df8ca 100644 --- a/common/web/types/src/util/util.ts +++ b/common/web/types/src/util/util.ts @@ -206,6 +206,29 @@ export function describeCodepoint(ch : number) : string { return `${s} (U+${Number(ch).toString(16).toUpperCase()})`; } +/** + * @brief function to convert a numeric character reference to a unicode codepoint e.g. c -> U+0063; 􏘁 -> U+10F601 + * @param instr the value that will converted + * @return a unicode codepoint if instr is a numeric character reference + * instr if instr is not a numeric character reference + */ +export function convertToUnicodeCodePoint(instr: string): string { + + if (instr.substring(0, 3) === "&#x") { + const num_length = instr.length - instr.indexOf("x") - 1; + const num_str = instr.substring(instr.indexOf("x") + 1, instr.length - 1); + return ("U+" + num_str.slice(-num_length).padStart(4, "0")); + } + + // if not hex: convert to hex + if ((instr.substring(0, 2) === "&#")) { + const num_length = instr.length - instr.indexOf("#") - 1; + const num_str = instr.substring(instr.indexOf("#") + 1, instr.length - 1); + return "U+" + Number(num_str.slice(-num_length)).toString(16).slice(-6).toUpperCase().padStart(4, "0"); + } + else + return instr; +} export enum BadStringType { pua = 'PUA', diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts index a78bf68ff69..0479d3ea7ca 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts @@ -7,6 +7,7 @@ import { CompilerCallbacks, CompilerOptions } from "@keymanapp/developer-utils"; import { KeylayoutToKmnConverter, convert_object, rule_object } from './keylayout-to-kmn-converter.js'; +import { util } from '@keymanapp/common-types'; export class KmnFileWriter { @@ -136,7 +137,7 @@ export class KmnFileWriter { const warn_text = this.reviewRules(unique_data_Rules, k); const output_character = new TextDecoder().decode(unique_data_Rules[k].output); - const output_character_unicode = this.convertToUnicodeCodePoint(output_character); + const output_character_unicode = util.convertToUnicodeCodePoint(output_character); // if we are about to print a unicode codepoint instead of a single character we need to check if it is a control character if ((output_character_unicode.length > 1) @@ -177,7 +178,7 @@ export class KmnFileWriter { const warn_text = this.reviewRules(unique_data_Rules, k); const output_character = new TextDecoder().decode(unique_data_Rules[k].output); - const output_character_unicode = this.convertToUnicodeCodePoint(output_character); + const output_character_unicode = util.convertToUnicodeCodePoint(output_character); // if we are about to print a unicode codepoint instead of a single character we need to check if it is a control character if ((output_character_unicode.length > 1) @@ -237,7 +238,7 @@ export class KmnFileWriter { const warn_text = this.reviewRules(unique_data_Rules, k); const output_character = new TextDecoder().decode(unique_data_Rules[k].output); - const output_character_unicode = this.convertToUnicodeCodePoint(output_character); + const output_character_unicode = util.convertToUnicodeCodePoint(output_character); // if we are about to print a unicode codepoint instead of a single character we need to check if a control character is to be used if ((output_character_unicode.length > 1) @@ -809,29 +810,4 @@ export class KmnFileWriter { } return warningTextArray; } - - /** - * @brief member function to convert a numeric character reference to a unicode codepoint e.g. &#c -> U+0063; 􏘁 -> U+10F601 - * @param instr the value that will converted - * @return a unicode codepoint if instr is a numeric character reference - * instr if instr is not a numeric character reference - */ - public convertToUnicodeCodePoint(instr: string): string { - - if (instr.substring(0, 3) === "&#x") { - const num_length = instr.length - instr.indexOf("x") - 1; - const num_str = instr.substring(instr.indexOf("x") + 1, instr.length - 1); - return ("U+" + num_str.slice(-num_length).padStart(4, "0")); - } - - // if not hex: convert to hex - if ((instr.substring(0, 2) === "&#")) { - const num_length = instr.length - instr.indexOf("#") - 1; - const num_str = instr.substring(instr.indexOf("#") + 1, instr.length - 1); - return "U+" + Number(num_str.slice(-num_length)).toString(16).slice(-6).toUpperCase().padStart(4, "0"); - } - else - return instr; - } - } diff --git a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts index e4c83027ea6..063994f5305 100644 --- a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts +++ b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts @@ -7,12 +7,14 @@ import 'mocha'; import { assert } from 'chai'; +import { util } from '@keymanapp/common-types'; import { compilerTestCallbacks, compilerTestOptions, makePathToFixture } from './helpers/index.js'; import { KeylayoutToKmnConverter } from '../src/keylayout-to-kmn/keylayout-to-kmn-converter.js'; import { KmnFileWriter } from '../src/keylayout-to-kmn/kmn-file-writer.js'; import { KeylayoutFileReader } from '../src/keylayout-to-kmn/keylayout-file-reader.js'; //import { rejects, doesNotReject } from "node:assert"; + //----------------------------------------------------------------------------------------------------------------------- describe('KmnFileWriter', function () { @@ -58,15 +60,15 @@ describe('KmnFileWriter', function () { const inputFilename_unavailable = makePathToFixture('X.keylayout'); const read_unavailable = sut_r.read(inputFilename_unavailable); const converted_unavailable = sut.convert(read_unavailable); - + it('writeData_Rules() should return true (no error) if written', async function () { const result = sut_w.writeData_Rules(converted); - assert.isTrue(result.length>0); + assert.isTrue(result.length > 0); }); it('writeData_Rules() should return false if no inputfile', async function () { const result = sut_w.writeData_Rules(converted_unavailable); - assert.isFalse(result.length>0); + assert.isFalse(result.length > 0); }); }); @@ -150,7 +152,6 @@ describe('KmnFileWriter', function () { }); describe('convertToUnicodeCodePoint ', function () { - const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); [ ["􏘁", 'U+10F601'], ["😁", 'U+1F601'], @@ -173,7 +174,7 @@ describe('KmnFileWriter', function () { [' ;', ' ;'] ].forEach(function (values) { it(('should convert "' + values[0] + '"').padEnd(25, " ") + 'to "' + values[1] + '"', async function () { - const result = sut_w.convertToUnicodeCodePoint(values[0] as string); + const result = util.convertToUnicodeCodePoint(values[0] as string); assert.equal(result, values[1]); }); }); From b07202bbf00e4968744b18ef80c82b85a056e324 Mon Sep 17 00:00:00 2001 From: Sabine Date: Thu, 3 Apr 2025 17:54:52 +0200 Subject: [PATCH 085/251] feat(developer): add constant for file subfolder; rename rule_object->rules --- .../src/keylayout-to-kmn/keylayout-file-reader.ts | 4 +++- .../src/keylayout-to-kmn/keylayout-to-kmn-converter.ts | 10 +++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts index d759227947e..24f11eb827a 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts @@ -14,6 +14,8 @@ export class KeylayoutFileReader { constructor(private callbacks: CompilerCallbacks /*,private options: CompilerOptions*/) { }; + static readonly FILE_SUBFOLDER = 'data'; + /** * @brief member function to box single-entry objects into arrays * @param source the object to be changed @@ -54,7 +56,7 @@ export class KeylayoutFileReader { }; try { - xmlFile = this.callbacks.fs.readFileSync(this.callbacks.path.join(process.cwd(), "data", absolutefilename.replace(/^.*[\\/]/, '')), 'utf8'); + xmlFile = this.callbacks.fs.readFileSync(this.callbacks.path.join(process.cwd(), KeylayoutFileReader.FILE_SUBFOLDER, this.callbacks.path.basename(absolutefilename)), 'utf8'); const parser = new XMLParser(options); jsonObj = parser.parse(xmlFile); // get plain Object this.boxArray(jsonObj.keyboard); // jsonObj now contains arrays; no single fields diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 2e67db0978d..3a7ba72cece 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -97,7 +97,7 @@ export class KeylayoutToKmnConverter { public convert(jsonObj: any, outputfilename: string = ""): convert_object { const modifierBehavior: string[][] = []; // modifier for each behaviour - const rule_object: rule_object[] = []; // an array of data for a kmn rule + const rules: rule_object[] = []; // an array of data for kmn rules const jsonObj_any: any = jsonObj; const data_object: convert_object = { @@ -112,17 +112,21 @@ export class KeylayoutToKmnConverter { data_object.keylayout_filename = jsonObj_any.keyboard['@_name'] + ".keylayout"; + // this.callbacks.fs.readFileSync(this.callbacks.path.join(process.cwd(), KeylayoutFileReader.FILE_SUBFOLDER, this.callbacks.path.basename(absolutefilename)), 'utf8'); //use join as in this.callbacks.path.join(process.cwd(), "data", absolutefilename.replace(/^.*[\\/]/, '')), 'utf8' if ((outputfilename === "") || (outputfilename === null)) { + // data_object.kmn_filename = (process.cwd() + "\\data\\" + data_object.keylayout_filename.substring(0, data_object.keylayout_filename.lastIndexOf(".")) + ".kmn"); data_object.kmn_filename = (process.cwd() + "\\data\\" + data_object.keylayout_filename.substring(0, data_object.keylayout_filename.lastIndexOf(".")) + ".kmn"); } else data_object.kmn_filename = outputfilename; - console.log("RUN kmc convert - input file: ", (process.cwd() + "\\data\\" + data_object.keylayout_filename), " --> output file: ", data_object.kmn_filename); + //console.log("RUN kmc convert - input file: ", (process.cwd() + "\\data\\" + data_object.keylayout_filename), " --> output file: ", data_object.kmn_filename); + console.log("RUN kmc convert - input file: ", (this.callbacks.path.dirname(data_object.kmn_filename) + "\\" + data_object.keylayout_filename), " --> output file: ", data_object.kmn_filename); + data_object.arrayOf_Modifiers = modifierBehavior; // ukelele uses behaviours e.g. 18 modifiersCombinations in 8 KeyMapSelect(behaviors) - data_object.arrayOf_Rules = rule_object; + data_object.arrayOf_Rules = rules; // create an array of modifier combinations and store in data_object for (let j = 0; j < jsonObj.keyboard.modifierMap.keyMapSelect.length; j++) { From 2a2b214e7fcf4d11799422c0b179be0c7176be27 Mon Sep 17 00:00:00 2001 From: Sabine Date: Fri, 4 Apr 2025 18:30:06 +0200 Subject: [PATCH 086/251] feat(developer): use chai-as-promised instead of { assert } from 'chai' --- .../test/keylayout-to-kmn-converter.tests.ts | 360 ++++-------------- .../kmc-convert/test/kmn-file-reader.tests.ts | 36 +- .../kmc-convert/test/kmn-file-writer.tests.ts | 44 +-- 3 files changed, 112 insertions(+), 328 deletions(-) diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index dc403d2ba13..f78fa765fc4 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -6,261 +6,68 @@ */ import 'mocha'; -import { assert } from 'chai'; import { compilerTestCallbacks, compilerTestOptions, makePathToFixture } from './helpers/index.js'; import { KeylayoutToKmnConverter } from '../src/keylayout-to-kmn/keylayout-to-kmn-converter.js'; import { KeylayoutFileReader } from '../src/keylayout-to-kmn/keylayout-file-reader.js'; -//import { rejects, doesNotReject } from "node:assert"; +import { rejects, doesNotReject } from "node:assert"; -//----------------------------------------------------------------------------------------------------------------------- describe('KeylayoutToKmnConverter', function () { before(function () { compilerTestCallbacks.clear(); }); - /* - // always fails - the FAIL-or - async function failor() { throw Error('Foo'); } - - // always passes - the PASS-or - async function passor() { return 3; } - - describe('test of node:assert', async () => { - it('should be able test reject or not reject', async () => { - await rejects(failor); // as function - await doesNotReject(async () => await passor()); // or as async arrow function - }); - - // this should fail - it('FAILS: show that doesNotReject() works', async () => { - await doesNotReject(async () => await failor()); - }); - // this should also fail - it('FAILS: show that rejects() works', async () => { - await rejects(passor); - }); - - it('it should pass if 1+1=2', async () => { - const a = 1 + 1; - if (a === 2) - await doesNotReject(passor); - else - await rejects(failor); - }); - //------------------------------------------ - it('irgendwas', async () => { - await assert.rejects( - async () => { - throw new TypeError('Wrong value'); - }, - { - name: 'TypeError', - message: 'Wrong value', - }, - ); - }); - - - - it("should fail but it's not", async () => { - const itemId = 77; - const x = 77; - await assert.rejects( - (itemId !== x), - { message: 'abracadabra' } - ); - } - ); - - - it('rejects when given foobar', () => { - return fxnThatShouldReject(foobar) - .then( - (val) => { - assert.fail(`Should have rejected, returned with ${val} instead`) - , - (err) => { assert.equal(err.message, "Rejection reason I was expecting"); } - ); - }) ; - - const assert = require('assert').strict; - - (async () => { - assert.strictEqual(45, 46); - await assert.rejects( - async () => { - throw new TypeError('This is an Error!'); - }, - (err: any) => { - assert.strictEqual(err.name, 'TypeError'); - assert.strictEqual(err.message, 'This is an Error!'); - return true; - } - ); - })(); - - - - - (async () => { - assert.strictEqual(46, 46); - await assert.rejects( - async () => { - throw new TypeError('This is an Error!'); - }, - (error: any) => { - assert.strictEqual(error.name, 'TypeError'); - assert.strictEqual(error.message, 'This is an Error!'); - return true; - } - ); - })(); - - - - }); - */ - - // todo remove - describe('RunOneFile ', function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const inputFilename = makePathToFixture('../data/Italian.keylayout'); - sut.run(inputFilename); - assert.isTrue(true); - ; - }); - // todo remove - describe('RunAllFiles ', function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - [ - [makePathToFixture('../data/Italian.keylayout')], - [makePathToFixture('../data/Italian_command.keylayout')], - [makePathToFixture('../data/Swiss_French.keylayout')], - [makePathToFixture('../data/Spanish.keylayout')], - [makePathToFixture('../data/Swiss_German.keylayout')], - [makePathToFixture('../data/US.keylayout')], - [makePathToFixture('../data/Polish.keylayout')], - [makePathToFixture('../data/French.keylayout')], - [makePathToFixture('../data/Latin_American.keylayout')], - /* [makePathToFixture('../data/German_complete.keylayout')],*/ - // [makePathToFixture('../data/German_complete_reduced.keylayout')], - // [makePathToFixture('../data/German_Standard.keylayout')], - ].forEach(function (files_) { - sut.run(files_[0]); - assert.isTrue(true); - }); - }); - - - describe("run() ", function () { + describe('run()', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); it('run() should throw on null input file name and null output file name', async function () { - // note, could use 'chai as promised' library to make this more fluent: - let threw = false; - try { - await sut.run(null, null); - } catch { - threw = true; - } - assert.isTrue(threw); - //await rejects(async () => sut.run(null, null)); + await rejects(async () => sut.run(null, null)); }); - it('run() should throw on null input file name and empty output file name', async function () { - let threw = false; - try { - await sut.run(null, ""); - } catch { - threw = true; - } - assert.isTrue(threw); + it('run() chai as promisedshould throw on null input file name and empty output file name', async function () { + await rejects(async () => sut.run(null, "")); }); - it('run() should throw on null input file name and unknown output file name', async function () { - let threw = false; - try { - await sut.run(null, "X"); - } catch { - threw = true; - } - assert.isTrue(threw); + it('run() chai as promisedshould throw on null input file name and unknown output file name', async function () { + await rejects(async () => sut.run(null, "X")); }); it('run() should throw on unavailable input file name and null output file name', async function () { const inputFilename = makePathToFixture('../data/Unavailable.keylayout'); - let threw = false; - try { - await sut.run(inputFilename, null); - } catch { - threw = true; - } - assert.isTrue(threw); + await rejects(async () => sut.run(inputFilename, null)); }); it('run() should return on correct input file name and empty output file name ', async function () { const inputFilename = makePathToFixture('../data/Italian.keylayout'); - let threw = false; - try { - await sut.run(inputFilename, ""); - } catch { - threw = true; - } - assert.isFalse(threw); + await doesNotReject(async () => sut.run(inputFilename, "")); }); it('run() should return on correct input file name and null output file name', async function () { const inputFilename = makePathToFixture('../data/Italian.keylayout'); - let threw = false; - try { - await sut.run(inputFilename, null); - } catch { - threw = true; - } - assert.isFalse(threw); + await doesNotReject(async () => sut.run(inputFilename, null)); }); it('run() should return on correct input file name and given output file name ', async function () { const inputFilename = makePathToFixture('../data/Italian.keylayout'); const outputFilename = makePathToFixture('../../data/OutputName.kmn'); - let threw = false; - try { - await sut.run(inputFilename, outputFilename); - } catch { - threw = true; - } - assert.isFalse(threw); + await doesNotReject(async () => sut.run(inputFilename, outputFilename)); }); it('run() should throw on incorrect input file extention and output file extention', async function () { const inputFilename = makePathToFixture('../data/Italian_command.A'); const outputFilename = makePathToFixture('../../data/OutputXName.B'); - let threw = false; - try { - await sut.run(inputFilename, outputFilename); - } catch { - threw = true; - } - assert.isTrue(threw); + await rejects(async () => sut.run(inputFilename, outputFilename)); }); it('run() return on correct input file extention and unsupperted output file extention', async function () { const inputFilename = makePathToFixture('../data/Italian.keylayout'); const outputFilename = makePathToFixture('../../data/OutputXName.B'); - let threw = false; - try { - await sut.run(inputFilename, outputFilename); - } catch { - threw = true; - } - assert.isFalse(threw); + await doesNotReject(async () => sut.run(inputFilename, outputFilename)); }); - }); - describe("convert() ", function () { + describe('convert()', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Italian.keylayout'); @@ -278,19 +85,19 @@ describe('KeylayoutToKmnConverter', function () { const converted_empty = sut.convert(read_empty); it('should return converted array on correct input', async function () { - assert.isTrue(converted.arrayOf_Rules.length !== 0); + await (doesNotReject(async () => (converted.arrayOf_Rules.length !== 0))); }); it('should return empty on empty input', async function () { - assert.isTrue((converted_empty.keylayout_filename === '' + await (doesNotReject(async () => (converted_empty.keylayout_filename === '' && converted_empty.arrayOf_Modifiers.length === 0 - && converted_empty.arrayOf_Rules.length === 0)); + && converted_empty.arrayOf_Rules.length === 0))); }); it('should return empty on only name as input', async function () { - assert.isTrue((converted_unavailable.keylayout_filename === '' + await (doesNotReject(async () => (converted_unavailable.keylayout_filename === '' && converted_unavailable.arrayOf_Modifiers.length === 0 - && converted_unavailable.arrayOf_Rules.length === 0)); + && converted_unavailable.arrayOf_Rules.length === 0))); }); it('should return empty on only modifiers as input', async function () { @@ -299,9 +106,9 @@ describe('KeylayoutToKmnConverter', function () { arrayOf_Modifiers: [['caps'], ['Shift'], ['command']], arrayOf_Rules: [] }); - assert.isTrue((converted_mod.keylayout_filename === '' + await (doesNotReject(async () => (converted_mod.keylayout_filename === '' && converted_mod.arrayOf_Modifiers.length === 0 - && converted_mod.arrayOf_Rules.length === 0)); + && converted_mod.arrayOf_Rules.length === 0))); }); it('should return empty on only rules as input', async function () { @@ -310,15 +117,14 @@ describe('KeylayoutToKmnConverter', function () { arrayOf_Modifiers: [], arrayOf_Rules: [["C0", "", "", 0, 0, "", "", 0, 0, "CAPS", "K_A", "A"]] }); - assert.isTrue((converted_rule.keylayout_filename === '' + await (doesNotReject(async () => (converted_rule.keylayout_filename === '' && converted_rule.arrayOf_Modifiers.length === 0 - && converted_rule.arrayOf_Rules.length === 0)); + && converted_rule.arrayOf_Rules.length === 0))); }); }); - describe('create_kmn_modifier ', function () { + describe('create_kmn_modifier', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - [ ['shift', true, 'NCAPS SHIFT'], ['leftshift', true, 'NCAPS SHIFT'], @@ -347,16 +153,15 @@ describe('KeylayoutToKmnConverter', function () { ['leftoption', true, 'NCAPS LALT'], ['loption', true, 'NCAPS LALT'], ].forEach(function (values) { + it(('should convert "' + values[0] + '"').padEnd(36, " ") + 'to "' + values[2] + '"', async function () { - const result = sut.create_kmn_modifier(values[0] as string, values[1] as boolean); - assert.equal(result, values[2]); + await doesNotReject(async () => (sut.create_kmn_modifier(values[0] as string, values[1] as boolean) === values[2])); }); }); }); - describe("isAcceptableKeymanModifier ", function () { + describe('isAcceptableKeymanModifier', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - [ ["NCAPS", true], ["NxCAPS", false], @@ -372,16 +177,17 @@ describe('KeylayoutToKmnConverter', function () { ["", true], [null, false], ].forEach(function (values) { + it(("isAcceptableKeymanModifier(" + values[0] + ")").padEnd(38, " ") + ' should return ' + values[1], async function () { - const result = sut.isAcceptableKeymanModifier(values[0] as string); - assert.equal(result, values[1]); + await doesNotReject(async () => sut.isAcceptableKeymanModifier(values[0] as string) === values[1]); }); + + }); }); - describe("map_UkeleleKC_To_VK ", function () { + describe('map_UkeleleKC_To_VK', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - [ [0x00, "K_A"], [0x31, "K_SPACE"], @@ -394,41 +200,37 @@ describe('KeylayoutToKmnConverter', function () { [null, ""], ].forEach(function (values) { it(("map_UkeleleKC_To_VK(" + values[0] + ")").padEnd(26, " ") + "should return " + "'" + values[1] + "'", async function () { - const result = sut.map_UkeleleKC_To_VK(values[0] as number); - assert.equal(result, values[1]); + await doesNotReject(async () => sut.map_UkeleleKC_To_VK(values[0] as number) === values[1]); }); }); }); - describe("checkIfCapsIsUsed ", function () { + describe('checkIfCapsIsUsed', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - - it(("checkIfCapsIsUsed([['caps', 'xxx'], ['yyy']])").padEnd(45, " ") + " should return true", async function () { - const result = sut.checkIfCapsIsUsed([["caps", "xxx"], ["yyy"]]); - assert.isTrue(result); - }); - - it(("checkIfCapsIsUsed([['zzz', 'xxx'], ['yyy']])").padEnd(45, " ") + " should return false", async function () { - const result = sut.checkIfCapsIsUsed([["zzz", "xxx"], ["yyy"]]); - assert.isFalse(result); - }); - it(("checkIfCapsIsUsed([['', ''], ['']])").padEnd(45, " ") + " should return false", async function () { - const result = sut.checkIfCapsIsUsed([["", ""], [""]]); - assert.isFalse(result); - }); - it(("checkIfCapsIsUsed([null])").padEnd(45, " ") + " should return false", async function () { - const result = sut.checkIfCapsIsUsed([null]); - assert.isFalse(result); + [ + [[['caps', 'xxx'], ['yyy']], true], + [[['Caps', 'xxx'], ['yyy']], true], + [[['Caps?', 'xxx'], ['yyy']], true], + [[['caps?', 'xxx'], ['yyy']], true], + [[['CaPs', 'xxx'], ['yyy']], true], + [[['zzz', 'xxx'], ['yyy']], false], + [[['', ''], ['']], false], + [[null], false], + ].forEach(function (values) { + it(("checkIfCapsIsUsed(" + values[0] + ")").padEnd(26, " ") + "should return " + "'" + values[1] + "'", async function () { + await doesNotReject(async () => sut.checkIfCapsIsUsed(values[0] as string[][]) === values[1]); + }); }); }); - describe("get_Modifier_array__From__KeyModifier_array ", function () { + describe('get_Modifier_array__From__KeyModifier_array', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Italian.keylayout'); const read = sut_r.read(inputFilename); const converted = sut.convert(read); + // strings as input [[[['0', 0]], [['', 'shift? caps? ']]], [[['0', 1]], [['anyShift caps?', 'shift? rightShift caps? ', 'shift? leftShift caps? ', 'shift leftShift caps ']]], [[['0', 999]], [null]], @@ -440,27 +242,27 @@ describe('KeylayoutToKmnConverter', function () { ("get_Modifier_array__From__KeyModifier_array(['" + values[0][0][0] + "', '" + values[0][0][1] + "'])").padEnd(68, " ") + " should return ['" + values[1][0][0] + "', '" + values[1][0][1] + "']" : ("get_Modifier_array__From__KeyModifier_array(['" + values[0][0][0] + "', '" + values[0][0][1] + "'])").padEnd(68, " ") + " should return ['" + values[1][0] + "']", async function () { const result = sut.get_Modifier_array__From__KeyModifier_array(converted.arrayOf_Modifiers, values[0]); - assert.deepStrictEqual(JSON.stringify(result), JSON.stringify(values[1])); + await doesNotReject(async () => JSON.stringify(result) === JSON.stringify(values[1])); }); }); + // null, undefined or empty as input [[[[null]], [null]], [[[undefined]], [null]], [[[]], [null]], ].forEach(function (values) { it(("get_Modifier_array__From__KeyModifier_array([" + values[0][0] + "])").padEnd(68, " ") + " should return ['" + values[1][0] + "']", async function () { const result = sut.get_Modifier_array__From__KeyModifier_array(converted.arrayOf_Modifiers, values[0]); - assert.deepStrictEqual(JSON.stringify(result), JSON.stringify(values[1])); + await doesNotReject(async () => JSON.stringify(result) === JSON.stringify(values[1])); }); }); }); - describe("get_KeyModifier_array__From__ActionID ", function () { + describe('get_KeyModifier_array__From__ActionID', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Italian.keylayout'); const read = sut_r.read(inputFilename); - [ ["a16", [['32', 3]]], ["a19", [['45', 3]]], @@ -471,7 +273,6 @@ describe('KeylayoutToKmnConverter', function () { [" ", []], ["", []], ].forEach(function (values) { - let outstring = "[ "; for (let i = 0; i < values[1].length; i++) { outstring = outstring + "[ '" + values[1][i][0] + "', " + values[1][i][1].toString() + "], "; @@ -479,17 +280,16 @@ describe('KeylayoutToKmnConverter', function () { it(("get_KeyModifier_array__From__ActionID('" + values[0] + "')").padEnd(57, " ") + ' should return ' + outstring.substring(0, outstring.lastIndexOf(']') + 2) + " ]", async function () { const result = sut.get_KeyModifier_array__From__ActionID(read, String(values[0])); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + await doesNotReject(async () => JSON.stringify(result) === JSON.stringify(values[1])); }); }); }); - describe("get_ActionID__From__ActionNext ", function () { + describe('get_ActionID__From__ActionNext', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Italian.keylayout'); const read = sut_r.read(inputFilename); - [ ["none", ""], ["a18", ""], @@ -506,12 +306,12 @@ describe('KeylayoutToKmnConverter', function () { ].forEach(function (values) { it(("get_ActionID__From__ActionNext('" + values[0] + "')").padEnd(49, " ") + ' should return ' + "'" + values[1] + "'", async function () { const result = sut.get_ActionID__From__ActionNext(read, String(values[0])); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + await doesNotReject(async () => JSON.stringify(result) === JSON.stringify(values[1])); }); }); }); - describe("get_ActionIndex__From__ActionId ", function () { + describe('get_ActionIndex__From__ActionId', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Italian.keylayout'); @@ -531,12 +331,12 @@ describe('KeylayoutToKmnConverter', function () { ].forEach(function (values) { it(("get_ActionIndex__From__ActionId('" + values[0] + "')").padEnd(50, " ") + ' should return ' + values[1], async function () { const result = sut.get_ActionIndex__From__ActionId(read, String(values[0])); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + await doesNotReject(async () => JSON.stringify(result) === JSON.stringify(values[1])); }); }); }); - describe("get_Output__From__ActionId_None ", function () { + describe('get_Output__From__ActionId_None', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Italian.keylayout'); @@ -551,7 +351,7 @@ describe('KeylayoutToKmnConverter', function () { it( ("get_Output__From__ActionId_None('" + values[0] + "')").padEnd(56, " ") + ' should return ' + "'" + values[1] + "'", async function () { const result = sut.get_Output__From__ActionId_None(read, String(values[0])); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + await doesNotReject(async () => JSON.stringify(result) === JSON.stringify(values[1])); }); }); @@ -561,12 +361,12 @@ describe('KeylayoutToKmnConverter', function () { ].forEach(function (values) { it(("get_Output__From__ActionId_None('" + values[0] + "')").padEnd(56, " ") + ' should return ' + values[1], async function () { const result = sut.get_Output__From__ActionId_None(read, String(values[0])); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + await doesNotReject(async () => JSON.stringify(result) === JSON.stringify(values[1])); }); }); }); - describe("get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array ", function () { + describe('get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Italian.keylayout'); @@ -628,6 +428,7 @@ describe('KeylayoutToKmnConverter', function () { ['K_A', 'a9', '0', 'NCAPS', 'â'] ]; + // for non-empty/undefined/null and isCaps_used = true [[b1_keycode_arr, b1_modifierKey_arr], [[['49', 'K_SPACE', 'a0', '0', 'ˆ']], [['K_SPACE', 'a0', '0', 'NCAPS', 'ˆ']]], [[['49', 'K_SPACE', 'a0', '0', '']], [['K_SPACE', 'a0', '0', 'NCAPS', '']]], @@ -638,7 +439,6 @@ describe('KeylayoutToKmnConverter', function () { [[['', 'K_SPACE', 'a0', '0', 'ˆ']], [['K_SPACE', 'a0', '0', 'NCAPS', 'ˆ']]], [[['', '', '', '', '']], [['', '', '', 'NCAPS', '']]], ].forEach(function (values) { - const isCaps_used = true; const string_in = "get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(['" + "', '" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "', '" + values[0][0][3] + "', '" + values[0][0][4] + "'])"; const string_out = "['" + "', '" + values[1][0][0] + "', '" + values[1][0][1] + "', '" + values[1][0][2] + "', '" + values[1][0][3] + "', '" + values[1][0][4] + "']"; @@ -646,26 +446,27 @@ describe('KeylayoutToKmnConverter', function () { it((JSON.stringify(values[1]).length > 60) ? 'an array of objects should return an array of objectss' : string_in.padEnd(74, " ") + ' should return ' + string_out, async function () { const result = sut.get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(read, values[0], isCaps_used); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + await doesNotReject(async () => JSON.stringify(result) === JSON.stringify(values[1])); }); }); + // for non-empty/undefined/null and isCaps_used = false [[[['49', 'K_SPACE', 'a0', '0', 'ˆ']], [['K_SPACE', 'a0', '0', '', 'ˆ']]], [[['49', 'K_SPACE', 'a0', '0', '']], [['K_SPACE', 'a0', '0', '', '']]], [[['', 'K_SPACE', 'a0', '0', 'ˆ']], [['K_SPACE', 'a0', '0', '', 'ˆ']]], [[['', '', '', '', '']], [['', '', '', '', '']]], ].forEach(function (values) { - const isCaps_used = false; const string_in = "get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(['" + "', '" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "', '" + values[0][0][3] + "', '" + values[0][0][4] + "'])"; const string_out = "['" + "', '" + values[1][0][0] + "', '" + values[1][0][1] + "', '" + values[1][0][2] + "', '" + values[1][0][3] + "', '" + values[1][0][4] + "']"; it(string_in.padEnd(74, " ") + ' should return ' + string_out, async function () { const result = sut.get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(read, values[0], isCaps_used); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + await doesNotReject(async () => JSON.stringify(result) === JSON.stringify(values[1])); }); }); + // for empty/undefined/null [[[], []], [undefined, []], [null, []], @@ -673,12 +474,12 @@ describe('KeylayoutToKmnConverter', function () { const isCaps = true; it(("get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array([" + values[0] + "])").padEnd(74, " ") + ' should return ' + "[" + values[1] + "]", async function () { const result = sut.get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(read, values[0], isCaps); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + await doesNotReject(async () => JSON.stringify(result) === JSON.stringify(values[1])); }); }); }); - describe("get_ActionStateOutput_array__From__ActionState ", function () { + describe('get_ActionStateOutput_array__From__ActionState', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Italian.keylayout'); @@ -719,12 +520,12 @@ describe('KeylayoutToKmnConverter', function () { ("get_ActionStateOutput_array__From__ActionState('" + values[0] + "')").padEnd(60, " ") + ' should return an array of objects' : ("get_ActionStateOutput_array__From__ActionState('" + values[0] + "')").padEnd(60, " ") + ' should return ' + "'" + JSON.stringify(values[1]) + "'", async function () { const result = sut.get_ActionStateOutput_array__From__ActionState(read, String(values[0])); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + await doesNotReject(async () => JSON.stringify(result) === JSON.stringify(values[1])); }); }); }); - describe("get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput ", function () { + describe('get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Italian.keylayout'); @@ -756,12 +557,12 @@ describe('KeylayoutToKmnConverter', function () { ("get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput('" + values[0] + "', '" + values[1] + "', " + values[2] + ")").padEnd(67, " ") + ' should return an array of objects' : ("get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput('" + values[0] + "', '" + values[1] + "', " + values[2] + ")").padEnd(67, " ") + ' should return ' + "'" + JSON.stringify(values[3]) + "'", async function () { const result = sut.get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput(read, converted.arrayOf_Modifiers, String(values[0]), String(values[1]), Boolean(values[2])); - assert.equal(JSON.stringify(result), JSON.stringify(values[3])); + await doesNotReject(async () => JSON.stringify(result) === JSON.stringify(values[3])); }); }); }); - describe("get_KeyActionOutput_array__From__ActionStateOutput_array ", function () { + describe('get_KeyActionOutput_array__From__ActionStateOutput_array', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Italian.keylayout'); @@ -809,11 +610,11 @@ describe('KeylayoutToKmnConverter', function () { ].forEach(function (values) { it(("get_KeyActionOutput_array__From__ActionStateOutput_array([['" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "'],..])").padEnd(73, " ") + ' should return an array of objects', async function () { const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0]); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + await doesNotReject(async () => JSON.stringify(result) === JSON.stringify(values[1])); }); }); - //----------------- + //------------------------------------------------------------------------------------------------------ const oneEntryResult = [ ["49", "K_SPACE", "a0", "0", "ˆ"], ["49", "K_SPACE", "a0", "1", "ˆ"], @@ -839,31 +640,30 @@ describe('KeylayoutToKmnConverter', function () { ].forEach(function (values) { it(("get_KeyActionOutput_array__From__ActionStateOutput_array(['" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "'])").padEnd(73, " ") + ' should return an array of objects', async function () { const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0]); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + await doesNotReject(async () => JSON.stringify(result) === JSON.stringify(values[1])); }); }); - //----------------- + //------------------------------------------------------------------------------------------------------ [[[['', '1', 'ˆ']], []], [[['', '', '']], []], [[[' ', ' ', '']], []], ].forEach(function (values) { it(("get_KeyActionOutput_array__From__ActionStateOutput_array(['" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "'])").padEnd(73, " ") + ' should return ' + "'[" + values[1] + "]'", async function () { const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0]); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + await doesNotReject(async () => JSON.stringify(result) === JSON.stringify(values[1])); }); }); - //----------------- + //------------------------------------------------------------------------------------------------------ [[[], []], [undefined, []], [null, []], ].forEach(function (values) { it(("get_KeyActionOutput_array__From__ActionStateOutput_array(" + values[0] + ")").padEnd(73, " ") + ' should return ' + "'[" + values[1] + "]'", async function () { const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0]); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + await doesNotReject(async () => JSON.stringify(result) === JSON.stringify(values[1])); }); }); }); - }); diff --git a/developer/src/kmc-convert/test/kmn-file-reader.tests.ts b/developer/src/kmc-convert/test/kmn-file-reader.tests.ts index 1cc81983b38..d758f85b8a5 100644 --- a/developer/src/kmc-convert/test/kmn-file-reader.tests.ts +++ b/developer/src/kmc-convert/test/kmn-file-reader.tests.ts @@ -6,11 +6,10 @@ */ import 'mocha'; -import { assert } from 'chai'; import { compilerTestCallbacks, makePathToFixture } from './helpers/index.js'; import { KeylayoutFileReader } from '../src/keylayout-to-kmn/keylayout-file-reader.js'; +import { doesNotReject } from "node:assert"; -//----------------------------------------------------------------------------------------------------------------------- describe('KeylayoutFileReader', function () { @@ -18,39 +17,32 @@ describe('KeylayoutFileReader', function () { compilerTestCallbacks.clear(); }); - describe("read() ", function () { + describe('read()', function () { const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename_unavailable = makePathToFixture('X.keylayout'); + const empty: any = []; it('read() should return filled array on correct input', async function () { - const inputFilename = makePathToFixture('../data/Italian.keylayout'); - const result = sut_r.read(inputFilename); - assert.isNotEmpty(result); + await doesNotReject(async () => (sut_r.read(makePathToFixture('../data/Italian.keylayout')))); }); - it('read() should return empty array on null input', async function () { - const result = sut_r.read(null); - assert.isEmpty(result); + it('read() should return empty array on null input', async function () { + await doesNotReject(async () => (Array.isArray(sut_r.read(null)) === Array.isArray(empty))); }); - it('read() should return empty array on empty input', async function () { - const result = sut_r.read(""); - assert.isEmpty(result); + it('read() should return empty array on empty input', async function () { + await doesNotReject(async () => (Array.isArray(sut_r.read("")) === Array.isArray(empty))); }); - it('read() should return empty array on space as input', async function () { - const result = sut_r.read(" "); - assert.isEmpty(result); + it('read() should return empty array on space as input', async function () { + await doesNotReject(async () => (Array.isArray(sut_r.read(" ")) === Array.isArray(empty))); }); - it('read() should return empty array on unavailable file name', async function () { - const result = sut_r.read(inputFilename_unavailable); - assert.isEmpty(result); + it('read() should return empty array on unavailable file name', async function () { + await doesNotReject(async () => (Array.isArray(sut_r.read(makePathToFixture('Unavailable_InputFilename.keylayout'))) === empty)); }); - it('read() should return empty array on typo in path', async function () { - const result = sut_r.read('../data|Italian.keylayout'); - assert.isEmpty(result); + it('read() should return empty array on typo in path', async function () { + await doesNotReject(async () => (Array.isArray(sut_r.read(makePathToFixture('../data|Italian.keylayout'))) === empty)); }); }); }); diff --git a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts index 063994f5305..12dee0adc3d 100644 --- a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts +++ b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts @@ -6,13 +6,12 @@ */ import 'mocha'; -import { assert } from 'chai'; import { util } from '@keymanapp/common-types'; import { compilerTestCallbacks, compilerTestOptions, makePathToFixture } from './helpers/index.js'; import { KeylayoutToKmnConverter } from '../src/keylayout-to-kmn/keylayout-to-kmn-converter.js'; import { KmnFileWriter } from '../src/keylayout-to-kmn/kmn-file-writer.js'; import { KeylayoutFileReader } from '../src/keylayout-to-kmn/keylayout-file-reader.js'; -//import { rejects, doesNotReject } from "node:assert"; +import { doesNotReject } from 'node:assert'; //----------------------------------------------------------------------------------------------------------------------- @@ -23,7 +22,7 @@ describe('KmnFileWriter', function () { compilerTestCallbacks.clear(); }); - describe("write() ", function () { + describe('write()', function () { const inputFilename = makePathToFixture('../data/Italian.keylayout'); const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); @@ -37,18 +36,15 @@ describe('KmnFileWriter', function () { const converted_unavailable = sut.convert(read_unavailable); it('write() should return true (no error) if written', async function () { - const result = sut_w.write(converted); - assert.isTrue(result); + await doesNotReject(async () => sut_w.write(converted)); }); it('write() should return false if no inputfile', async function () { - const result = sut_w.write(converted_unavailable); - assert.isFalse(result); + await doesNotReject(async () => sut_w.write(converted_unavailable) === false); }); - }); - describe("writeData_Rules() ", function () { + describe('writeData_Rules()', function () { const inputFilename = makePathToFixture('../data/Italian.keylayout'); const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); @@ -62,18 +58,16 @@ describe('KmnFileWriter', function () { const converted_unavailable = sut.convert(read_unavailable); it('writeData_Rules() should return true (no error) if written', async function () { - const result = sut_w.writeData_Rules(converted); - assert.isTrue(result.length > 0); + await doesNotReject(async () => sut_w.writeData_Rules(converted).length > 0); }); it('writeData_Rules() should return false if no inputfile', async function () { - const result = sut_w.writeData_Rules(converted_unavailable); - assert.isFalse(result.length > 0); + await doesNotReject(async () => sut_w.writeData_Rules(converted_unavailable).length > 0); }); }); - describe("writeData_Stores() ", function () { + describe('writeData_Stores() ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); @@ -113,21 +107,22 @@ describe('KmnFileWriter', function () { it(('writeData_Stores should return store text with filename ').padEnd(62, " ") + 'on correct input', async function () { const written_correctName = sut_w.writeData_Stores(converted); - assert.equal(written_correctName, (out_expected_first + converted.keylayout_filename + out_expected_last)); + await doesNotReject(async () => (written_correctName === (out_expected_first + converted.keylayout_filename + out_expected_last))); }); it(('writeData_Stores should return store text without filename ').padEnd(62, " ") + 'on empty input', async function () { const written_emptyName = sut_w.writeData_Stores(converted_empty); - assert.equal(written_emptyName, (out_expected_first + out_expected_last)); + await doesNotReject(async () => (written_emptyName === (out_expected_first + out_expected_last))); + }); it(('writeData_Stores should return store text without filename ').padEnd(62, " ") + 'on only filename as input', async function () { const written_onlyName = sut_w.writeData_Stores(converted_unavailable); - assert.equal(written_onlyName, (out_expected_first + converted_unavailable.keylayout_filename + out_expected_last)); + await doesNotReject(async () => (written_onlyName === (out_expected_first + converted_unavailable.keylayout_filename + out_expected_last))); }); }); - describe("reviewRules() ", function () { + describe('reviewRules() ', function () { const inputFilename = makePathToFixture('../data/Italian.keylayout'); const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); @@ -140,14 +135,12 @@ describe('KmnFileWriter', function () { const read_unavailable = sut_r.read(inputFilename_unavailable); const converted_unavailable = sut.convert(read_unavailable); - it('write() should return true (no error) if written', async function () { - const result = sut_w.write(converted); - assert.isTrue(result); + it('reviewRules() should return true (no error) if written', async function () { + await doesNotReject(async () => sut_w.write(converted)); }); - it('write() should return false if no inputfile', async function () { - const result = sut_w.write(converted_unavailable); - assert.isFalse(result); + it('reviewRules() should return false if no inputfile', async function () { + await doesNotReject(async () => !sut_w.write(converted_unavailable)); }); }); @@ -174,8 +167,7 @@ describe('KmnFileWriter', function () { [' ;', ' ;'] ].forEach(function (values) { it(('should convert "' + values[0] + '"').padEnd(25, " ") + 'to "' + values[1] + '"', async function () { - const result = util.convertToUnicodeCodePoint(values[0] as string); - assert.equal(result, values[1]); + await doesNotReject(async () => util.convertToUnicodeCodePoint(values[0] as string) === values[1]); }); }); }); From b8e4a792116050a8a349b4a3dd27fa75fa91e80c Mon Sep 17 00:00:00 2001 From: Sabine Date: Tue, 8 Apr 2025 19:53:21 +0200 Subject: [PATCH 087/251] feat(developer): use NodeAssert.rejects for tests of run() only; other tests changed back to before --- .../keylayout-to-kmn-converter.ts | 37 +++-- .../src/keylayout-to-kmn/kmn-file-writer.ts | 14 +- .../test/keylayout-to-kmn-converter.tests.ts | 146 +++++++++--------- .../kmc-convert/test/kmn-file-reader.tests.ts | 36 +++-- .../kmc-convert/test/kmn-file-writer.tests.ts | 46 +++--- 5 files changed, 152 insertions(+), 127 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 3a7ba72cece..e5b2c0bcd9a 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -33,6 +33,7 @@ export interface convert_object { kmn_filename: string, arrayOf_Modifiers: string[][], arrayOf_Rules: rule_object[], + //arrayOf_Rules: any[], }; export class KeylayoutToKmnConverter { @@ -97,8 +98,8 @@ export class KeylayoutToKmnConverter { public convert(jsonObj: any, outputfilename: string = ""): convert_object { const modifierBehavior: string[][] = []; // modifier for each behaviour - const rules: rule_object[] = []; // an array of data for kmn rules - const jsonObj_any: any = jsonObj; + const rules: rule_object[] = []; // an array of data for a kmn rule + //const rules: any[] = []; // an array of data for a kmn rule const data_object: convert_object = { keylayout_filename: "", @@ -108,22 +109,23 @@ export class KeylayoutToKmnConverter { }; // ToDo in a new PR: check tags ( issue # 13599) - if (jsonObj_any.hasOwnProperty("keyboard")) { + if (jsonObj.hasOwnProperty("keyboard")) { - data_object.keylayout_filename = jsonObj_any.keyboard['@_name'] + ".keylayout"; + // get filename from data that had been read + const fileNameNoExtention = jsonObj.keyboard['@_name']; + const filePath = this.callbacks.path.join(process.cwd(), "data"); - // this.callbacks.fs.readFileSync(this.callbacks.path.join(process.cwd(), KeylayoutFileReader.FILE_SUBFOLDER, this.callbacks.path.basename(absolutefilename)), 'utf8'); - //use join as in this.callbacks.path.join(process.cwd(), "data", absolutefilename.replace(/^.*[\\/]/, '')), 'utf8' + data_object.keylayout_filename = this.callbacks.path.join(filePath, (fileNameNoExtention + ".keylayout")); + + // if no outputfile name is specified: create one from input file name if ((outputfilename === "") || (outputfilename === null)) { - // data_object.kmn_filename = (process.cwd() + "\\data\\" + data_object.keylayout_filename.substring(0, data_object.keylayout_filename.lastIndexOf(".")) + ".kmn"); - data_object.kmn_filename = (process.cwd() + "\\data\\" + data_object.keylayout_filename.substring(0, data_object.keylayout_filename.lastIndexOf(".")) + ".kmn"); + data_object.kmn_filename = this.callbacks.path.join(filePath, fileNameNoExtention + ".kmn"); } + // if outputfile name is specified: use it else data_object.kmn_filename = outputfilename; - //console.log("RUN kmc convert - input file: ", (process.cwd() + "\\data\\" + data_object.keylayout_filename), " --> output file: ", data_object.kmn_filename); - console.log("RUN kmc convert - input file: ", (this.callbacks.path.dirname(data_object.kmn_filename) + "\\" + data_object.keylayout_filename), " --> output file: ", data_object.kmn_filename); - + console.log("RUN kmc convert - input file: ", data_object.keylayout_filename, " --> output file: ", data_object.kmn_filename); data_object.arrayOf_Modifiers = modifierBehavior; // ukelele uses behaviours e.g. 18 modifiersCombinations in 8 KeyMapSelect(behaviors) data_object.arrayOf_Rules = rules; @@ -151,6 +153,7 @@ export class KeylayoutToKmnConverter { public createRuleData(data_ukelele: convert_object, jsonObj: any): convert_object { const object_array: rule_object[] = []; + // const object_array = []; let dk_counter_C3: number = 0; let dk_counter_C2: number = 0; let action_id: string; @@ -165,6 +168,7 @@ export class KeylayoutToKmnConverter { for (let i = 0; i < jsonObj.keyboard.keyMapSet[0].keyMap.length; i++) { let rule_obj: rule_object; + //let rule_obj; // ............................................................................................................................... // case C0: output ............................................................................................................... @@ -180,7 +184,7 @@ export class KeylayoutToKmnConverter { for (let l = 0; l < data_ukelele.arrayOf_Modifiers[i].length; l++) { if (this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']))) { - rule_obj = new Rules( + rule_obj = new Rule( /* rule_type */ "C0", /* modifier_prev_deadkey*/ "", @@ -224,7 +228,7 @@ export class KeylayoutToKmnConverter { for (let m = 0; m < b1_modifierKey_arr.length; m++) { - rule_obj = new Rules( + rule_obj = new Rule( /* rule_type */ "C1", /* modifier_prev_deadkey*/ "", @@ -295,7 +299,7 @@ export class KeylayoutToKmnConverter { for (let n3 = 0; n3 < b4_deadkey_arr.length; n3++) { for (let n4 = 0; n4 < b1_modifierKey_arr.length; n4++) { - rule_obj = new Rules( + rule_obj = new Rule( /* rule_type */ "C2", /* modifier_prev_deadkey*/ "", @@ -384,7 +388,7 @@ export class KeylayoutToKmnConverter { for (let n6 = 0; n6 < b4_deadkey_arr.length; n6++) { for (let n7 = 0; n7 < b1_modifierKey_arr.length; n7++) { - rule_obj = new Rules( + rule_obj = new Rule( /* rule_type */ "C3", /* modifier_prev_deadkey*/ this.create_kmn_modifier(b2_prev_deadkeyModifier_arr[n1][n2], isCapsused), /* prev_deadkey */ this.map_UkeleleKC_To_VK(Number(b2_prev_deadkey_arr[n3][0])), @@ -443,6 +447,7 @@ export class KeylayoutToKmnConverter { const list_of_unique_Text2_rules: string[][] = []; const object_array: rule_object[] = data_ukelele.arrayOf_Rules; + //const object_array = data_ukelele.arrayOf_Rules; //------------------------------------ C2: dk ---------------------------------- // first rule is always unique @@ -985,7 +990,7 @@ export class KeylayoutToKmnConverter { /** * @brief class for all storing a rule containing data for key, deadkey, previous deadkey, output) */ -class Rules { +class Rule { constructor( public rule_type: string, /* C0, C1, C2, C3, or C4 */ diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts index 0479d3ea7ca..833e17b9938 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts @@ -6,7 +6,8 @@ */ import { CompilerCallbacks, CompilerOptions } from "@keymanapp/developer-utils"; -import { KeylayoutToKmnConverter, convert_object, rule_object } from './keylayout-to-kmn-converter.js'; +//import { KeylayoutToKmnConverter, convert_object, rule_object } from './keylayout-to-kmn-converter.js'; +import { KeylayoutToKmnConverter, convert_object } from './keylayout-to-kmn-converter.js'; import { util } from '@keymanapp/common-types'; export class KmnFileWriter { @@ -78,7 +79,8 @@ export class KmnFileWriter { let data: string = ""; // filter array of all rules and remove duplicates - const unique_data_Rules: rule_object[] = data_ukelele.arrayOf_Rules.filter((curr) => { + //const unique_data_Rules: rule_object[] = data_ukelele.arrayOf_Rules.filter((curr) => { + const unique_data_Rules: any[] = data_ukelele.arrayOf_Rules.filter((curr) => { return (!(curr.output === new TextEncoder().encode("") || curr.output === undefined) && (curr.key !== "") && ((curr.rule_type === "C0") @@ -87,11 +89,10 @@ export class KmnFileWriter { || (curr.rule_type === "C3" && (curr.deadkey !== "") && (curr.prev_deadkey !== ""))) ); }).reduce((unique, o) => { - if (!unique.some((obj: rule_object) => + // if (!unique.some((obj: rule_object) => + if (!unique.some((obj: any) => new TextDecoder().decode(obj.output) === new TextDecoder().decode(o.output) - && obj.output !== new TextEncoder().encode("") - && obj.rule_type === o.rule_type && obj.modifier_key === o.modifier_key && obj.key === o.key @@ -325,7 +326,8 @@ export class KmnFileWriter { * @param index the index of a rule in array[rule] * @return a string[] containing possible warnings for a rule */ - public reviewRules(rule: rule_object[], index: number): string[] { + //public reviewRules(rule: rule_object[], index: number): string[] { + public reviewRules(rule: any[], index: number): string[] { const keylayoutKmnConverter = new KeylayoutToKmnConverter(this.callbacks, this.options); const warningTextArray: string[] = Array(3).fill(""); diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index f78fa765fc4..1a3ad760615 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -6,11 +6,11 @@ */ import 'mocha'; +import { assert } from 'chai'; import { compilerTestCallbacks, compilerTestOptions, makePathToFixture } from './helpers/index.js'; import { KeylayoutToKmnConverter } from '../src/keylayout-to-kmn/keylayout-to-kmn-converter.js'; import { KeylayoutFileReader } from '../src/keylayout-to-kmn/keylayout-file-reader.js'; -import { rejects, doesNotReject } from "node:assert"; - +import * as NodeAssert from 'node:assert'; describe('KeylayoutToKmnConverter', function () { @@ -18,56 +18,57 @@ describe('KeylayoutToKmnConverter', function () { compilerTestCallbacks.clear(); }); - describe('run()', function () { + describe('run() ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); it('run() should throw on null input file name and null output file name', async function () { - await rejects(async () => sut.run(null, null)); + // note, could use 'chai as promised' library to make this more fluent: + await NodeAssert.rejects(async () => sut.run(null, null)); }); - it('run() chai as promisedshould throw on null input file name and empty output file name', async function () { - await rejects(async () => sut.run(null, "")); + it('run() should throw on null input file name and empty output file name', async function () { + await NodeAssert.rejects(async () => sut.run(null, "")); }); - it('run() chai as promisedshould throw on null input file name and unknown output file name', async function () { - await rejects(async () => sut.run(null, "X")); + it('run() should throw on null input file name and unknown output file name', async function () { + await NodeAssert.rejects(async () => sut.run(null, "X")); }); it('run() should throw on unavailable input file name and null output file name', async function () { const inputFilename = makePathToFixture('../data/Unavailable.keylayout'); - await rejects(async () => sut.run(inputFilename, null)); + await NodeAssert.rejects(async () => sut.run(inputFilename, null)); }); it('run() should return on correct input file name and empty output file name ', async function () { const inputFilename = makePathToFixture('../data/Italian.keylayout'); - await doesNotReject(async () => sut.run(inputFilename, "")); + await NodeAssert.doesNotReject(async () => sut.run(inputFilename, "")); }); it('run() should return on correct input file name and null output file name', async function () { const inputFilename = makePathToFixture('../data/Italian.keylayout'); - await doesNotReject(async () => sut.run(inputFilename, null)); + await NodeAssert.doesNotReject(async () => sut.run(inputFilename, null)); }); it('run() should return on correct input file name and given output file name ', async function () { const inputFilename = makePathToFixture('../data/Italian.keylayout'); const outputFilename = makePathToFixture('../../data/OutputName.kmn'); - await doesNotReject(async () => sut.run(inputFilename, outputFilename)); + await NodeAssert.doesNotReject(async () => sut.run(inputFilename, outputFilename)); }); it('run() should throw on incorrect input file extention and output file extention', async function () { const inputFilename = makePathToFixture('../data/Italian_command.A'); const outputFilename = makePathToFixture('../../data/OutputXName.B'); - await rejects(async () => sut.run(inputFilename, outputFilename)); + await NodeAssert.rejects(async () => sut.run(inputFilename, outputFilename)); }); it('run() return on correct input file extention and unsupperted output file extention', async function () { const inputFilename = makePathToFixture('../data/Italian.keylayout'); const outputFilename = makePathToFixture('../../data/OutputXName.B'); - await doesNotReject(async () => sut.run(inputFilename, outputFilename)); + await NodeAssert.doesNotReject(async () => sut.run(inputFilename, outputFilename)); }); }); - describe('convert()', function () { + describe("convert() ", function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Italian.keylayout'); @@ -85,19 +86,19 @@ describe('KeylayoutToKmnConverter', function () { const converted_empty = sut.convert(read_empty); it('should return converted array on correct input', async function () { - await (doesNotReject(async () => (converted.arrayOf_Rules.length !== 0))); + assert.isTrue(converted.arrayOf_Rules.length !== 0); }); it('should return empty on empty input', async function () { - await (doesNotReject(async () => (converted_empty.keylayout_filename === '' + assert.isTrue((converted_empty.keylayout_filename === '' && converted_empty.arrayOf_Modifiers.length === 0 - && converted_empty.arrayOf_Rules.length === 0))); + && converted_empty.arrayOf_Rules.length === 0)); }); it('should return empty on only name as input', async function () { - await (doesNotReject(async () => (converted_unavailable.keylayout_filename === '' + assert.isTrue((converted_unavailable.keylayout_filename === '' && converted_unavailable.arrayOf_Modifiers.length === 0 - && converted_unavailable.arrayOf_Rules.length === 0))); + && converted_unavailable.arrayOf_Rules.length === 0)); }); it('should return empty on only modifiers as input', async function () { @@ -106,9 +107,9 @@ describe('KeylayoutToKmnConverter', function () { arrayOf_Modifiers: [['caps'], ['Shift'], ['command']], arrayOf_Rules: [] }); - await (doesNotReject(async () => (converted_mod.keylayout_filename === '' + assert.isTrue((converted_mod.keylayout_filename === '' && converted_mod.arrayOf_Modifiers.length === 0 - && converted_mod.arrayOf_Rules.length === 0))); + && converted_mod.arrayOf_Rules.length === 0)); }); it('should return empty on only rules as input', async function () { @@ -117,14 +118,15 @@ describe('KeylayoutToKmnConverter', function () { arrayOf_Modifiers: [], arrayOf_Rules: [["C0", "", "", 0, 0, "", "", 0, 0, "CAPS", "K_A", "A"]] }); - await (doesNotReject(async () => (converted_rule.keylayout_filename === '' + assert.isTrue((converted_rule.keylayout_filename === '' && converted_rule.arrayOf_Modifiers.length === 0 - && converted_rule.arrayOf_Rules.length === 0))); + && converted_rule.arrayOf_Rules.length === 0)); }); }); - describe('create_kmn_modifier', function () { + describe('create_kmn_modifier ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + [ ['shift', true, 'NCAPS SHIFT'], ['leftshift', true, 'NCAPS SHIFT'], @@ -153,15 +155,16 @@ describe('KeylayoutToKmnConverter', function () { ['leftoption', true, 'NCAPS LALT'], ['loption', true, 'NCAPS LALT'], ].forEach(function (values) { - it(('should convert "' + values[0] + '"').padEnd(36, " ") + 'to "' + values[2] + '"', async function () { - await doesNotReject(async () => (sut.create_kmn_modifier(values[0] as string, values[1] as boolean) === values[2])); + const result = sut.create_kmn_modifier(values[0] as string, values[1] as boolean); + assert.equal(result, values[2]); }); }); }); - describe('isAcceptableKeymanModifier', function () { + describe("isAcceptableKeymanModifier ", function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + [ ["NCAPS", true], ["NxCAPS", false], @@ -177,17 +180,16 @@ describe('KeylayoutToKmnConverter', function () { ["", true], [null, false], ].forEach(function (values) { - it(("isAcceptableKeymanModifier(" + values[0] + ")").padEnd(38, " ") + ' should return ' + values[1], async function () { - await doesNotReject(async () => sut.isAcceptableKeymanModifier(values[0] as string) === values[1]); + const result = sut.isAcceptableKeymanModifier(values[0] as string); + assert.equal(result, values[1]); }); - - }); }); - describe('map_UkeleleKC_To_VK', function () { + describe("map_UkeleleKC_To_VK ", function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + [ [0x00, "K_A"], [0x31, "K_SPACE"], @@ -200,13 +202,15 @@ describe('KeylayoutToKmnConverter', function () { [null, ""], ].forEach(function (values) { it(("map_UkeleleKC_To_VK(" + values[0] + ")").padEnd(26, " ") + "should return " + "'" + values[1] + "'", async function () { - await doesNotReject(async () => sut.map_UkeleleKC_To_VK(values[0] as number) === values[1]); + const result = sut.map_UkeleleKC_To_VK(values[0] as number); + assert.equal(result, values[1]); }); }); }); - describe('checkIfCapsIsUsed', function () { + describe("checkIfCapsIsUsed ", function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + [ [[['caps', 'xxx'], ['yyy']], true], [[['Caps', 'xxx'], ['yyy']], true], @@ -217,20 +221,20 @@ describe('KeylayoutToKmnConverter', function () { [[['', ''], ['']], false], [[null], false], ].forEach(function (values) { - it(("checkIfCapsIsUsed(" + values[0] + ")").padEnd(26, " ") + "should return " + "'" + values[1] + "'", async function () { - await doesNotReject(async () => sut.checkIfCapsIsUsed(values[0] as string[][]) === values[1]); + it(("checkIfCapsIsUsed([['caps', 'xxx'], ['yyy']])").padEnd(45, " ") + "should return " + "'" + values[1] + "'", async function () { + const result = sut.checkIfCapsIsUsed(values[0] as string[][]) === values[1]; + assert.isTrue(result); }); }); }); - describe('get_Modifier_array__From__KeyModifier_array', function () { + describe("get_Modifier_array__From__KeyModifier_array ", function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Italian.keylayout'); const read = sut_r.read(inputFilename); const converted = sut.convert(read); - // strings as input [[[['0', 0]], [['', 'shift? caps? ']]], [[['0', 1]], [['anyShift caps?', 'shift? rightShift caps? ', 'shift? leftShift caps? ', 'shift leftShift caps ']]], [[['0', 999]], [null]], @@ -242,27 +246,27 @@ describe('KeylayoutToKmnConverter', function () { ("get_Modifier_array__From__KeyModifier_array(['" + values[0][0][0] + "', '" + values[0][0][1] + "'])").padEnd(68, " ") + " should return ['" + values[1][0][0] + "', '" + values[1][0][1] + "']" : ("get_Modifier_array__From__KeyModifier_array(['" + values[0][0][0] + "', '" + values[0][0][1] + "'])").padEnd(68, " ") + " should return ['" + values[1][0] + "']", async function () { const result = sut.get_Modifier_array__From__KeyModifier_array(converted.arrayOf_Modifiers, values[0]); - await doesNotReject(async () => JSON.stringify(result) === JSON.stringify(values[1])); + assert.deepStrictEqual(JSON.stringify(result), JSON.stringify(values[1])); }); }); - // null, undefined or empty as input [[[[null]], [null]], [[[undefined]], [null]], [[[]], [null]], ].forEach(function (values) { it(("get_Modifier_array__From__KeyModifier_array([" + values[0][0] + "])").padEnd(68, " ") + " should return ['" + values[1][0] + "']", async function () { const result = sut.get_Modifier_array__From__KeyModifier_array(converted.arrayOf_Modifiers, values[0]); - await doesNotReject(async () => JSON.stringify(result) === JSON.stringify(values[1])); + assert.deepStrictEqual(JSON.stringify(result), JSON.stringify(values[1])); }); }); }); - describe('get_KeyModifier_array__From__ActionID', function () { + describe("get_KeyModifier_array__From__ActionID ", function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Italian.keylayout'); const read = sut_r.read(inputFilename); + [ ["a16", [['32', 3]]], ["a19", [['45', 3]]], @@ -273,6 +277,7 @@ describe('KeylayoutToKmnConverter', function () { [" ", []], ["", []], ].forEach(function (values) { + let outstring = "[ "; for (let i = 0; i < values[1].length; i++) { outstring = outstring + "[ '" + values[1][i][0] + "', " + values[1][i][1].toString() + "], "; @@ -280,16 +285,17 @@ describe('KeylayoutToKmnConverter', function () { it(("get_KeyModifier_array__From__ActionID('" + values[0] + "')").padEnd(57, " ") + ' should return ' + outstring.substring(0, outstring.lastIndexOf(']') + 2) + " ]", async function () { const result = sut.get_KeyModifier_array__From__ActionID(read, String(values[0])); - await doesNotReject(async () => JSON.stringify(result) === JSON.stringify(values[1])); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); }); - describe('get_ActionID__From__ActionNext', function () { + describe("get_ActionID__From__ActionNext ", function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Italian.keylayout'); const read = sut_r.read(inputFilename); + [ ["none", ""], ["a18", ""], @@ -306,12 +312,12 @@ describe('KeylayoutToKmnConverter', function () { ].forEach(function (values) { it(("get_ActionID__From__ActionNext('" + values[0] + "')").padEnd(49, " ") + ' should return ' + "'" + values[1] + "'", async function () { const result = sut.get_ActionID__From__ActionNext(read, String(values[0])); - await doesNotReject(async () => JSON.stringify(result) === JSON.stringify(values[1])); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); }); - describe('get_ActionIndex__From__ActionId', function () { + describe("get_ActionIndex__From__ActionId ", function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Italian.keylayout'); @@ -331,12 +337,12 @@ describe('KeylayoutToKmnConverter', function () { ].forEach(function (values) { it(("get_ActionIndex__From__ActionId('" + values[0] + "')").padEnd(50, " ") + ' should return ' + values[1], async function () { const result = sut.get_ActionIndex__From__ActionId(read, String(values[0])); - await doesNotReject(async () => JSON.stringify(result) === JSON.stringify(values[1])); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); }); - describe('get_Output__From__ActionId_None', function () { + describe("get_Output__From__ActionId_None ", function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Italian.keylayout'); @@ -351,7 +357,7 @@ describe('KeylayoutToKmnConverter', function () { it( ("get_Output__From__ActionId_None('" + values[0] + "')").padEnd(56, " ") + ' should return ' + "'" + values[1] + "'", async function () { const result = sut.get_Output__From__ActionId_None(read, String(values[0])); - await doesNotReject(async () => JSON.stringify(result) === JSON.stringify(values[1])); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); @@ -361,12 +367,12 @@ describe('KeylayoutToKmnConverter', function () { ].forEach(function (values) { it(("get_Output__From__ActionId_None('" + values[0] + "')").padEnd(56, " ") + ' should return ' + values[1], async function () { const result = sut.get_Output__From__ActionId_None(read, String(values[0])); - await doesNotReject(async () => JSON.stringify(result) === JSON.stringify(values[1])); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); }); - describe('get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array', function () { + describe("get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array ", function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Italian.keylayout'); @@ -428,7 +434,6 @@ describe('KeylayoutToKmnConverter', function () { ['K_A', 'a9', '0', 'NCAPS', 'â'] ]; - // for non-empty/undefined/null and isCaps_used = true [[b1_keycode_arr, b1_modifierKey_arr], [[['49', 'K_SPACE', 'a0', '0', 'ˆ']], [['K_SPACE', 'a0', '0', 'NCAPS', 'ˆ']]], [[['49', 'K_SPACE', 'a0', '0', '']], [['K_SPACE', 'a0', '0', 'NCAPS', '']]], @@ -439,6 +444,7 @@ describe('KeylayoutToKmnConverter', function () { [[['', 'K_SPACE', 'a0', '0', 'ˆ']], [['K_SPACE', 'a0', '0', 'NCAPS', 'ˆ']]], [[['', '', '', '', '']], [['', '', '', 'NCAPS', '']]], ].forEach(function (values) { + const isCaps_used = true; const string_in = "get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(['" + "', '" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "', '" + values[0][0][3] + "', '" + values[0][0][4] + "'])"; const string_out = "['" + "', '" + values[1][0][0] + "', '" + values[1][0][1] + "', '" + values[1][0][2] + "', '" + values[1][0][3] + "', '" + values[1][0][4] + "']"; @@ -446,27 +452,26 @@ describe('KeylayoutToKmnConverter', function () { it((JSON.stringify(values[1]).length > 60) ? 'an array of objects should return an array of objectss' : string_in.padEnd(74, " ") + ' should return ' + string_out, async function () { const result = sut.get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(read, values[0], isCaps_used); - await doesNotReject(async () => JSON.stringify(result) === JSON.stringify(values[1])); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); - // for non-empty/undefined/null and isCaps_used = false [[[['49', 'K_SPACE', 'a0', '0', 'ˆ']], [['K_SPACE', 'a0', '0', '', 'ˆ']]], [[['49', 'K_SPACE', 'a0', '0', '']], [['K_SPACE', 'a0', '0', '', '']]], [[['', 'K_SPACE', 'a0', '0', 'ˆ']], [['K_SPACE', 'a0', '0', '', 'ˆ']]], [[['', '', '', '', '']], [['', '', '', '', '']]], ].forEach(function (values) { + const isCaps_used = false; const string_in = "get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(['" + "', '" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "', '" + values[0][0][3] + "', '" + values[0][0][4] + "'])"; const string_out = "['" + "', '" + values[1][0][0] + "', '" + values[1][0][1] + "', '" + values[1][0][2] + "', '" + values[1][0][3] + "', '" + values[1][0][4] + "']"; it(string_in.padEnd(74, " ") + ' should return ' + string_out, async function () { const result = sut.get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(read, values[0], isCaps_used); - await doesNotReject(async () => JSON.stringify(result) === JSON.stringify(values[1])); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); - // for empty/undefined/null [[[], []], [undefined, []], [null, []], @@ -474,12 +479,12 @@ describe('KeylayoutToKmnConverter', function () { const isCaps = true; it(("get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array([" + values[0] + "])").padEnd(74, " ") + ' should return ' + "[" + values[1] + "]", async function () { const result = sut.get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(read, values[0], isCaps); - await doesNotReject(async () => JSON.stringify(result) === JSON.stringify(values[1])); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); }); - describe('get_ActionStateOutput_array__From__ActionState', function () { + describe("get_ActionStateOutput_array__From__ActionState ", function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Italian.keylayout'); @@ -520,12 +525,12 @@ describe('KeylayoutToKmnConverter', function () { ("get_ActionStateOutput_array__From__ActionState('" + values[0] + "')").padEnd(60, " ") + ' should return an array of objects' : ("get_ActionStateOutput_array__From__ActionState('" + values[0] + "')").padEnd(60, " ") + ' should return ' + "'" + JSON.stringify(values[1]) + "'", async function () { const result = sut.get_ActionStateOutput_array__From__ActionState(read, String(values[0])); - await doesNotReject(async () => JSON.stringify(result) === JSON.stringify(values[1])); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); }); - describe('get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput', function () { + describe("get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput ", function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Italian.keylayout'); @@ -557,12 +562,12 @@ describe('KeylayoutToKmnConverter', function () { ("get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput('" + values[0] + "', '" + values[1] + "', " + values[2] + ")").padEnd(67, " ") + ' should return an array of objects' : ("get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput('" + values[0] + "', '" + values[1] + "', " + values[2] + ")").padEnd(67, " ") + ' should return ' + "'" + JSON.stringify(values[3]) + "'", async function () { const result = sut.get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput(read, converted.arrayOf_Modifiers, String(values[0]), String(values[1]), Boolean(values[2])); - await doesNotReject(async () => JSON.stringify(result) === JSON.stringify(values[3])); + assert.equal(JSON.stringify(result), JSON.stringify(values[3])); }); }); }); - describe('get_KeyActionOutput_array__From__ActionStateOutput_array', function () { + describe("get_KeyActionOutput_array__From__ActionStateOutput_array ", function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Italian.keylayout'); @@ -610,11 +615,11 @@ describe('KeylayoutToKmnConverter', function () { ].forEach(function (values) { it(("get_KeyActionOutput_array__From__ActionStateOutput_array([['" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "'],..])").padEnd(73, " ") + ' should return an array of objects', async function () { const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0]); - await doesNotReject(async () => JSON.stringify(result) === JSON.stringify(values[1])); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); - //------------------------------------------------------------------------------------------------------ + //----------------- const oneEntryResult = [ ["49", "K_SPACE", "a0", "0", "ˆ"], ["49", "K_SPACE", "a0", "1", "ˆ"], @@ -640,30 +645,31 @@ describe('KeylayoutToKmnConverter', function () { ].forEach(function (values) { it(("get_KeyActionOutput_array__From__ActionStateOutput_array(['" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "'])").padEnd(73, " ") + ' should return an array of objects', async function () { const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0]); - await doesNotReject(async () => JSON.stringify(result) === JSON.stringify(values[1])); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); - //------------------------------------------------------------------------------------------------------ + //------------------------------------------------------------------------------------- [[[['', '1', 'ˆ']], []], [[['', '', '']], []], [[[' ', ' ', '']], []], ].forEach(function (values) { it(("get_KeyActionOutput_array__From__ActionStateOutput_array(['" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "'])").padEnd(73, " ") + ' should return ' + "'[" + values[1] + "]'", async function () { const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0]); - await doesNotReject(async () => JSON.stringify(result) === JSON.stringify(values[1])); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); - //------------------------------------------------------------------------------------------------------ + //------------------------------------------------------------------------------------- [[[], []], [undefined, []], [null, []], ].forEach(function (values) { it(("get_KeyActionOutput_array__From__ActionStateOutput_array(" + values[0] + ")").padEnd(73, " ") + ' should return ' + "'[" + values[1] + "]'", async function () { const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0]); - await doesNotReject(async () => JSON.stringify(result) === JSON.stringify(values[1])); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); }); + }); diff --git a/developer/src/kmc-convert/test/kmn-file-reader.tests.ts b/developer/src/kmc-convert/test/kmn-file-reader.tests.ts index d758f85b8a5..1cc81983b38 100644 --- a/developer/src/kmc-convert/test/kmn-file-reader.tests.ts +++ b/developer/src/kmc-convert/test/kmn-file-reader.tests.ts @@ -6,10 +6,11 @@ */ import 'mocha'; +import { assert } from 'chai'; import { compilerTestCallbacks, makePathToFixture } from './helpers/index.js'; import { KeylayoutFileReader } from '../src/keylayout-to-kmn/keylayout-file-reader.js'; -import { doesNotReject } from "node:assert"; +//----------------------------------------------------------------------------------------------------------------------- describe('KeylayoutFileReader', function () { @@ -17,32 +18,39 @@ describe('KeylayoutFileReader', function () { compilerTestCallbacks.clear(); }); - describe('read()', function () { + describe("read() ", function () { const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const empty: any = []; + const inputFilename_unavailable = makePathToFixture('X.keylayout'); it('read() should return filled array on correct input', async function () { - await doesNotReject(async () => (sut_r.read(makePathToFixture('../data/Italian.keylayout')))); + const inputFilename = makePathToFixture('../data/Italian.keylayout'); + const result = sut_r.read(inputFilename); + assert.isNotEmpty(result); }); - it('read() should return empty array on null input', async function () { - await doesNotReject(async () => (Array.isArray(sut_r.read(null)) === Array.isArray(empty))); + it('read() should return empty array on null input', async function () { + const result = sut_r.read(null); + assert.isEmpty(result); }); - it('read() should return empty array on empty input', async function () { - await doesNotReject(async () => (Array.isArray(sut_r.read("")) === Array.isArray(empty))); + it('read() should return empty array on empty input', async function () { + const result = sut_r.read(""); + assert.isEmpty(result); }); - it('read() should return empty array on space as input', async function () { - await doesNotReject(async () => (Array.isArray(sut_r.read(" ")) === Array.isArray(empty))); + it('read() should return empty array on space as input', async function () { + const result = sut_r.read(" "); + assert.isEmpty(result); }); - it('read() should return empty array on unavailable file name', async function () { - await doesNotReject(async () => (Array.isArray(sut_r.read(makePathToFixture('Unavailable_InputFilename.keylayout'))) === empty)); + it('read() should return empty array on unavailable file name', async function () { + const result = sut_r.read(inputFilename_unavailable); + assert.isEmpty(result); }); - it('read() should return empty array on typo in path', async function () { - await doesNotReject(async () => (Array.isArray(sut_r.read(makePathToFixture('../data|Italian.keylayout'))) === empty)); + it('read() should return empty array on typo in path', async function () { + const result = sut_r.read('../data|Italian.keylayout'); + assert.isEmpty(result); }); }); }); diff --git a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts index 12dee0adc3d..1c7c2753cee 100644 --- a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts +++ b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts @@ -6,15 +6,12 @@ */ import 'mocha'; +import { assert } from 'chai'; import { util } from '@keymanapp/common-types'; import { compilerTestCallbacks, compilerTestOptions, makePathToFixture } from './helpers/index.js'; import { KeylayoutToKmnConverter } from '../src/keylayout-to-kmn/keylayout-to-kmn-converter.js'; import { KmnFileWriter } from '../src/keylayout-to-kmn/kmn-file-writer.js'; import { KeylayoutFileReader } from '../src/keylayout-to-kmn/keylayout-file-reader.js'; -import { doesNotReject } from 'node:assert'; - - -//----------------------------------------------------------------------------------------------------------------------- describe('KmnFileWriter', function () { @@ -22,7 +19,7 @@ describe('KmnFileWriter', function () { compilerTestCallbacks.clear(); }); - describe('write()', function () { + describe("write() ", function () { const inputFilename = makePathToFixture('../data/Italian.keylayout'); const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); @@ -36,15 +33,18 @@ describe('KmnFileWriter', function () { const converted_unavailable = sut.convert(read_unavailable); it('write() should return true (no error) if written', async function () { - await doesNotReject(async () => sut_w.write(converted)); + const result = sut_w.write(converted); + assert.isTrue(result); }); it('write() should return false if no inputfile', async function () { - await doesNotReject(async () => sut_w.write(converted_unavailable) === false); + const result = sut_w.write(converted_unavailable); + assert.isFalse(result); }); + }); - describe('writeData_Rules()', function () { + describe("writeData_Rules() ", function () { const inputFilename = makePathToFixture('../data/Italian.keylayout'); const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); @@ -58,16 +58,18 @@ describe('KmnFileWriter', function () { const converted_unavailable = sut.convert(read_unavailable); it('writeData_Rules() should return true (no error) if written', async function () { - await doesNotReject(async () => sut_w.writeData_Rules(converted).length > 0); + const result = sut_w.writeData_Rules(converted); + assert.isTrue(result.length > 0); }); it('writeData_Rules() should return false if no inputfile', async function () { - await doesNotReject(async () => sut_w.writeData_Rules(converted_unavailable).length > 0); + const result = sut_w.writeData_Rules(converted_unavailable); + assert.isFalse(result.length > 0); }); }); - describe('writeData_Stores() ', function () { + describe("writeData_Stores() ", function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); @@ -107,22 +109,21 @@ describe('KmnFileWriter', function () { it(('writeData_Stores should return store text with filename ').padEnd(62, " ") + 'on correct input', async function () { const written_correctName = sut_w.writeData_Stores(converted); - await doesNotReject(async () => (written_correctName === (out_expected_first + converted.keylayout_filename + out_expected_last))); + assert.equal(written_correctName, (out_expected_first + converted.keylayout_filename + out_expected_last)); }); it(('writeData_Stores should return store text without filename ').padEnd(62, " ") + 'on empty input', async function () { const written_emptyName = sut_w.writeData_Stores(converted_empty); - await doesNotReject(async () => (written_emptyName === (out_expected_first + out_expected_last))); - + assert.equal(written_emptyName, (out_expected_first + out_expected_last)); }); it(('writeData_Stores should return store text without filename ').padEnd(62, " ") + 'on only filename as input', async function () { const written_onlyName = sut_w.writeData_Stores(converted_unavailable); - await doesNotReject(async () => (written_onlyName === (out_expected_first + converted_unavailable.keylayout_filename + out_expected_last))); + assert.equal(written_onlyName, (out_expected_first + converted_unavailable.keylayout_filename + out_expected_last)); }); }); - describe('reviewRules() ', function () { + describe("reviewRules() ", function () { const inputFilename = makePathToFixture('../data/Italian.keylayout'); const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); @@ -135,12 +136,14 @@ describe('KmnFileWriter', function () { const read_unavailable = sut_r.read(inputFilename_unavailable); const converted_unavailable = sut.convert(read_unavailable); - it('reviewRules() should return true (no error) if written', async function () { - await doesNotReject(async () => sut_w.write(converted)); + it('write() should return true (no error) if written', async function () { + const result = sut_w.write(converted); + assert.isTrue(result); }); - it('reviewRules() should return false if no inputfile', async function () { - await doesNotReject(async () => !sut_w.write(converted_unavailable)); + it('write() should return false if no inputfile', async function () { + const result = sut_w.write(converted_unavailable); + assert.isFalse(result); }); }); @@ -167,7 +170,8 @@ describe('KmnFileWriter', function () { [' ;', ' ;'] ].forEach(function (values) { it(('should convert "' + values[0] + '"').padEnd(25, " ") + 'to "' + values[1] + '"', async function () { - await doesNotReject(async () => util.convertToUnicodeCodePoint(values[0] as string) === values[1]); + const result = util.convertToUnicodeCodePoint(values[0] as string); + assert.equal(result, values[1]); }); }); }); From 1634cc0efbcd3d2869882ef1800aeeb9353c0434 Mon Sep 17 00:00:00 2001 From: Sabine Date: Mon, 14 Apr 2025 14:54:24 +0200 Subject: [PATCH 088/251] feat(developer): remove interface rule_object and use Rule instead --- .../keylayout-to-kmn-converter.ts | 33 +++---------------- 1 file changed, 5 insertions(+), 28 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index e5b2c0bcd9a..ab525929d11 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -10,30 +10,11 @@ import { ConverterToKmnArtifacts } from "../converter-artifacts.js"; import { KmnFileWriter } from './kmn-file-writer.js'; import { KeylayoutFileReader } from './keylayout-file-reader.js'; -export interface rule_object { - rule_type: string, /* rule type C0-C4 */ - - modifier_prev_deadkey: string, /* string of modifiers for the first key (e.g. "NCAPS RALT CTRL") */ - prev_deadkey: string, /* name of the first key (e.g. K_U) */ - id_prev_deadkey: number, /* dk id for prev-deadkeys */ - unique_prev_deadkey: number, /* marks the first prev_dk */ - - modifier_deadkey: string, /* string of modifiers for the second key (e.g. "NCAPS RALT CTRL") */ - deadkey: string, /* name of the second key */ - id_deadkey: number, /* dk id for deadkeys */ - unique_deadkey: number, /* marks the first dk */ - - modifier_key: string, /* string of modifiers for the third key (e.g. "NCAPS RALT CTRL") */ - key: string, /* name of the third key (e.g. K_U) */ - output: Uint8Array, /* the output character */ -}; - export interface convert_object { keylayout_filename: string, kmn_filename: string, arrayOf_Modifiers: string[][], - arrayOf_Rules: rule_object[], - //arrayOf_Rules: any[], + arrayOf_Rules: Rule[], }; export class KeylayoutToKmnConverter { @@ -98,8 +79,7 @@ export class KeylayoutToKmnConverter { public convert(jsonObj: any, outputfilename: string = ""): convert_object { const modifierBehavior: string[][] = []; // modifier for each behaviour - const rules: rule_object[] = []; // an array of data for a kmn rule - //const rules: any[] = []; // an array of data for a kmn rule + const rules: Rule[] = []; // an array of data for a kmn rule const data_object: convert_object = { keylayout_filename: "", @@ -152,8 +132,7 @@ export class KeylayoutToKmnConverter { */ public createRuleData(data_ukelele: convert_object, jsonObj: any): convert_object { - const object_array: rule_object[] = []; - // const object_array = []; + const object_array: Rule[] = []; let dk_counter_C3: number = 0; let dk_counter_C2: number = 0; let action_id: string; @@ -167,8 +146,7 @@ export class KeylayoutToKmnConverter { // loop behaviors (in ukelele it is possible to define multiple modifier combinations that behave in the same way) for (let i = 0; i < jsonObj.keyboard.keyMapSet[0].keyMap.length; i++) { - let rule_obj: rule_object; - //let rule_obj; + let rule_obj: Rule; // ............................................................................................................................... // case C0: output ............................................................................................................... @@ -446,8 +424,7 @@ export class KeylayoutToKmnConverter { let unique_dkB_count = 0; const list_of_unique_Text2_rules: string[][] = []; - const object_array: rule_object[] = data_ukelele.arrayOf_Rules; - //const object_array = data_ukelele.arrayOf_Rules; + const object_array: Rule[] = data_ukelele.arrayOf_Rules; //------------------------------------ C2: dk ---------------------------------- // first rule is always unique From 60f588e9964b74d53d3ee567711fcc9f7ad9ae49 Mon Sep 17 00:00:00 2001 From: Sabine Date: Tue, 15 Apr 2025 17:38:43 +0200 Subject: [PATCH 089/251] feat(developer): delete interface rule_object; unversion and move testfiles to test/data; use constants to specify folder --- .../src/kmc-convert/data/French.keylayout | 1066 ------- .../data/German_Standard.keylayout | 2783 ---------------- .../data/German_complete.keylayout | 2785 ----------------- .../src/kmc-convert/data/Italian.keylayout | 1059 ------- .../data/Italian_CapsAdded.keylayout | 1060 ------- .../data/Italian_command.keylayout | 1063 ------- .../kmc-convert/data/Latin_American.keylayout | 820 ----- .../src/kmc-convert/data/Polish.keylayout | 1030 ------ .../src/kmc-convert/data/Spanish.keylayout | 1062 ------- .../kmc-convert/data/Swiss_French.keylayout | 1174 ------- .../kmc-convert/data/Swiss_German.keylayout | 1289 -------- developer/src/kmc-convert/data/US.keylayout | 1136 ------- .../keylayout-to-kmn/keylayout-file-reader.ts | 5 +- .../keylayout-to-kmn-converter.ts | 9 +- .../src/keylayout-to-kmn/kmn-file-writer.ts | 29 +- .../test/keylayout-to-kmn-converter.tests.ts | 38 +- .../kmc-convert/test/kmn-file-reader.tests.ts | 18 +- .../kmc-convert/test/kmn-file-writer.tests.ts | 27 +- 18 files changed, 65 insertions(+), 16388 deletions(-) delete mode 100644 developer/src/kmc-convert/data/French.keylayout delete mode 100644 developer/src/kmc-convert/data/German_Standard.keylayout delete mode 100644 developer/src/kmc-convert/data/German_complete.keylayout delete mode 100644 developer/src/kmc-convert/data/Italian.keylayout delete mode 100644 developer/src/kmc-convert/data/Italian_CapsAdded.keylayout delete mode 100644 developer/src/kmc-convert/data/Italian_command.keylayout delete mode 100644 developer/src/kmc-convert/data/Latin_American.keylayout delete mode 100644 developer/src/kmc-convert/data/Polish.keylayout delete mode 100644 developer/src/kmc-convert/data/Spanish.keylayout delete mode 100644 developer/src/kmc-convert/data/Swiss_French.keylayout delete mode 100644 developer/src/kmc-convert/data/Swiss_German.keylayout delete mode 100644 developer/src/kmc-convert/data/US.keylayout diff --git a/developer/src/kmc-convert/data/French.keylayout b/developer/src/kmc-convert/data/French.keylayout deleted file mode 100644 index a4c0743b37f..00000000000 --- a/developer/src/kmc-convert/data/French.keylayout +++ /dev/null @@ -1,1066 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/developer/src/kmc-convert/data/German_Standard.keylayout b/developer/src/kmc-convert/data/German_Standard.keylayout deleted file mode 100644 index 921b7e8c60b..00000000000 --- a/developer/src/kmc-convert/data/German_Standard.keylayout +++ /dev/null @@ -1,2783 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/developer/src/kmc-convert/data/German_complete.keylayout b/developer/src/kmc-convert/data/German_complete.keylayout deleted file mode 100644 index d4f3ff6581c..00000000000 --- a/developer/src/kmc-convert/data/German_complete.keylayout +++ /dev/null @@ -1,2785 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/developer/src/kmc-convert/data/Italian.keylayout b/developer/src/kmc-convert/data/Italian.keylayout deleted file mode 100644 index 354a1a7fb3e..00000000000 --- a/developer/src/kmc-convert/data/Italian.keylayout +++ /dev/null @@ -1,1059 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/developer/src/kmc-convert/data/Italian_CapsAdded.keylayout b/developer/src/kmc-convert/data/Italian_CapsAdded.keylayout deleted file mode 100644 index 14f1f2d2d25..00000000000 --- a/developer/src/kmc-convert/data/Italian_CapsAdded.keylayout +++ /dev/null @@ -1,1060 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/developer/src/kmc-convert/data/Italian_command.keylayout b/developer/src/kmc-convert/data/Italian_command.keylayout deleted file mode 100644 index 77832fd2bb7..00000000000 --- a/developer/src/kmc-convert/data/Italian_command.keylayout +++ /dev/null @@ -1,1063 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/developer/src/kmc-convert/data/Latin_American.keylayout b/developer/src/kmc-convert/data/Latin_American.keylayout deleted file mode 100644 index 4a5d3b198c1..00000000000 --- a/developer/src/kmc-convert/data/Latin_American.keylayout +++ /dev/null @@ -1,820 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/developer/src/kmc-convert/data/Polish.keylayout b/developer/src/kmc-convert/data/Polish.keylayout deleted file mode 100644 index c2a52899e73..00000000000 --- a/developer/src/kmc-convert/data/Polish.keylayout +++ /dev/null @@ -1,1030 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/developer/src/kmc-convert/data/Spanish.keylayout b/developer/src/kmc-convert/data/Spanish.keylayout deleted file mode 100644 index b5fbe9714bf..00000000000 --- a/developer/src/kmc-convert/data/Spanish.keylayout +++ /dev/null @@ -1,1062 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/developer/src/kmc-convert/data/Swiss_French.keylayout b/developer/src/kmc-convert/data/Swiss_French.keylayout deleted file mode 100644 index 8bd3f689971..00000000000 --- a/developer/src/kmc-convert/data/Swiss_French.keylayout +++ /dev/null @@ -1,1174 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/developer/src/kmc-convert/data/Swiss_German.keylayout b/developer/src/kmc-convert/data/Swiss_German.keylayout deleted file mode 100644 index 9d4d5be6a1e..00000000000 --- a/developer/src/kmc-convert/data/Swiss_German.keylayout +++ /dev/null @@ -1,1289 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/developer/src/kmc-convert/data/US.keylayout b/developer/src/kmc-convert/data/US.keylayout deleted file mode 100644 index aca8dbf6f0c..00000000000 --- a/developer/src/kmc-convert/data/US.keylayout +++ /dev/null @@ -1,1136 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts index 24f11eb827a..aba87801b5d 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts @@ -8,13 +8,14 @@ import { CompilerCallbacks } from "@keymanapp/developer-utils"; import { XMLParser } from 'fast-xml-parser'; import { util } from '@keymanapp/common-types'; +import { KeylayoutToKmnConverter } from './keylayout-to-kmn-converter.js'; import boxXmlArray = util.boxXmlArray; export class KeylayoutFileReader { constructor(private callbacks: CompilerCallbacks /*,private options: CompilerOptions*/) { }; - static readonly FILE_SUBFOLDER = 'data'; + /** * @brief member function to box single-entry objects into arrays @@ -56,7 +57,7 @@ export class KeylayoutFileReader { }; try { - xmlFile = this.callbacks.fs.readFileSync(this.callbacks.path.join(process.cwd(), KeylayoutFileReader.FILE_SUBFOLDER, this.callbacks.path.basename(absolutefilename)), 'utf8'); + xmlFile = this.callbacks.fs.readFileSync(this.callbacks.path.join(process.cwd(), KeylayoutToKmnConverter.TEST_DATA_SUBFOLDER, this.callbacks.path.basename(absolutefilename)), 'utf8'); const parser = new XMLParser(options); jsonObj = parser.parse(xmlFile); // get plain Object this.boxArray(jsonObj.keyboard); // jsonObj now contains arrays; no single fields diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index ab525929d11..23166edeede 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -24,8 +24,11 @@ export class KeylayoutToKmnConverter { static readonly USED_KEYS_COUNT = 51; static readonly MAX_CTRL_CHARACTER = 32; static readonly SKIP_COMMENTED_LINES = false; + static readonly KMC_CONVERT_VERSION = "0.1"; + + static readonly DATA_SUBFOLDER = 'data'; + static readonly TEST_DATA_SUBFOLDER = 'test/data'; - //private callbacks: CompilerCallbacks; private options: CompilerOptions; async init(callbacks: CompilerCallbacks, options: CompilerOptions): Promise { @@ -93,7 +96,7 @@ export class KeylayoutToKmnConverter { // get filename from data that had been read const fileNameNoExtention = jsonObj.keyboard['@_name']; - const filePath = this.callbacks.path.join(process.cwd(), "data"); + const filePath = this.callbacks.path.join(process.cwd(), KeylayoutToKmnConverter.TEST_DATA_SUBFOLDER); data_object.keylayout_filename = this.callbacks.path.join(filePath, (fileNameNoExtention + ".keylayout")); @@ -967,7 +970,7 @@ export class KeylayoutToKmnConverter { /** * @brief class for all storing a rule containing data for key, deadkey, previous deadkey, output) */ -class Rule { +export class Rule { constructor( public rule_type: string, /* C0, C1, C2, C3, or C4 */ diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts index 833e17b9938..d2697b3dfcf 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts @@ -6,8 +6,7 @@ */ import { CompilerCallbacks, CompilerOptions } from "@keymanapp/developer-utils"; -//import { KeylayoutToKmnConverter, convert_object, rule_object } from './keylayout-to-kmn-converter.js'; -import { KeylayoutToKmnConverter, convert_object } from './keylayout-to-kmn-converter.js'; +import { KeylayoutToKmnConverter, convert_object, Rule } from './keylayout-to-kmn-converter.js'; import { util } from '@keymanapp/common-types'; export class KmnFileWriter { @@ -47,12 +46,13 @@ export class KmnFileWriter { public writeData_Stores(data_ukelele: convert_object): string { let data: string = ""; - data += "c ......................................................................\n"; - data += "c ......................................................................\n"; - data += "c Keyman keyboard generated by kmn-convert\n"; + + data += "c ..................................................................................................................\n"; + data += "c ..................................................................................................................\n"; + data += "c Keyman keyboard generated by kmn-convert version: " + KeylayoutToKmnConverter.KMC_CONVERT_VERSION + "\n"; data += "c from Ukelele file: " + data_ukelele.keylayout_filename + "\n"; - data += "c ......................................................................\n"; - data += "c ......................................................................\n"; + data += "c ..................................................................................................................\n"; + data += "c ..................................................................................................................\n"; data += "\n"; data += "store(&VERSION) \'10.0\'\n"; @@ -79,8 +79,7 @@ export class KmnFileWriter { let data: string = ""; // filter array of all rules and remove duplicates - //const unique_data_Rules: rule_object[] = data_ukelele.arrayOf_Rules.filter((curr) => { - const unique_data_Rules: any[] = data_ukelele.arrayOf_Rules.filter((curr) => { + const unique_data_Rules: Rule[] = data_ukelele.arrayOf_Rules.filter((curr) => { return (!(curr.output === new TextEncoder().encode("") || curr.output === undefined) && (curr.key !== "") && ((curr.rule_type === "C0") @@ -89,8 +88,7 @@ export class KmnFileWriter { || (curr.rule_type === "C3" && (curr.deadkey !== "") && (curr.prev_deadkey !== ""))) ); }).reduce((unique, o) => { - // if (!unique.some((obj: rule_object) => - if (!unique.some((obj: any) => + if (!unique.some((obj: Rule) => new TextDecoder().decode(obj.output) === new TextDecoder().decode(o.output) && obj.rule_type === o.rule_type @@ -322,12 +320,11 @@ export class KmnFileWriter { * @brief member function to review rules for acceptable modifiers, duplicate or ambiguous rules and return an array containing possible warnings * definition of comparisons e.g. 1-1, 2-4, 6-6 * see https://docs.google.com/document/d/12J3NGO6RxIthCpZDTR8FYSRjiMgXJDLwPY2z9xqKzJ0/edit?tab=t.0#heading=h.pcz8rjyrl5ug - * @param rule : rule_object[] - an array of all rules + * @param rule : Rule[] - an array of all rules * @param index the index of a rule in array[rule] * @return a string[] containing possible warnings for a rule */ - //public reviewRules(rule: rule_object[], index: number): string[] { - public reviewRules(rule: any[], index: number): string[] { + public reviewRules(rule: Rule[], index: number): string[] { const keylayoutKmnConverter = new KeylayoutToKmnConverter(this.callbacks, this.options); const warningTextArray: string[] = Array(3).fill(""); @@ -634,7 +631,7 @@ export class KmnFileWriter { && idx < index ); - // 5-5 + // 5-5 dk(C1) + [SHIFT CAPS K_A] > dk(C2) <-> dk(C1) + [SHIFT CAPS K_A] > dk(C3) const amb_5_5 = rule.filter((curr, idx) => (curr.rule_type === "C3") && curr.modifier_key === rule[index].modifier_key @@ -644,7 +641,7 @@ export class KmnFileWriter { && idx < index ); - // 5-5 + // 5-5 dk(C1) + [SHIFT CAPS K_A] > dk(C2) <-> dk(C1) + [SHIFT CAPS K_A] > dk(C2) const dup_5_5 = rule.filter((curr, idx) => (curr.rule_type === "C3") && curr.modifier_deadkey === rule[index].modifier_deadkey diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index 1a3ad760615..193d1cb909b 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -35,35 +35,35 @@ describe('KeylayoutToKmnConverter', function () { }); it('run() should throw on unavailable input file name and null output file name', async function () { - const inputFilename = makePathToFixture('../data/Unavailable.keylayout'); + const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Unavailable.keylayout'); await NodeAssert.rejects(async () => sut.run(inputFilename, null)); }); it('run() should return on correct input file name and empty output file name ', async function () { - const inputFilename = makePathToFixture('../data/Italian.keylayout'); + const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Italian.keylayout'); await NodeAssert.doesNotReject(async () => sut.run(inputFilename, "")); }); it('run() should return on correct input file name and null output file name', async function () { - const inputFilename = makePathToFixture('../data/Italian.keylayout'); + const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Italian.keylayout'); await NodeAssert.doesNotReject(async () => sut.run(inputFilename, null)); }); it('run() should return on correct input file name and given output file name ', async function () { - const inputFilename = makePathToFixture('../data/Italian.keylayout'); - const outputFilename = makePathToFixture('../../data/OutputName.kmn'); + const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Italian.keylayout'); + const outputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/OutputName.kmn'); await NodeAssert.doesNotReject(async () => sut.run(inputFilename, outputFilename)); }); it('run() should throw on incorrect input file extention and output file extention', async function () { - const inputFilename = makePathToFixture('../data/Italian_command.A'); - const outputFilename = makePathToFixture('../../data/OutputXName.B'); + const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Italian_command.A'); + const outputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/data/OutputXName.B'); await NodeAssert.rejects(async () => sut.run(inputFilename, outputFilename)); }); it('run() return on correct input file extention and unsupperted output file extention', async function () { - const inputFilename = makePathToFixture('../data/Italian.keylayout'); - const outputFilename = makePathToFixture('../../data/OutputXName.B'); + const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Italian.keylayout'); + const outputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/OutputXName.B'); await NodeAssert.doesNotReject(async () => sut.run(inputFilename, outputFilename)); }); }); @@ -71,7 +71,7 @@ describe('KeylayoutToKmnConverter', function () { describe("convert() ", function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Italian.keylayout'); + const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Italian.keylayout'); const read = sut_r.read(inputFilename); const converted = sut.convert(read); @@ -231,7 +231,7 @@ describe('KeylayoutToKmnConverter', function () { describe("get_Modifier_array__From__KeyModifier_array ", function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Italian.keylayout'); + const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Italian.keylayout'); const read = sut_r.read(inputFilename); const converted = sut.convert(read); @@ -264,7 +264,7 @@ describe('KeylayoutToKmnConverter', function () { describe("get_KeyModifier_array__From__ActionID ", function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Italian.keylayout'); + const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Italian.keylayout'); const read = sut_r.read(inputFilename); [ @@ -293,7 +293,7 @@ describe('KeylayoutToKmnConverter', function () { describe("get_ActionID__From__ActionNext ", function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Italian.keylayout'); + const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Italian.keylayout'); const read = sut_r.read(inputFilename); [ @@ -320,7 +320,7 @@ describe('KeylayoutToKmnConverter', function () { describe("get_ActionIndex__From__ActionId ", function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Italian.keylayout'); + const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Italian.keylayout'); const read = sut_r.read(inputFilename); [ @@ -345,7 +345,7 @@ describe('KeylayoutToKmnConverter', function () { describe("get_Output__From__ActionId_None ", function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Italian.keylayout'); + const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Italian.keylayout'); const read = sut_r.read(inputFilename); [["a14", "u"], @@ -375,7 +375,7 @@ describe('KeylayoutToKmnConverter', function () { describe("get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array ", function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Italian.keylayout'); + const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Italian.keylayout'); const read = sut_r.read(inputFilename); const b1_keycode_arr = [ @@ -487,7 +487,7 @@ describe('KeylayoutToKmnConverter', function () { describe("get_ActionStateOutput_array__From__ActionState ", function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Italian.keylayout'); + const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Italian.keylayout'); const read = sut_r.read(inputFilename); [["1", [ @@ -533,7 +533,7 @@ describe('KeylayoutToKmnConverter', function () { describe("get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput ", function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Italian.keylayout'); + const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Italian.keylayout'); const read = sut_r.read(inputFilename); const converted = sut.convert(read); @@ -570,7 +570,7 @@ describe('KeylayoutToKmnConverter', function () { describe("get_KeyActionOutput_array__From__ActionStateOutput_array ", function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Italian.keylayout'); + const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Italian.keylayout'); const read = sut_r.read(inputFilename); const b6_actionId_arr = [ diff --git a/developer/src/kmc-convert/test/kmn-file-reader.tests.ts b/developer/src/kmc-convert/test/kmn-file-reader.tests.ts index 1cc81983b38..aa655f26e71 100644 --- a/developer/src/kmc-convert/test/kmn-file-reader.tests.ts +++ b/developer/src/kmc-convert/test/kmn-file-reader.tests.ts @@ -9,6 +9,7 @@ import 'mocha'; import { assert } from 'chai'; import { compilerTestCallbacks, makePathToFixture } from './helpers/index.js'; import { KeylayoutFileReader } from '../src/keylayout-to-kmn/keylayout-file-reader.js'; +import { KeylayoutToKmnConverter } from '../src/keylayout-to-kmn/keylayout-to-kmn-converter.js'; //----------------------------------------------------------------------------------------------------------------------- @@ -19,37 +20,38 @@ describe('KeylayoutFileReader', function () { }); describe("read() ", function () { + const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename_unavailable = makePathToFixture('X.keylayout'); it('read() should return filled array on correct input', async function () { - const inputFilename = makePathToFixture('../data/Italian.keylayout'); + const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Italian.keylayout'); const result = sut_r.read(inputFilename); assert.isNotEmpty(result); }); - it('read() should return empty array on null input', async function () { + it('read() should return empty array on null input', async function () { const result = sut_r.read(null); assert.isEmpty(result); }); - it('read() should return empty array on empty input', async function () { + it('read() should return empty array on empty input', async function () { const result = sut_r.read(""); assert.isEmpty(result); }); - it('read() should return empty array on space as input', async function () { + it('read() should return empty array on space as input', async function () { const result = sut_r.read(" "); assert.isEmpty(result); }); - it('read() should return empty array on unavailable file name', async function () { + it('read() should return empty array on unavailable file name', async function () { + const inputFilename_unavailable = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/X.keylayout'); const result = sut_r.read(inputFilename_unavailable); assert.isEmpty(result); }); - it('read() should return empty array on typo in path', async function () { - const result = sut_r.read('../data|Italian.keylayout'); + it('read() should return empty array on typo in path', async function () { + const result = sut_r.read(makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '|Italian.keylayout')); assert.isEmpty(result); }); }); diff --git a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts index 1c7c2753cee..f852f1ca9f2 100644 --- a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts +++ b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts @@ -20,7 +20,7 @@ describe('KmnFileWriter', function () { }); describe("write() ", function () { - const inputFilename = makePathToFixture('../data/Italian.keylayout'); + const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Italian.keylayout'); const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); @@ -28,11 +28,12 @@ describe('KmnFileWriter', function () { const converted = sut.convert(read); // empty convert_object from unavailable file name - const inputFilename_unavailable = makePathToFixture('X.keylayout'); + const inputFilename_unavailable = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/X.keylayout'); const read_unavailable = sut_r.read(inputFilename_unavailable); const converted_unavailable = sut.convert(read_unavailable); it('write() should return true (no error) if written', async function () { + const result = sut_w.write(converted); assert.isTrue(result); }); @@ -45,7 +46,7 @@ describe('KmnFileWriter', function () { }); describe("writeData_Rules() ", function () { - const inputFilename = makePathToFixture('../data/Italian.keylayout'); + const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Italian.keylayout'); const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); @@ -53,7 +54,7 @@ describe('KmnFileWriter', function () { const converted = sut.convert(read); // empty convert_object from unavailable file name - const inputFilename_unavailable = makePathToFixture('X.keylayout'); + const inputFilename_unavailable = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/X.keylayout'); const read_unavailable = sut_r.read(inputFilename_unavailable); const converted_unavailable = sut.convert(read_unavailable); @@ -73,12 +74,12 @@ describe('KmnFileWriter', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); - const inputFilename = makePathToFixture('../data/Italian.keylayout'); + const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Italian.keylayout'); const read = sut_r.read(inputFilename); const converted = sut.convert(read); // empty convert_object from unavailable file name - const inputFilename_unavailable = makePathToFixture('X.keylayout'); + const inputFilename_unavailable = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/X.keylayout'); const read_unavailable = sut_r.read(inputFilename_unavailable); const converted_unavailable = sut.convert(read_unavailable); @@ -88,15 +89,15 @@ describe('KmnFileWriter', function () { const converted_empty = sut.convert(read_empty); const out_expected_first: string = - "c ......................................................................\n" - + "c ......................................................................\n" - + "c Keyman keyboard generated by kmn-convert\n" + "c ..................................................................................................................\n" + + "c ..................................................................................................................\n" + + "c Keyman keyboard generated by kmn-convert version: 0.1\n" + "c from Ukelele file: "; const out_expected_last: string = "\n" - + "c ......................................................................\n" - + "c ......................................................................\n" + + "c ..................................................................................................................\n" + + "c ..................................................................................................................\n" + "\n" + "store(&VERSION) '10.0'\n" + "store(&TARGETS) 'any'\n" @@ -124,7 +125,7 @@ describe('KmnFileWriter', function () { }); describe("reviewRules() ", function () { - const inputFilename = makePathToFixture('../data/Italian.keylayout'); + const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Italian.keylayout'); const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); @@ -132,7 +133,7 @@ describe('KmnFileWriter', function () { const converted = sut.convert(read); // empty convert_object from unavailable file name - const inputFilename_unavailable = makePathToFixture('X.keylayout'); + const inputFilename_unavailable = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/X.keylayout'); const read_unavailable = sut_r.read(inputFilename_unavailable); const converted_unavailable = sut.convert(read_unavailable); From ca3697b7c2df658eb12f3da05464a070fb8b3e47 Mon Sep 17 00:00:00 2001 From: Sabine Date: Wed, 16 Apr 2025 14:07:28 +0200 Subject: [PATCH 090/251] feat(developer): create our own test.keylayout and use it in tests --- .../keylayout-to-kmn-converter.ts | 2 +- .../src/kmc-convert/test/data/Test.keylayout | 589 +++++++++++++++ .../test/keylayout-to-kmn-converter.tests.ts | 701 +++++++++++------- 3 files changed, 1042 insertions(+), 250 deletions(-) create mode 100644 developer/src/kmc-convert/test/data/Test.keylayout diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 23166edeede..182d224988b 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -21,7 +21,7 @@ export class KeylayoutToKmnConverter { static readonly INPUT_FILE_EXTENSION = '.keylayout'; static readonly OUTPUT_FILE_EXTENSION = '.kmn'; - static readonly USED_KEYS_COUNT = 51; + static readonly USED_KEYS_COUNT = 50; // we use key Nr 0 (A) -> key Nr 49 (Space) static readonly MAX_CTRL_CHARACTER = 32; static readonly SKIP_COMMENTED_LINES = false; static readonly KMC_CONVERT_VERSION = "0.1"; diff --git a/developer/src/kmc-convert/test/data/Test.keylayout b/developer/src/kmc-convert/test/data/Test.keylayout new file mode 100644 index 00000000000..fe546dbf565 --- /dev/null +++ b/developer/src/kmc-convert/test/data/Test.keylayout @@ -0,0 +1,589 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index 193d1cb909b..404006f52e4 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -27,11 +27,11 @@ describe('KeylayoutToKmnConverter', function () { }); it('run() should throw on null input file name and empty output file name', async function () { - await NodeAssert.rejects(async () => sut.run(null, "")); + await NodeAssert.rejects(async () => sut.run(null, '')); }); it('run() should throw on null input file name and unknown output file name', async function () { - await NodeAssert.rejects(async () => sut.run(null, "X")); + await NodeAssert.rejects(async () => sut.run(null, 'X')); }); it('run() should throw on unavailable input file name and null output file name', async function () { @@ -40,17 +40,17 @@ describe('KeylayoutToKmnConverter', function () { }); it('run() should return on correct input file name and empty output file name ', async function () { - const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Italian.keylayout'); - await NodeAssert.doesNotReject(async () => sut.run(inputFilename, "")); + const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Test.keylayout'); + await NodeAssert.doesNotReject(async () => sut.run(inputFilename, '')); }); it('run() should return on correct input file name and null output file name', async function () { - const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Italian.keylayout'); + const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Test.keylayout'); await NodeAssert.doesNotReject(async () => sut.run(inputFilename, null)); }); it('run() should return on correct input file name and given output file name ', async function () { - const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Italian.keylayout'); + const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Test.keylayout'); const outputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/OutputName.kmn'); await NodeAssert.doesNotReject(async () => sut.run(inputFilename, outputFilename)); }); @@ -62,16 +62,16 @@ describe('KeylayoutToKmnConverter', function () { }); it('run() return on correct input file extention and unsupperted output file extention', async function () { - const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Italian.keylayout'); + const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Test.keylayout'); const outputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/OutputXName.B'); await NodeAssert.doesNotReject(async () => sut.run(inputFilename, outputFilename)); }); }); - describe("convert() ", function () { + describe('convert() ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Italian.keylayout'); + const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Test.keylayout'); const read = sut_r.read(inputFilename); const converted = sut.convert(read); @@ -116,7 +116,7 @@ describe('KeylayoutToKmnConverter', function () { const converted_rule = sut.convert({ keylayout_filename: '', arrayOf_Modifiers: [], - arrayOf_Rules: [["C0", "", "", 0, 0, "", "", 0, 0, "CAPS", "K_A", "A"]] + arrayOf_Rules: [['C0', '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_A', 'A']] }); assert.isTrue((converted_rule.keylayout_filename === '' && converted_rule.arrayOf_Modifiers.length === 0 @@ -162,22 +162,22 @@ describe('KeylayoutToKmnConverter', function () { }); }); - describe("isAcceptableKeymanModifier ", function () { + describe('isAcceptableKeymanModifier ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); [ - ["NCAPS", true], - ["NxCAPS", false], - ["SHIFT", true], - ["ALT", true], - ["RALT", true], - ["LALT", true], - ["CTRL", true], - ["LCTRL", true], - ["RCTRL", true], - ["LCTRL CAPS", true], - ["LCTRL X", false], - ["", true], + ['NCAPS', true], + ['NxCAPS', false], + ['SHIFT', true], + ['ALT', true], + ['RALT', true], + ['LALT', true], + ['CTRL', true], + ['LCTRL', true], + ['RCTRL', true], + ['LCTRL CAPS', true], + ['LCTRL X', false], + ['', true], [null, false], ].forEach(function (values) { it(("isAcceptableKeymanModifier(" + values[0] + ")").padEnd(38, " ") + ' should return ' + values[1], async function () { @@ -187,19 +187,19 @@ describe('KeylayoutToKmnConverter', function () { }); }); - describe("map_UkeleleKC_To_VK ", function () { + describe('map_UkeleleKC_To_VK ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); [ - [0x00, "K_A"], - [0x31, "K_SPACE"], - [0x18, "K_EQUAL"], - [0x10, "K_Y"], - [0x18, "K_EQUAL"], - [0x21, "K_LBRKT"], - [0x999, ""], - [-1, ""], - [null, ""], + [0x00, 'K_A'], + [0x31, 'K_SPACE'], + [0x18, 'K_EQUAL'], + [0x10, 'K_Y'], + [0x18, 'K_EQUAL'], + [0x21, 'K_LBRKT'], + [0x999, ''], + [-1, ''], + [null, ''], ].forEach(function (values) { it(("map_UkeleleKC_To_VK(" + values[0] + ")").padEnd(26, " ") + "should return " + "'" + values[1] + "'", async function () { const result = sut.map_UkeleleKC_To_VK(values[0] as number); @@ -208,7 +208,7 @@ describe('KeylayoutToKmnConverter', function () { }); }); - describe("checkIfCapsIsUsed ", function () { + describe('checkIfCapsIsUsed ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); [ @@ -228,19 +228,24 @@ describe('KeylayoutToKmnConverter', function () { }); }); - describe("get_Modifier_array__From__KeyModifier_array ", function () { + describe('get_Modifier_array__From__KeyModifier_array ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Italian.keylayout'); + const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Test.keylayout'); const read = sut_r.read(inputFilename); const converted = sut.convert(read); - [[[['0', 0]], [['', 'shift? caps? ']]], - [[['0', 1]], [['anyShift caps?', 'shift? rightShift caps? ', 'shift? leftShift caps? ', 'shift leftShift caps ']]], - [[['0', 999]], [null]], - [[['999',]], [null]], - [[['0', -999]], [null]], - [[['0']], [null]], + [ + [[['0', 0]], [['', 'shift? caps? ']]], + // Italian: [[['0', 1]], [['anyShift caps?', 'shift? rightShift caps? ', 'shift? leftShift caps? ', 'shift leftShift caps ']]], + [[['0', 2]], [['shift? leftShift caps? ', 'anyShift caps?', 'shift leftShift caps ', 'shift? rightShift caps? ']]], + [[['0', 999]], [null]], + [[['999',]], [null]], + [[['0', -999]], [null]], + [[['0']], [null]], + + + ].forEach(function (values) { it((values[1][0] !== null) ? ("get_Modifier_array__From__KeyModifier_array(['" + values[0][0][0] + "', '" + values[0][0][1] + "'])").padEnd(68, " ") + " should return ['" + values[1][0][0] + "', '" + values[1][0][1] + "']" : @@ -261,24 +266,28 @@ describe('KeylayoutToKmnConverter', function () { }); }); - describe("get_KeyModifier_array__From__ActionID ", function () { + describe('get_KeyModifier_array__From__ActionID ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Italian.keylayout'); + const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Test.keylayout'); const read = sut_r.read(inputFilename); [ - ["a16", [['32', 3]]], - ["a19", [['45', 3]]], - ["a18", [['24', 0], ['24', 3]]], - ["unknown", []], + // Italian: ['a16', [['32', 3]]], + // Italian: ['a19', [['45', 3]]], + // Italian: ['a18', [['24', 0], ['24', 3]]], + ['A_16', [['32', 5]]], + ['A_19', [['45', 5]]], + ['A_18', [['24', 0], ['24', 5]]], + + ['unknown', []], [undefined, []], [null, []], - [" ", []], - ["", []], + [' ', []], + ['', []], ].forEach(function (values) { - let outstring = "[ "; + let outstring = '[ '; for (let i = 0; i < values[1].length; i++) { outstring = outstring + "[ '" + values[1][i][0] + "', " + values[1][i][1].toString() + "], "; } @@ -290,25 +299,31 @@ describe('KeylayoutToKmnConverter', function () { }); }); - describe("get_ActionID__From__ActionNext ", function () { + describe('get_ActionID__From__ActionNext ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Italian.keylayout'); + const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Test.keylayout'); const read = sut_r.read(inputFilename); [ - ["none", ""], - ["a18", ""], - ["0", ""], - ["1", "a16"], - ["2", "a8"], - ["3", "a17"], - ["", ""], - [" ", ""], - ["99", ""], - [null, ""], - [undefined, ""], - ["unknown", ""], + ['none', ''], + // Italian: ['a18', ''], + ['0', ''], + // Italian: ['1', 'a16'], + // Italian: // Italian: ['2', 'a8'], + // Italian: ['3', 'a17'], + + ['A_18', ''], + ['1', 'A_16'], + ['2', 'A_8'], + ['3', 'A_17'], + + ['', ''], + [' ', ''], + ['99', ''], + [null, ''], + [undefined, ''], + ['unknown', ''], ].forEach(function (values) { it(("get_ActionID__From__ActionNext('" + values[0] + "')").padEnd(49, " ") + ' should return ' + "'" + values[1] + "'", async function () { const result = sut.get_ActionID__From__ActionNext(read, String(values[0])); @@ -317,23 +332,26 @@ describe('KeylayoutToKmnConverter', function () { }); }); - describe("get_ActionIndex__From__ActionId ", function () { + describe('get_ActionIndex__From__ActionId ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Italian.keylayout'); + const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Test.keylayout'); const read = sut_r.read(inputFilename); [ - ["none", 0], - ["a16", 8], - ["a18", 10], - ["a19", 11], - ["0", 0], - ["", 0], - [" ", 0], + ['none', 0], + // Italian: ['a16', 8], + // Italian: ['a18', 10], + // Italian: ['a19', 11], + ['A_16', 8], + ['A_18', 10], + ['A_19', 11], + ['0', 0], + ['', 0], + [' ', 0], [null, 0], [undefined, 0], - ["unknown", 0], + ['unknown', 0], ].forEach(function (values) { it(("get_ActionIndex__From__ActionId('" + values[0] + "')").padEnd(50, " ") + ' should return ' + values[1], async function () { const result = sut.get_ActionIndex__From__ActionId(read, String(values[0])); @@ -342,17 +360,20 @@ describe('KeylayoutToKmnConverter', function () { }); }); - describe("get_Output__From__ActionId_None ", function () { + describe('get_Output__From__ActionId_None ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Italian.keylayout'); + const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Test.keylayout'); const read = sut_r.read(inputFilename); - [["a14", "u"], - ["", ""], - [" ", ""], - ["a18", undefined], - ["unknown", ""], + [ + // Italian: ['a14', 'u'], + ['A_14', 'u'], + ['', ''], + [' ', ''], + // Italian: ['a18', undefined], + ['A_18', undefined], + ['unknown', ''], ].forEach(function (values) { it( ("get_Output__From__ActionId_None('" + values[0] + "')").padEnd(56, " ") + ' should return ' + "'" + values[1] + "'", async function () { @@ -361,9 +382,9 @@ describe('KeylayoutToKmnConverter', function () { }); }); - [[null, ""], - [undefined, ""], - [99, ""], + [[null, ''], + [undefined, ''], + [99, ''], ].forEach(function (values) { it(("get_Output__From__ActionId_None('" + values[0] + "')").padEnd(56, " ") + ' should return ' + values[1], async function () { const result = sut.get_Output__From__ActionId_None(read, String(values[0])); @@ -372,76 +393,144 @@ describe('KeylayoutToKmnConverter', function () { }); }); - describe("get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array ", function () { + describe('get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Italian.keylayout'); + const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Test.keylayout'); const read = sut_r.read(inputFilename); + /*Italian: + + const b1_keycode_arr = [ + ['49', 'K_SPACE', 'a0', '0', 'ˆ'], + ['49', 'K_SPACE', 'a0', '1', 'ˆ'], + ['49', 'K_SPACE', 'a0', '2', 'ˆ'], + ['6', 'K_Z', 'a0', '4', 'ˆ'], + ['25', 'K_9', 'a0', '4', 'ˆ'], + ['43', 'K_COMMA', 'a0', '4', 'ˆ'], + ['49', 'K_SPACE', 'a0', '7', 'ˆ'], + ['0', 'K_A', 'a1', '1', 'Â'], + ['0', 'K_A', 'a1', '2', 'Â'], + ['14', 'K_E', 'a10', '0', 'ê'], + ['34', 'K_I', 'a11', '0', 'î'], + ['31', 'K_O', 'a13', '0', 'ô'], + ['32', 'K_U', 'a14', '0', 'û'], + ['14', 'K_E', 'a2', '1', 'Ê'], + ['14', 'K_E', 'a2', '2', 'Ê'], + ['34', 'K_I', 'a3', '1', 'Î'], + ['34', 'K_I', 'a3', '2', 'Î'], + ['31', 'K_O', 'a5', '1', 'Ô'], + ['31', 'K_O', 'a5', '2', 'Ô'], + ['32', 'K_U', 'a6', '1', 'Û'], + ['32', 'K_U', 'a6', '2', 'Û'], + ['0', 'K_A', 'a9', '0', 'â'] + ]; + const b1_modifierKey_arr = [ + ['K_SPACE', 'a0', '0', 'NCAPS', 'ˆ'], + ['K_SPACE', 'a0', '1', 'NCAPS SHIFT', 'ˆ'], + ['K_SPACE', 'a0', '1', 'SHIFT CAPS', 'ˆ'], + ['K_SPACE', 'a0', '2', 'CAPS', 'ˆ'], + ['K_Z', 'a0', '4', 'NCAPS SHIFT RALT', 'ˆ'], + ['K_9', 'a0', '4', 'NCAPS SHIFT RALT', 'ˆ'], + ['K_COMMA', 'a0', '4', 'NCAPS SHIFT RALT', 'ˆ'], + ['K_SPACE', 'a0', '7', 'NCAPS CTRL', 'ˆ'], + ['K_SPACE', 'a0', '7', 'NCAPS RALT CTRL', 'ˆ'], + ['K_A', 'a1', '1', 'NCAPS SHIFT', 'Â'], + ['K_A', 'a1', '1', 'SHIFT CAPS', 'Â'], + ['K_A', 'a1', '2', 'CAPS', 'Â'], + ['K_E', 'a10', '0', 'NCAPS', 'ê'], + ['K_I', 'a11', '0', 'NCAPS', 'î'], + ['K_O', 'a13', '0', 'NCAPS', 'ô'], + ['K_U', 'a14', '0', 'NCAPS', 'û'], + ['K_E', 'a2', '1', 'NCAPS SHIFT', 'Ê'], + ['K_E', 'a2', '1', 'SHIFT CAPS', 'Ê'], + ['K_E', 'a2', '2', 'CAPS', 'Ê'], + ['K_I', 'a3', '1', 'NCAPS SHIFT', 'Î'], + ['K_I', 'a3', '1', 'SHIFT CAPS', 'Î'], + ['K_I', 'a3', '2', 'CAPS', 'Î'], + ['K_O', 'a5', '1', 'NCAPS SHIFT', 'Ô'], + ['K_O', 'a5', '1', 'SHIFT CAPS', 'Ô'], + ['K_O', 'a5', '2', 'CAPS', 'Ô'], + ['K_U', 'a6', '1', 'NCAPS SHIFT', 'Û'], + ['K_U', 'a6', '1', 'SHIFT CAPS', 'Û'], + ['K_U', 'a6', '2', 'CAPS', 'Û'], + ['K_A', 'a9', '0', 'NCAPS', 'â'] + ]; + + [[b1_keycode_arr, b1_modifierKey_arr], + [[['49', 'K_SPACE', 'a0', '0', 'ˆ']], [['K_SPACE', 'a0', '0', 'NCAPS', 'ˆ']]], + [[['49', 'K_SPACE', 'a0', '0', '']], [['K_SPACE', 'a0', '0', 'NCAPS', '']]], + [[['49', 'K_SPACE', 'a0', '', 'ˆ']], [['K_SPACE', 'a0', '', 'NCAPS', 'ˆ']]], + [[['49', 'K_SPACE', '', '0', 'ˆ']], [['K_SPACE', '', '0', 'NCAPS', 'ˆ']]], + [[['49', '', 'a0', '0', 'ˆ']], [['', 'a0', '0', 'NCAPS', 'ˆ']]], + [[['', 'K_SPACE', 'a0', '0', 'ˆ']], [['K_SPACE', 'a0', '0', 'NCAPS', 'ˆ']]], + [[['', 'K_SPACE', 'a0', '0', 'ˆ']], [['K_SPACE', 'a0', '0', 'NCAPS', 'ˆ']]], + [[['', '', '', '', '']], [['', '', '', 'NCAPS', '']]], + */ const b1_keycode_arr = [ - ['49', 'K_SPACE', 'a0', '0', 'ˆ'], - ['49', 'K_SPACE', 'a0', '1', 'ˆ'], - ['49', 'K_SPACE', 'a0', '2', 'ˆ'], - ['6', 'K_Z', 'a0', '4', 'ˆ'], - ['25', 'K_9', 'a0', '4', 'ˆ'], - ['43', 'K_COMMA', 'a0', '4', 'ˆ'], - ['49', 'K_SPACE', 'a0', '7', 'ˆ'], - ['0', 'K_A', 'a1', '1', 'Â'], - ['0', 'K_A', 'a1', '2', 'Â'], - ['14', 'K_E', 'a10', '0', 'ê'], - ['34', 'K_I', 'a11', '0', 'î'], - ['31', 'K_O', 'a13', '0', 'ô'], - ['32', 'K_U', 'a14', '0', 'û'], - ['14', 'K_E', 'a2', '1', 'Ê'], - ['14', 'K_E', 'a2', '2', 'Ê'], - ['34', 'K_I', 'a3', '1', 'Î'], - ['34', 'K_I', 'a3', '2', 'Î'], - ['31', 'K_O', 'a5', '1', 'Ô'], - ['31', 'K_O', 'a5', '2', 'Ô'], - ['32', 'K_U', 'a6', '1', 'Û'], - ['32', 'K_U', 'a6', '2', 'Û'], - ['0', 'K_A', 'a9', '0', 'â'] + ['49', 'K_SPACE', 'A_0', '0', 'ˆ'], + ['49', 'K_SPACE', 'A_0', '1', 'ˆ'], + ['49', 'K_SPACE', 'A_0', '2', 'ˆ'], + ['6', 'K_Z', 'A_0', '4', 'ˆ'], + ['25', 'K_9', 'A_0', '4', 'ˆ'], + ['43', 'K_COMMA', 'A_0', '4', 'ˆ'], + ['49', 'K_SPACE', 'A_0', '3', 'ˆ'], + ['0', 'K_A', 'A_1', '2', 'Â'], + ['0', 'K_A', 'A_1', '1', 'Â'], + ['14', 'K_E', 'A_10', '0', 'ê'], + ['34', 'K_I', 'A_11', '0', 'î'], + ['31', 'K_O', 'A_13', '0', 'ô'], + ['32', 'K_U', 'A_14', '0', 'û'], + ['14', 'K_E', 'A_2', '2', 'Ê'], + ['14', 'K_E', 'A_2', '1', 'Ê'], + ['34', 'K_I', 'A_3', '2', 'Î'], + ['34', 'K_I', 'A_3', '1', 'Î'], + ['31', 'K_O', 'A_5', '2', 'Ô'], + ['31', 'K_O', 'A_5', '1', 'Ô'], + ['32', 'K_U', 'A_6', '2', 'Û'], + ['32', 'K_U', 'A_6', '1', 'Û'], + ['0', 'K_A', 'A_9', '0', 'â']/**/ ]; const b1_modifierKey_arr = [ - ['K_SPACE', 'a0', '0', 'NCAPS', 'ˆ'], - ['K_SPACE', 'a0', '1', 'NCAPS SHIFT', 'ˆ'], - ['K_SPACE', 'a0', '1', 'SHIFT CAPS', 'ˆ'], - ['K_SPACE', 'a0', '2', 'CAPS', 'ˆ'], - ['K_Z', 'a0', '4', 'NCAPS SHIFT RALT', 'ˆ'], - ['K_9', 'a0', '4', 'NCAPS SHIFT RALT', 'ˆ'], - ['K_COMMA', 'a0', '4', 'NCAPS SHIFT RALT', 'ˆ'], - ['K_SPACE', 'a0', '7', 'NCAPS CTRL', 'ˆ'], - ['K_SPACE', 'a0', '7', 'NCAPS RALT CTRL', 'ˆ'], - ['K_A', 'a1', '1', 'NCAPS SHIFT', 'Â'], - ['K_A', 'a1', '1', 'SHIFT CAPS', 'Â'], - ['K_A', 'a1', '2', 'CAPS', 'Â'], - ['K_E', 'a10', '0', 'NCAPS', 'ê'], - ['K_I', 'a11', '0', 'NCAPS', 'î'], - ['K_O', 'a13', '0', 'NCAPS', 'ô'], - ['K_U', 'a14', '0', 'NCAPS', 'û'], - ['K_E', 'a2', '1', 'NCAPS SHIFT', 'Ê'], - ['K_E', 'a2', '1', 'SHIFT CAPS', 'Ê'], - ['K_E', 'a2', '2', 'CAPS', 'Ê'], - ['K_I', 'a3', '1', 'NCAPS SHIFT', 'Î'], - ['K_I', 'a3', '1', 'SHIFT CAPS', 'Î'], - ['K_I', 'a3', '2', 'CAPS', 'Î'], - ['K_O', 'a5', '1', 'NCAPS SHIFT', 'Ô'], - ['K_O', 'a5', '1', 'SHIFT CAPS', 'Ô'], - ['K_O', 'a5', '2', 'CAPS', 'Ô'], - ['K_U', 'a6', '1', 'NCAPS SHIFT', 'Û'], - ['K_U', 'a6', '1', 'SHIFT CAPS', 'Û'], - ['K_U', 'a6', '2', 'CAPS', 'Û'], - ['K_A', 'a9', '0', 'NCAPS', 'â'] + ['K_SPACE', 'A_0', '0', 'NCAPS', 'ˆ'], + ['K_SPACE', 'A_0', '1', 'CAPS', 'ˆ'], + ['K_SPACE', 'A_0', '2', 'NCAPS SHIFT', 'ˆ'], + ['K_SPACE', 'A_0', '2', 'SHIFT CAPS', 'ˆ'], + ['K_Z', 'A_0', '4', 'NCAPS SHIFT RALT', 'ˆ'], + ['K_9', 'A_0', '4', 'NCAPS SHIFT RALT', 'ˆ'], + ['K_COMMA', 'A_0', '4', 'NCAPS SHIFT RALT', 'ˆ'], + ['K_SPACE', 'A_0', '3', 'NCAPS RALT CTRL', 'ˆ'], + ['K_SPACE', 'A_0', '3', 'NCAPS CTRL', 'ˆ'], + ['K_A', 'A_1', '2', 'NCAPS SHIFT', 'Â'], + ['K_A', 'A_1', '2', 'SHIFT CAPS', 'Â'], + ['K_A', 'A_1', '1', 'CAPS', 'Â'], + ['K_E', 'A_10', '0', 'NCAPS', 'ê'], + ['K_I', 'A_11', '0', 'NCAPS', 'î'], + ['K_O', 'A_13', '0', 'NCAPS', 'ô'], + ['K_U', 'A_14', '0', 'NCAPS', 'û'], + ['K_E', 'A_2', '2', 'NCAPS SHIFT', 'Ê'], + ['K_E', 'A_2', '2', 'SHIFT CAPS', 'Ê'], + ['K_E', 'A_2', '1', 'CAPS', 'Ê'], + ['K_I', 'A_3', '2', 'NCAPS SHIFT', 'Î'], + ['K_I', 'A_3', '2', 'SHIFT CAPS', 'Î'], + ['K_I', 'A_3', '1', 'CAPS', 'Î'], + ['K_O', 'A_5', '2', 'NCAPS SHIFT', 'Ô'], + ['K_O', 'A_5', '2', 'SHIFT CAPS', 'Ô'], + ['K_O', 'A_5', '1', 'CAPS', 'Ô'], + ['K_U', 'A_6', '2', 'NCAPS SHIFT', 'Û'], + ['K_U', 'A_6', '2', 'SHIFT CAPS', 'Û'], + ['K_U', 'A_6', '1', 'CAPS', 'Û'], + ['K_A', 'A_9', '0', 'NCAPS', 'â']/**/ ]; [[b1_keycode_arr, b1_modifierKey_arr], - [[['49', 'K_SPACE', 'a0', '0', 'ˆ']], [['K_SPACE', 'a0', '0', 'NCAPS', 'ˆ']]], - [[['49', 'K_SPACE', 'a0', '0', '']], [['K_SPACE', 'a0', '0', 'NCAPS', '']]], - [[['49', 'K_SPACE', 'a0', '', 'ˆ']], [['K_SPACE', 'a0', '', 'NCAPS', 'ˆ']]], + [[['49', 'K_SPACE', 'A_0', '0', 'ˆ']], [['K_SPACE', 'A_0', '0', 'NCAPS', 'ˆ']]], + [[['49', 'K_SPACE', 'A_0', '0', '']], [['K_SPACE', 'A_0', '0', 'NCAPS', '']]], + [[['49', 'K_SPACE', 'A_0', '', 'ˆ']], [['K_SPACE', 'A_0', '', 'NCAPS', 'ˆ']]], [[['49', 'K_SPACE', '', '0', 'ˆ']], [['K_SPACE', '', '0', 'NCAPS', 'ˆ']]], - [[['49', '', 'a0', '0', 'ˆ']], [['', 'a0', '0', 'NCAPS', 'ˆ']]], - [[['', 'K_SPACE', 'a0', '0', 'ˆ']], [['K_SPACE', 'a0', '0', 'NCAPS', 'ˆ']]], - [[['', 'K_SPACE', 'a0', '0', 'ˆ']], [['K_SPACE', 'a0', '0', 'NCAPS', 'ˆ']]], + [[['49', '', 'A_0', '0', 'ˆ']], [['', 'A_0', '0', 'NCAPS', 'ˆ']]], + [[['', 'K_SPACE', 'A_0', '0', 'ˆ']], [['K_SPACE', 'A_0', '0', 'NCAPS', 'ˆ']]], + [[['', 'K_SPACE', 'A_0', '0', 'ˆ']], [['K_SPACE', 'A_0', '0', 'NCAPS', 'ˆ']]], [[['', '', '', '', '']], [['', '', '', 'NCAPS', '']]], ].forEach(function (values) { @@ -449,16 +538,22 @@ describe('KeylayoutToKmnConverter', function () { const string_in = "get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(['" + "', '" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "', '" + values[0][0][3] + "', '" + values[0][0][4] + "'])"; const string_out = "['" + "', '" + values[1][0][0] + "', '" + values[1][0][1] + "', '" + values[1][0][2] + "', '" + values[1][0][3] + "', '" + values[1][0][4] + "']"; - it((JSON.stringify(values[1]).length > 60) ? 'an array of objects should return an array of objectss' : + it((JSON.stringify(values[1]).length > 60) ? 'an array of objects should return an array of objects' : string_in.padEnd(74, " ") + ' should return ' + string_out, async function () { const result = sut.get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(read, values[0], isCaps_used); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); - [[[['49', 'K_SPACE', 'a0', '0', 'ˆ']], [['K_SPACE', 'a0', '0', '', 'ˆ']]], - [[['49', 'K_SPACE', 'a0', '0', '']], [['K_SPACE', 'a0', '0', '', '']]], - [[['', 'K_SPACE', 'a0', '0', 'ˆ']], [['K_SPACE', 'a0', '0', '', 'ˆ']]], + /* Italian: [[[['49', 'K_SPACE', 'a0', '0', 'ˆ']], [['K_SPACE', 'a0', '0', '', 'ˆ']]], + [[['49', 'K_SPACE', 'a0', '0', '']], [['K_SPACE', 'a0', '0', '', '']]], + [[['', 'K_SPACE', 'a0', '0', 'ˆ']], [['K_SPACE', 'a0', '0', '', 'ˆ']]], + [[['', '', '', '', '']], [['', '', '', '', '']]], + ].forEach(function (values) { */ + + [[[['49', 'K_SPACE', 'A_0', '0', 'ˆ']], [['K_SPACE', 'A_0', '0', '', 'ˆ']]], + [[['49', 'K_SPACE', 'A_0', '0', '']], [['K_SPACE', 'A_0', '0', '', '']]], + [[['', 'K_SPACE', 'A_0', '0', 'ˆ']], [['K_SPACE', 'A_0', '0', '', 'ˆ']]], [[['', '', '', '', '']], [['', '', '', '', '']]], ].forEach(function (values) { @@ -484,39 +579,65 @@ describe('KeylayoutToKmnConverter', function () { }); }); - describe("get_ActionStateOutput_array__From__ActionState ", function () { + describe('get_ActionStateOutput_array__From__ActionState ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Italian.keylayout'); + const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Test.keylayout'); const read = sut_r.read(inputFilename); - [["1", [ - ['a0', '1', 'ˆ'], - ['a1', '1', 'Â'], - ['a10', '1', 'ê'], - ['a11', '1', 'î'], - ['a13', '1', 'ô'], - ['a14', '1', 'û'], - ['a2', '1', 'Ê'], - ['a3', '1', 'Î'], - ['a5', '1', 'Ô'], - ['a6', '1', 'Û'], - ['a9', '1', 'â']],], - ["2", [ - ['a0', '2', '`'], - ['a1', '2', 'À'], - ['a10', '2', 'è'], - ['a11', '2', 'ì'], - ['a13', '2', 'ò'], - ['a14', '2', 'ù'], - ['a2', '2', 'È'], - ['a3', '2', 'Ì'], - ['a5', '2', 'Ò'], - ['a6', '2', 'Ù'], - ['a9', '2', 'à']],], - ["789", [],], - ["", [],], - [" ", [],], + /* + Italian:[['1', [ + ['a0', '1', 'ˆ'], + ['a1', '1', 'Â'], + ['a10', '1', 'ê'], + ['a11', '1', 'î'], + ['a13', '1', 'ô'], + ['a14', '1', 'û'], + ['a2', '1', 'Ê'], + ['a3', '1', 'Î'], + ['a5', '1', 'Ô'], + ['a6', '1', 'Û'], + ['a9', '1', 'â']],], + ['2', [ + ['a0', '2', '`'], + ['a1', '2', 'À'], + ['a10', '2', 'è'], + ['a11', '2', 'ì'], + ['a13', '2', 'ò'], + ['a14', '2', 'ù'], + ['a2', '2', 'È'], + ['a3', '2', 'Ì'], + ['a5', '2', 'Ò'], + ['a6', '2', 'Ù'], + ['a9', '2', 'à']],], + */ + [['1', [ + ['A_0', '1', 'ˆ'], + ['A_1', '1', 'Â'], + ['A_10', '1', 'ê'], + ['A_11', '1', 'î'], + ['A_13', '1', 'ô'], + ['A_14', '1', 'û'], + ['A_2', '1', 'Ê'], + ['A_3', '1', 'Î'], + ['A_5', '1', 'Ô'], + ['A_6', '1', 'Û'], + ['A_9', '1', 'â']],], + ['2', [ + ['A_0', '2', '`'], + ['A_1', '2', 'À'], + ['A_10', '2', 'è'], + ['A_11', '2', 'ì'], + ['A_13', '2', 'ò'], + ['A_14', '2', 'ù'], + ['A_2', '2', 'È'], + ['A_3', '2', 'Ì'], + ['A_5', '2', 'Ò'], + ['A_6', '2', 'Ù'], + ['A_9', '2', 'à']],], + ['789', [],], + ['', [],], + [' ', [],], [123, [],], [null, [],], [undefined, [],], @@ -530,32 +651,53 @@ describe('KeylayoutToKmnConverter', function () { }); }); - describe("get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput ", function () { + describe('get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Italian.keylayout'); + const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Test.keylayout'); const read = sut_r.read(inputFilename); const converted = sut.convert(read); + /* Italian: [ + ['a1', 'A', true, [ + ['a1', 'A', 'a1', '1', 'K_A', 'NCAPS SHIFT'], + ['a1', 'A', 'a1', '1', 'K_A', 'SHIFT CAPS'], + ['a1', 'A', 'a1', '2', 'K_A', 'CAPS']] + ], + ['a1', 'A', false, [ + ['a1', 'A', 'a1', '1', 'K_A', 'SHIFT'], + ['a1', 'A', 'a1', '1', 'K_A', 'SHIFT CAPS'], + ['a1', 'A', 'a1', '2', 'K_A', 'CAPS']] + ], + ['a9', 'a', true, [['a9', 'a', 'a9', '0', 'K_A', 'NCAPS']]], + ['a9', 'a', false, [['a9', 'a', 'a9', '0', 'K_A', '']]], + ['a9', 'a', , [['a9', 'a', 'a9', '0', 'K_A', '']]], + ['a9', '', true, [['a9', '', 'a9', '0', 'K_A', 'NCAPS']]], + ['a9', '', false, [['a9', '', 'a9', '0', 'K_A', '']]], + ['', 'a', true, []], + ['', 'a', false, []], + ['', '', , []], + */ [ - ["a1", "A", true, [ - ['a1', 'A', 'a1', '1', 'K_A', 'NCAPS SHIFT'], - ['a1', 'A', 'a1', '1', 'K_A', 'SHIFT CAPS'], - ['a1', 'A', 'a1', '2', 'K_A', 'CAPS']] + ['A_1', 'A', true, [ + ['A_1', 'A', 'A_1', '1', 'K_A', 'CAPS'], + ['A_1', 'A', 'A_1', '2', 'K_A', 'NCAPS SHIFT'], + ['A_1', 'A', 'A_1', '2', 'K_A', 'SHIFT CAPS'], + ] ], - ["a1", "A", false, [ - ['a1', 'A', 'a1', '1', 'K_A', 'SHIFT'], - ['a1', 'A', 'a1', '1', 'K_A', 'SHIFT CAPS'], - ['a1', 'A', 'a1', '2', 'K_A', 'CAPS']] + ['A_1', 'A', false, [ + ['A_1', 'A', 'A_1', '1', 'K_A', 'CAPS'], + ['A_1', 'A', 'A_1', '2', 'K_A', 'SHIFT'], + ['A_1', 'A', 'A_1', '2', 'K_A', 'SHIFT CAPS']] ], - ["a9", "a", true, [['a9', 'a', 'a9', '0', 'K_A', 'NCAPS']]], - ["a9", "a", false, [['a9', 'a', 'a9', '0', 'K_A', '']]], - ["a9", "a", , [['a9', 'a', 'a9', '0', 'K_A', '']]], - ["a9", "", true, [["a9", "", "a9", "0", "K_A", "NCAPS"]]], - ["a9", "", false, [["a9", "", "a9", "0", "K_A", ""]]], - ["", "a", true, []], - ["", "a", false, []], - ["", "", , []], + ['A_9', 'a', true, [['A_9', 'a', 'A_9', '0', 'K_A', 'NCAPS']]], + ['A_9', 'a', false, [['A_9', 'a', 'A_9', '0', 'K_A', '']]], + ['A_9', 'a', , [['A_9', 'a', 'A_9', '0', 'K_A', '']]], + ['A_9', '', true, [['A_9', '', 'A_9', '0', 'K_A', 'NCAPS']]], + ['A_9', '', false, [['A_9', '', 'A_9', '0', 'K_A', '']]], + ['', 'a', true, []], + ['', 'a', false, []], + ['', '', , []], ].forEach(function (values) { it((JSON.stringify(values[3]).length > 35) ? @@ -567,83 +709,144 @@ describe('KeylayoutToKmnConverter', function () { }); }); - describe("get_KeyActionOutput_array__From__ActionStateOutput_array ", function () { + describe('get_KeyActionOutput_array__From__ActionStateOutput_array ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Italian.keylayout'); + const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Test.keylayout'); const read = sut_r.read(inputFilename); + /* Italian: const b6_actionId_arr = [ + ['a0', '1', 'ˆ'], + ['a1', '1', 'Â'], + ['a10', '1', 'ê'], + ['a11', '1', 'î'], + ['a13', '1', 'ô'], + ['a14', '1', 'û'], + ['a2', '1', 'Ê'], + ['a3', '1', 'Î'], + ['a5', '1', 'Ô'], + ['a6', '1', 'Û'], + ['a9', '1', 'â'] + ]; + const b1_keycode_arr = [ + ['49', 'K_SPACE', 'a0', '0', 'ˆ'], + ['49', 'K_SPACE', 'a0', '1', 'ˆ'], + ['49', 'K_SPACE', 'a0', '2', 'ˆ'], + ['6', 'K_Z', 'a0', '4', 'ˆ'], + ['25', 'K_9', 'a0', '4', 'ˆ'], + ['43', 'K_COMMA', 'a0', '4', 'ˆ'], + ['49', 'K_SPACE', 'a0', '7', 'ˆ'], + ['0', 'K_A', 'a1', '1', 'Â'], + ['0', 'K_A', 'a1', '2', 'Â'], + ['14', 'K_E', 'a10', '0', 'ê'], + ['34', 'K_I', 'a11', '0', 'î'], + ['31', 'K_O', 'a13', '0', 'ô'], + ['32', 'K_U', 'a14', '0', 'û'], + ['14', 'K_E', 'a2', '1', 'Ê'], + ['14', 'K_E', 'a2', '2', 'Ê'], + ['34', 'K_I', 'a3', '1', 'Î'], + ['34', 'K_I', 'a3', '2', 'Î'], + ['31', 'K_O', 'a5', '1', 'Ô'], + ['31', 'K_O', 'a5', '2', 'Ô'], + ['32', 'K_U', 'a6', '1', 'Û'], + ['32', 'K_U', 'a6', '2', 'Û'], + ['0', 'K_A', 'a9', '0', 'â'] + ]; + */ const b6_actionId_arr = [ - ['a0', '1', 'ˆ'], - ['a1', '1', 'Â'], - ['a10', '1', 'ê'], - ['a11', '1', 'î'], - ['a13', '1', 'ô'], - ['a14', '1', 'û'], - ['a2', '1', 'Ê'], - ['a3', '1', 'Î'], - ['a5', '1', 'Ô'], - ['a6', '1', 'Û'], - ['a9', '1', 'â'] + ['A_0', '1', 'ˆ'], + ['A_1', '1', 'Â'], + ['A_10', '1', 'ê'], + ['A_11', '1', 'î'], + ['A_13', '1', 'ô'], + ['A_14', '1', 'û'], + ['A_2', '1', 'Ê'], + ['A_3', '1', 'Î'], + ['A_5', '1', 'Ô'], + ['A_6', '1', 'Û'], + ['A_9', '1', 'â'] ]; const b1_keycode_arr = [ - ['49', 'K_SPACE', 'a0', '0', 'ˆ'], - ['49', 'K_SPACE', 'a0', '1', 'ˆ'], - ['49', 'K_SPACE', 'a0', '2', 'ˆ'], - ['6', 'K_Z', 'a0', '4', 'ˆ'], - ['25', 'K_9', 'a0', '4', 'ˆ'], - ['43', 'K_COMMA', 'a0', '4', 'ˆ'], - ['49', 'K_SPACE', 'a0', '7', 'ˆ'], - ['0', 'K_A', 'a1', '1', 'Â'], - ['0', 'K_A', 'a1', '2', 'Â'], - ['14', 'K_E', 'a10', '0', 'ê'], - ['34', 'K_I', 'a11', '0', 'î'], - ['31', 'K_O', 'a13', '0', 'ô'], - ['32', 'K_U', 'a14', '0', 'û'], - ['14', 'K_E', 'a2', '1', 'Ê'], - ['14', 'K_E', 'a2', '2', 'Ê'], - ['34', 'K_I', 'a3', '1', 'Î'], - ['34', 'K_I', 'a3', '2', 'Î'], - ['31', 'K_O', 'a5', '1', 'Ô'], - ['31', 'K_O', 'a5', '2', 'Ô'], - ['32', 'K_U', 'a6', '1', 'Û'], - ['32', 'K_U', 'a6', '2', 'Û'], - ['0', 'K_A', 'a9', '0', 'â'] + + + ['49', 'K_SPACE', 'A_0', '0', 'ˆ'], + ['49', 'K_SPACE', 'A_0', '1', 'ˆ'], + ['49', 'K_SPACE', 'A_0', '2', 'ˆ'], + ['49', 'K_SPACE', 'A_0', '3', 'ˆ'], + ['6', 'K_Z', 'A_0', '4', 'ˆ'], + ['25', 'K_9', 'A_0', '4', 'ˆ'], + ['43', 'K_COMMA', 'A_0', '4', 'ˆ'], + + ['0', 'K_A', 'A_1', '1', 'Â'], + ['0', 'K_A', 'A_1', '2', 'Â'], + ['14', 'K_E', 'A_10', '0', 'ê'], + ['34', 'K_I', 'A_11', '0', 'î'], + ['31', 'K_O', 'A_13', '0', 'ô'], + ['32', 'K_U', 'A_14', '0', 'û'], + ['14', 'K_E', 'A_2', '1', 'Ê'], + ['14', 'K_E', 'A_2', '2', 'Ê'], + ['34', 'K_I', 'A_3', '1', 'Î'], + ['34', 'K_I', 'A_3', '2', 'Î'], + ['31', 'K_O', 'A_5', '1', 'Ô'], + ['31', 'K_O', 'A_5', '2', 'Ô'], + ['32', 'K_U', 'A_6', '1', 'Û'], + ['32', 'K_U', 'A_6', '2', 'Û'], + ['0', 'K_A', 'A_9', '0', 'â'] ]; [[b6_actionId_arr, b1_keycode_arr], ].forEach(function (values) { - it(("get_KeyActionOutput_array__From__ActionStateOutput_array([['" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "'],..])").padEnd(73, " ") + ' should return an array of objects', async function () { + it(("get_KeyActionOutput_array__From__ActionStateOutput_array([['" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "'],..])").padEnd(73, " ") + '1 should return an array of objects', async function () { const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0]); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); //----------------- + /* Italian: const oneEntryResult = [ + ['49', 'K_SPACE', 'a0', '0', 'ˆ'], + ['49', 'K_SPACE', 'a0', '1', 'ˆ'], + ['49', 'K_SPACE', 'a0', '2', 'ˆ'], + ['6', 'K_Z', 'a0', '4', 'ˆ'], + ['25', 'K_9', 'a0', '4', 'ˆ'], + ['43', 'K_COMMA', 'a0', '4', 'ˆ'], + ['49', 'K_SPACE', 'a0', '7', 'ˆ'] + ]; + const oneEntryResultNoOutput = [ + ['49', 'K_SPACE', 'a0', '0', ''], + ['49', 'K_SPACE', 'a0', '1', ''], + ['49', 'K_SPACE', 'a0', '2', ''], + ['6', 'K_Z', 'a0', '4', ''], + ['25', 'K_9', 'a0', '4', ''], + ['43', 'K_COMMA', 'a0', '4', ''], + ['49', 'K_SPACE', 'a0', '7', ''] + ] ; + */ + const oneEntryResult = [ - ["49", "K_SPACE", "a0", "0", "ˆ"], - ["49", "K_SPACE", "a0", "1", "ˆ"], - ["49", "K_SPACE", "a0", "2", "ˆ"], - ["6", "K_Z", "a0", "4", "ˆ"], - ["25", "K_9", "a0", "4", "ˆ"], - ["43", "K_COMMA", "a0", "4", "ˆ"], - ["49", "K_SPACE", "a0", "7", "ˆ"] + ['49', 'K_SPACE', 'A_0', '0', 'ˆ'], + ['49', 'K_SPACE', 'A_0', '1', 'ˆ'], + ['49', 'K_SPACE', 'A_0', '2', 'ˆ'], + ['49', 'K_SPACE', 'A_0', '3', 'ˆ'], + ['6', 'K_Z', 'A_0', '4', 'ˆ'], + ['25', 'K_9', 'A_0', '4', 'ˆ'], + ['43', 'K_COMMA', 'A_0', '4', 'ˆ'] ]; const oneEntryResultNoOutput = [ - ["49", "K_SPACE", "a0", "0", ""], - ["49", "K_SPACE", "a0", "1", ""], - ["49", "K_SPACE", "a0", "2", ""], - ["6", "K_Z", "a0", "4", ""], - ["25", "K_9", "a0", "4", ""], - ["43", "K_COMMA", "a0", "4", ""], - ["49", "K_SPACE", "a0", "7", ""] + ['49', 'K_SPACE', 'A_0', '0', ''], + ['49', 'K_SPACE', 'A_0', '1', ''], + ['49', 'K_SPACE', 'A_0', '2', ''], + ['49', 'K_SPACE', 'A_0', '3', ''], + ['6', 'K_Z', 'A_0', '4', ''], + ['25', 'K_9', 'A_0', '4', ''], + ['43', 'K_COMMA', 'A_0', '4', ''] ]; - [[[['a0', '1', 'ˆ']], oneEntryResult], - [[['a0', '1', '']], oneEntryResultNoOutput], - [[['a0', '', 'ˆ']], oneEntryResult], + [[[['A_0', '1', 'ˆ']], oneEntryResult], + [[['A_0', '1', '']], oneEntryResultNoOutput], + [[['A_0', '', 'ˆ']], oneEntryResult], ].forEach(function (values) { - it(("get_KeyActionOutput_array__From__ActionStateOutput_array(['" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "'])").padEnd(73, " ") + ' should return an array of objects', async function () { + it(("get_KeyActionOutput_array__From__ActionStateOutput_array(['" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "'])").padEnd(73, " ") + '2 should return an array of objects', async function () { const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0]); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); From 94d3e542ebe79861ed4ba09c02ae54cb1371840d Mon Sep 17 00:00:00 2001 From: Sabine Date: Wed, 16 Apr 2025 17:22:35 +0200 Subject: [PATCH 091/251] feat(developer): use test.keylayout in all tests; use single paths instead of relative path for test/data --- .../src/keylayout-to-kmn/keylayout-file-reader.ts | 2 +- .../src/keylayout-to-kmn/keylayout-to-kmn-converter.ts | 6 +++--- developer/src/kmc-convert/test/data/Test.keylayout | 10 ++++++++-- .../test/keylayout-to-kmn-converter.tests.ts | 2 +- .../src/kmc-convert/test/kmn-file-reader.tests.ts | 4 ++-- .../src/kmc-convert/test/kmn-file-writer.tests.ts | 8 ++++---- 6 files changed, 19 insertions(+), 13 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts index aba87801b5d..1180ce71726 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts @@ -57,7 +57,7 @@ export class KeylayoutFileReader { }; try { - xmlFile = this.callbacks.fs.readFileSync(this.callbacks.path.join(process.cwd(), KeylayoutToKmnConverter.TEST_DATA_SUBFOLDER, this.callbacks.path.basename(absolutefilename)), 'utf8'); + xmlFile = this.callbacks.fs.readFileSync(this.callbacks.path.join(process.cwd(), KeylayoutToKmnConverter.TEST_SUBFOLDER, KeylayoutToKmnConverter.DATA_SUBFOLDER, this.callbacks.path.basename(absolutefilename)), 'utf8'); const parser = new XMLParser(options); jsonObj = parser.parse(xmlFile); // get plain Object this.boxArray(jsonObj.keyboard); // jsonObj now contains arrays; no single fields diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 182d224988b..02359581f14 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -21,13 +21,13 @@ export class KeylayoutToKmnConverter { static readonly INPUT_FILE_EXTENSION = '.keylayout'; static readonly OUTPUT_FILE_EXTENSION = '.kmn'; - static readonly USED_KEYS_COUNT = 50; // we use key Nr 0 (A) -> key Nr 49 (Space) + static readonly USED_KEYS_COUNT = 51; // we use key Nr 0 (A) -> key Nr 49 (Space) static readonly MAX_CTRL_CHARACTER = 32; static readonly SKIP_COMMENTED_LINES = false; static readonly KMC_CONVERT_VERSION = "0.1"; static readonly DATA_SUBFOLDER = 'data'; - static readonly TEST_DATA_SUBFOLDER = 'test/data'; + static readonly TEST_SUBFOLDER = 'test'; private options: CompilerOptions; @@ -96,7 +96,7 @@ export class KeylayoutToKmnConverter { // get filename from data that had been read const fileNameNoExtention = jsonObj.keyboard['@_name']; - const filePath = this.callbacks.path.join(process.cwd(), KeylayoutToKmnConverter.TEST_DATA_SUBFOLDER); + const filePath = this.callbacks.path.join(process.cwd(), KeylayoutToKmnConverter.TEST_SUBFOLDER, KeylayoutToKmnConverter.DATA_SUBFOLDER); data_object.keylayout_filename = this.callbacks.path.join(filePath, (fileNameNoExtention + ".keylayout")); diff --git a/developer/src/kmc-convert/test/data/Test.keylayout b/developer/src/kmc-convert/test/data/Test.keylayout index fe546dbf565..87b8420ecc1 100644 --- a/developer/src/kmc-convert/test/data/Test.keylayout +++ b/developer/src/kmc-convert/test/data/Test.keylayout @@ -95,6 +95,7 @@ + @@ -147,6 +148,7 @@ + @@ -199,6 +201,7 @@ + @@ -251,6 +254,7 @@ + @@ -303,6 +307,7 @@ + @@ -355,6 +360,7 @@ + @@ -407,7 +413,7 @@ - + @@ -460,7 +466,7 @@ - + diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index 404006f52e4..87d842a6b54 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -56,7 +56,7 @@ describe('KeylayoutToKmnConverter', function () { }); it('run() should throw on incorrect input file extention and output file extention', async function () { - const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Italian_command.A'); + const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Test_command.A'); const outputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/data/OutputXName.B'); await NodeAssert.rejects(async () => sut.run(inputFilename, outputFilename)); }); diff --git a/developer/src/kmc-convert/test/kmn-file-reader.tests.ts b/developer/src/kmc-convert/test/kmn-file-reader.tests.ts index aa655f26e71..3b53763c933 100644 --- a/developer/src/kmc-convert/test/kmn-file-reader.tests.ts +++ b/developer/src/kmc-convert/test/kmn-file-reader.tests.ts @@ -24,7 +24,7 @@ describe('KeylayoutFileReader', function () { const sut_r = new KeylayoutFileReader(compilerTestCallbacks); it('read() should return filled array on correct input', async function () { - const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Italian.keylayout'); + const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Test.keylayout'); const result = sut_r.read(inputFilename); assert.isNotEmpty(result); }); @@ -51,7 +51,7 @@ describe('KeylayoutFileReader', function () { }); it('read() should return empty array on typo in path', async function () { - const result = sut_r.read(makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '|Italian.keylayout')); + const result = sut_r.read(makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '|Test.keylayout')); assert.isEmpty(result); }); }); diff --git a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts index f852f1ca9f2..2a8dfe9d3de 100644 --- a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts +++ b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts @@ -20,7 +20,7 @@ describe('KmnFileWriter', function () { }); describe("write() ", function () { - const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Italian.keylayout'); + const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Test.keylayout'); const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); @@ -46,7 +46,7 @@ describe('KmnFileWriter', function () { }); describe("writeData_Rules() ", function () { - const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Italian.keylayout'); + const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Test.keylayout'); const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); @@ -74,7 +74,7 @@ describe('KmnFileWriter', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); - const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Italian.keylayout'); + const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Test.keylayout'); const read = sut_r.read(inputFilename); const converted = sut.convert(read); @@ -125,7 +125,7 @@ describe('KmnFileWriter', function () { }); describe("reviewRules() ", function () { - const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Italian.keylayout'); + const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Test.keylayout'); const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); From a10849b93933ca0c5e02ff7fe0239f18d57afbb2 Mon Sep 17 00:00:00 2001 From: Sabine Date: Wed, 16 Apr 2025 17:31:12 +0200 Subject: [PATCH 092/251] feat(developer): replace empty output in test.keylayout --- .../src/kmc-convert/test/data/Test.keylayout | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/developer/src/kmc-convert/test/data/Test.keylayout b/developer/src/kmc-convert/test/data/Test.keylayout index 87b8420ecc1..911e401fb9f 100644 --- a/developer/src/kmc-convert/test/data/Test.keylayout +++ b/developer/src/kmc-convert/test/data/Test.keylayout @@ -95,7 +95,7 @@ - + @@ -148,7 +148,7 @@ - + @@ -201,7 +201,7 @@ - + @@ -254,7 +254,7 @@ - + @@ -307,7 +307,7 @@ - + @@ -360,7 +360,7 @@ - + @@ -413,7 +413,7 @@ - + @@ -466,7 +466,7 @@ - + From cb795f2b5d63ad4f4bdae617a8b4a250679a55d4 Mon Sep 17 00:00:00 2001 From: Sabine Date: Tue, 22 Apr 2025 18:56:01 +0200 Subject: [PATCH 093/251] feat(developer): use callback for error msg --- .../src/keylayout-to-kmn/keylayout-file-reader.ts | 8 +++++--- .../src/keylayout-to-kmn/keylayout-to-kmn-converter.ts | 2 +- .../src/kmc-convert/test/kmn-file-reader.tests.ts | 10 +++++----- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts index 1180ce71726..3ae96e27eec 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts @@ -9,6 +9,7 @@ import { CompilerCallbacks } from "@keymanapp/developer-utils"; import { XMLParser } from 'fast-xml-parser'; import { util } from '@keymanapp/common-types'; import { KeylayoutToKmnConverter } from './keylayout-to-kmn-converter.js'; +import { ConverterMessages } from '../converter-messages.js'; import boxXmlArray = util.boxXmlArray; export class KeylayoutFileReader { @@ -45,7 +46,7 @@ export class KeylayoutFileReader { * @param absolutefilename the ukelele .keylayout-file to be parsed * @return in case of success: json object containing data of the .keylayout file; else null */ - public read(absolutefilename: string): Object { + public read(inputFilename: string): Object { let xmlFile; let jsonObj = []; @@ -57,13 +58,14 @@ export class KeylayoutFileReader { }; try { - xmlFile = this.callbacks.fs.readFileSync(this.callbacks.path.join(process.cwd(), KeylayoutToKmnConverter.TEST_SUBFOLDER, KeylayoutToKmnConverter.DATA_SUBFOLDER, this.callbacks.path.basename(absolutefilename)), 'utf8'); + xmlFile = this.callbacks.fs.readFileSync(this.callbacks.path.join(process.cwd(), KeylayoutToKmnConverter.TEST_SUBFOLDER, KeylayoutToKmnConverter.DATA_SUBFOLDER, this.callbacks.path.basename(inputFilename)), 'utf8'); const parser = new XMLParser(options); jsonObj = parser.parse(xmlFile); // get plain Object this.boxArray(jsonObj.keyboard); // jsonObj now contains arrays; no single fields } catch (err) { - console.log(err.message); + this.callbacks.reportMessage(ConverterMessages.Error_FileNotFound({ inputFilename })); + return null; } return jsonObj; } diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 02359581f14..a906e36ce41 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -92,7 +92,7 @@ export class KeylayoutToKmnConverter { }; // ToDo in a new PR: check tags ( issue # 13599) - if (jsonObj.hasOwnProperty("keyboard")) { + if ((jsonObj !== null) && (jsonObj.hasOwnProperty("keyboard"))) { // get filename from data that had been read const fileNameNoExtention = jsonObj.keyboard['@_name']; diff --git a/developer/src/kmc-convert/test/kmn-file-reader.tests.ts b/developer/src/kmc-convert/test/kmn-file-reader.tests.ts index 3b53763c933..bb464359744 100644 --- a/developer/src/kmc-convert/test/kmn-file-reader.tests.ts +++ b/developer/src/kmc-convert/test/kmn-file-reader.tests.ts @@ -31,28 +31,28 @@ describe('KeylayoutFileReader', function () { it('read() should return empty array on null input', async function () { const result = sut_r.read(null); - assert.isEmpty(result); + assert.isNull(result); }); it('read() should return empty array on empty input', async function () { const result = sut_r.read(""); - assert.isEmpty(result); + assert.isNull(result); }); it('read() should return empty array on space as input', async function () { const result = sut_r.read(" "); - assert.isEmpty(result); + assert.isNull(result); }); it('read() should return empty array on unavailable file name', async function () { const inputFilename_unavailable = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/X.keylayout'); const result = sut_r.read(inputFilename_unavailable); - assert.isEmpty(result); + assert.isNull(result); }); it('read() should return empty array on typo in path', async function () { const result = sut_r.read(makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '|Test.keylayout')); - assert.isEmpty(result); + assert.isNull(result); }); }); }); From 6ac48da82a3e72665c1bd31741834526c248f0c7 Mon Sep 17 00:00:00 2001 From: Sabine Date: Thu, 24 Apr 2025 14:06:52 +0200 Subject: [PATCH 094/251] feat(developer): use callback for error msg in kmn-file-writer --- .../src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts index d2697b3dfcf..71b997ab295 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts @@ -8,6 +8,7 @@ import { CompilerCallbacks, CompilerOptions } from "@keymanapp/developer-utils"; import { KeylayoutToKmnConverter, convert_object, Rule } from './keylayout-to-kmn-converter.js'; import { util } from '@keymanapp/common-types'; +import { ConverterMessages } from '../converter-messages.js'; export class KmnFileWriter { @@ -33,7 +34,8 @@ export class KmnFileWriter { this.callbacks.fs.writeFileSync(data_ukelele.kmn_filename, new TextEncoder().encode(data)); return true; } catch (err) { - console.log('ERROR writing kmn file:' + err.message); + //console.log('ERROR writing kmn file:' + err.message); + this.callbacks.reportMessage(ConverterMessages.Error_OutputFilenameIsRequired()); return false; } } From 5c7d217ed4c938aa3d929f444c7b9f61b310f82c Mon Sep 17 00:00:00 2001 From: Sabine Date: Thu, 24 Apr 2025 14:08:51 +0200 Subject: [PATCH 095/251] feat(developer): converter messages --- developer/src/kmc-convert/src/converter-messages.ts | 10 +++++----- .../src/keylayout-to-kmn/keylayout-to-kmn-converter.ts | 5 +---- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/developer/src/kmc-convert/src/converter-messages.ts b/developer/src/kmc-convert/src/converter-messages.ts index c270464f217..d6500033c12 100644 --- a/developer/src/kmc-convert/src/converter-messages.ts +++ b/developer/src/kmc-convert/src/converter-messages.ts @@ -18,13 +18,13 @@ const SevError = CompilerErrorSeverity.Error | Namespace; export class ConverterMessages { static ERROR_OutputFilenameIsRequired = SevError | 0x0001; static Error_OutputFilenameIsRequired = () => - m(this.ERROR_OutputFilenameIsRequired, `An output filename is required for keyboard conversion.`); + m(this.ERROR_OutputFilenameIsRequired, `An output filename is required for keyboard conversion.`); static ERROR_NoConverterFound = SevError | 0x0002; - static Error_NoConverterFound = (o:{inputFilename: string, outputFilename: string}) => - m(this.ERROR_NoConverterFound, `No converter is available that can convert from '${def(o.inputFilename)}' to '${def(o.outputFilename)}'.`); + static Error_NoConverterFound = (o: { inputFilename: string, outputFilename: string; }) => + m(this.ERROR_NoConverterFound, `No converter is available that can convert from '${def(o.inputFilename)}' to '${def(o.outputFilename)}'.`); static ERROR_FileNotFound = SevError | 0x0003; - static Error_FileNotFound = (o:{inputFilename: string}) => - m(this.ERROR_FileNotFound, `Input filename '${def(o.inputFilename)}' does not exist or could not be loaded.`); + static Error_FileNotFound = (o: { inputFilename: string; }) => + m(this.ERROR_FileNotFound, `Input filename '${def(o.inputFilename)}' does not exist or could not be loaded.`); } diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index a906e36ce41..84c387e2226 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -55,13 +55,11 @@ export class KeylayoutToKmnConverter { const jsonO: object = KeylayoutReader.read(inputFilename); if (!jsonO) { throw new Error('Error while processing read()'); - return null; } const outArray: convert_object = await this.convert(jsonO, outputFilename); if (!outArray) { throw new Error('Error while processing convert()'); - return null; } const kmnFileWriter = new KmnFileWriter(this.callbacks, this.options); @@ -69,7 +67,6 @@ export class KeylayoutToKmnConverter { if (!out_text_ok) { throw new Error('Error while processing write()'); - return null; } return null; } @@ -402,7 +399,7 @@ export class KeylayoutToKmnConverter { } } } else { - console.log("ERROR : some output characters can not be used in keyman \"", + console.log("ERROR : some output characters can not be used in Keyman \"", (jsonObj.keyboard['@_name'] + ".keylayout\""), "\"\" :", jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]); From b401a26286a893f8c40c34dfe9ff1652caf391f8 Mon Sep 17 00:00:00 2001 From: Sabine Date: Wed, 30 Apr 2025 17:27:09 +0200 Subject: [PATCH 096/251] feat(developer): start validation: add new keylayout validator (= copy of keyboard3Test validator ) that can be used from kmc.convert --- common/web/types/src/schema-validators.ts | 2 ++ .../src/kmc-convert/src/converter-messages.ts | 12 ++++++++++++ .../keylayout-to-kmn/keylayout-file-reader.ts | 19 +++++++++++++++++++ .../keylayout-to-kmn-converter.ts | 19 +++++++++++++++++++ 4 files changed, 52 insertions(+) diff --git a/common/web/types/src/schema-validators.ts b/common/web/types/src/schema-validators.ts index ed07d44fde7..7c4d337fefa 100644 --- a/common/web/types/src/schema-validators.ts +++ b/common/web/types/src/schema-validators.ts @@ -2,6 +2,7 @@ import kpj from './schemas/kpj.schema.validator.mjs'; import kpj90 from './schemas/kpj-9.0.schema.validator.mjs'; import kvks from './schemas/kvks.schema.validator.mjs'; import ldmlKeyboard3 from './schemas/ldml-keyboard3.schema.validator.mjs'; +import keylayout from './schemas/keylayout.schema.validator.mjs'; import ldmlKeyboardTest3 from './schemas/ldml-keyboardtest3.schema.validator.mjs'; import displayMap from './schemas/displaymap.schema.validator.mjs'; import touchLayoutClean from './schemas/keyman-touch-layout.clean.spec.validator.mjs'; @@ -16,6 +17,7 @@ const SchemaValidators = { kpj90, kvks, ldmlKeyboard3, + keylayout, ldmlKeyboardTest3, displayMap, touchLayoutClean, diff --git a/developer/src/kmc-convert/src/converter-messages.ts b/developer/src/kmc-convert/src/converter-messages.ts index d6500033c12..1f70144d613 100644 --- a/developer/src/kmc-convert/src/converter-messages.ts +++ b/developer/src/kmc-convert/src/converter-messages.ts @@ -27,4 +27,16 @@ export class ConverterMessages { static ERROR_FileNotFound = SevError | 0x0003; static Error_FileNotFound = (o: { inputFilename: string; }) => m(this.ERROR_FileNotFound, `Input filename '${def(o.inputFilename)}' does not exist or could not be loaded.`); + + // from SRL + static ERROR_InvalidFile = SevError | 0x0007; + static Error_InvalidFile = (o:{errorText: string}) => + m(this.ERROR_InvalidFile, `The source file has an invalid structure: ${def(o.errorText)}`); + + // from SRL + static ERROR_SchemaValidationError = SevError | 0x0011; + static Error_SchemaValidationError = (o:{instancePath:string, keyword:string, message: string, params: string}) => m(this.ERROR_SchemaValidationError, + `Error validating Keylayout XML file: ${def(o.instancePath)}: ${def(o.keyword)}: ${def(o.message)} ${def(o.params)}`); + + } diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts index 3ae96e27eec..c72cb7e70de 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts @@ -10,13 +10,32 @@ import { XMLParser } from 'fast-xml-parser'; import { util } from '@keymanapp/common-types'; import { KeylayoutToKmnConverter } from './keylayout-to-kmn-converter.js'; import { ConverterMessages } from '../converter-messages.js'; +import { SchemaValidators } from '@keymanapp/common-types'; import boxXmlArray = util.boxXmlArray; export class KeylayoutFileReader { constructor(private callbacks: CompilerCallbacks /*,private options: CompilerOptions*/) { }; + /** + * @returns true if valid, false if invalid + */ + public validate(source: any): boolean { + if(!SchemaValidators.default.keylayout(source)) { + console.log("SchemaValidators.default.keylayout).errors ",(SchemaValidators.default.keylayout).errors); + for (const err of (SchemaValidators.default.keylayout).errors) { + this.callbacks.reportMessage(ConverterMessages.Error_SchemaValidationError({ + instancePath: err.instancePath, + keyword: err.keyword, + message: err.message || 'Unknown AJV Error', // docs say 'message' is optional if 'messages:false' in options + params: Object.entries(err.params || {}).sort().map(([k,v])=>`${k}="${v}"`).join(' '), + })); + } + return false; + } + return true; + } /** * @brief member function to box single-entry objects into arrays diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 84c387e2226..7c42327a2f5 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -9,6 +9,7 @@ import { CompilerCallbacks, CompilerOptions } from "@keymanapp/developer-utils"; import { ConverterToKmnArtifacts } from "../converter-artifacts.js"; import { KmnFileWriter } from './kmn-file-writer.js'; import { KeylayoutFileReader } from './keylayout-file-reader.js'; +import { ConverterMessages } from '../converter-messages.js'; export interface convert_object { keylayout_filename: string, @@ -53,6 +54,24 @@ export class KeylayoutToKmnConverter { const KeylayoutReader = new KeylayoutFileReader(this.callbacks/*, this.options*/); const jsonO: object = KeylayoutReader.read(inputFilename); + + + // just to check if it works: validate file with stevens schema file ------------------------------------------------- + + console.log("stop ",); + try { + // validate the object tree against the .xsd schema + if (!KeylayoutReader.validate(jsonO)) { + //if (KeylayoutReader.validate(jsonO)) { + return null; + } + } catch (e) { + this.callbacks.reportMessage(ConverterMessages.Error_InvalidFile({ errorText: e.toString() })); + return null; + } + // just to check if it works: validate file with stevens schema file ------------------------------------------------- + + if (!jsonO) { throw new Error('Error while processing read()'); } From b2413a9d76275f00e90af76f4d28dc339e6fa725 Mon Sep 17 00:00:00 2001 From: Sabine Date: Mon, 5 May 2025 19:38:37 +0200 Subject: [PATCH 097/251] feat(developer): change xml version --- developer/src/kmc-convert/test/data/Test.keylayout | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/developer/src/kmc-convert/test/data/Test.keylayout b/developer/src/kmc-convert/test/data/Test.keylayout index 911e401fb9f..a6b697b4d71 100644 --- a/developer/src/kmc-convert/test/data/Test.keylayout +++ b/developer/src/kmc-convert/test/data/Test.keylayout @@ -1,4 +1,4 @@ - + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/standards-data/keylayout/create_keylayout_schema.sh b/resources/standards-data/keylayout/create_keylayout_schema.sh new file mode 100644 index 00000000000..5d287fe5e41 --- /dev/null +++ b/resources/standards-data/keylayout/create_keylayout_schema.sh @@ -0,0 +1,135 @@ +#!/usr/bin/env bash + +# Copyright: © SIL International. +# Description: Import new files from CLDR tech preview +# Create Date: 17 Oct 2022 +# Authors: Steven R. Loomis (SRL) + +set -eu + +# if [[ $# -ne 2 ]]; +# then +# echo >&2 "Usage: $0 " +# exit 1 +# fi + +## START STANDARD BUILD SCRIPT INCLUDE +# adjust relative paths as necessary +THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" +. "${THIS_SCRIPT%/*}/../../../resources/build/build-utils.sh" +## END STANDARD BUILD SCRIPT INCLUDE + +. "$KEYMAN_ROOT/resources/build/jq.inc.sh" + +cd "$THIS_SCRIPT_PATH" + +# KEYMAN_CORE_LDML="../../../core/include/ldml" + +# builder_echo debug "Building ${KEYMAN_CORE_LDML}" + +# "${KEYMAN_CORE_LDML}/build.sh" || builder_die "building core/include/ldml failed" + +# KEYMAN_CORE_LDML_JS="${KEYMAN_CORE_LDML}/build/keyman_core_ldml.js" + +# if [ ! -f "${KEYMAN_CORE_LDML_JS}" ]; +# then +# builder_die "Could not read ${KEYMAN_CORE_LDML_JS} - check build." +# fi + +# CLDR_VERSION="$1" +# shift + +# CLDR_DIR="$1" +# shift + +# node verify-version.mjs "${CLDR_VERSION}" || builder_die "Check CLDR version" + +# KEYBOARDS_DIR="${CLDR_DIR}/keyboards" +# DTD_DIR="${KEYBOARDS_DIR}/dtd" + +# KEYMAN_CORE_LDML="../../../core/include/ldml" + KEYLAYOUT_DIR=$THIS_SCRIPT_PATH + DTD_DIR="${KEYLAYOUT_DIR}/dtd" + +# IMPORT_DIR="${KEYBOARDS_DIR}/import" +# DATA_DIR="${KEYBOARDS_DIR}/3.0" +# TEST_DIR="${KEYBOARDS_DIR}/test" +# ABNF_DIR="${KEYBOARDS_DIR}/abnf" + +# a file to check +# CHECK_1="${DTD_DIR}/ldmlKeyboard3.dtd" # Critical, present in prior CLDR +# CHECK_2="${DTD_DIR}/ldmlKeyboardTest3.dtd" # Only in Keyboard 3.0+ +# CHECK_3="${ABNF_DIR}/transform-from-required.abnf" # Present in v47+ + +# if [[ ! -f "${CHECK_1}" ]]; +# then +# builder_die "${CHECK_1} did not exist: is ${CLDR_DIR} a valid CLDR keyboard directory?" +# fi + +# if [[ ! -f "${CHECK_2}" ]]; +# then +# builder_die "${CHECK_2} did not exist: is ${CLDR_DIR} a valid CLDR keyboard directory?" +# fi + +# if [[ ! -f "${CHECK_3}" ]]; +# then +# builder_die "${CHECK_3} did not exist: does ${CLDR_DIR} contain CLDR 47+? Or did ABNF change?" +# fi + + +# # collect git info +# GIT_DESCRIBE=$(cd "${CLDR_DIR}" && git describe HEAD || echo unknown) +# GIT_SHA=$(cd "${CLDR_DIR}" && git rev-parse HEAD || echo unknown) +# NOW=$(date -u -R) + + +# builder_echo heading "Ready to copy v${CLDR_VERSION} from ${CLDR_DIR}" +# builder_echo debug "${GIT_DESCRIBE} - ${GIT_SHA}" + +# mkdir -pv "${CLDR_VERSION}" + +# cd "${CLDR_VERSION}" + +# pwd + +# # delete the old files in case some were removed from CLDR +# rm -rf ./import ./3.0 ./dtd ./test +# # copy over everything +# cp -Rv "${IMPORT_DIR}" "${DATA_DIR}" "${DTD_DIR}" "${TEST_DIR}" "${ABNF_DIR}" . + +# # delete old files, no reason to keep them +# rm -vf dtd/{ldmlKeyboard,ldmlPlatform}.{xsd,dtd} + + +# echo "{\"sha\": \"${GIT_SHA}\",\"description\":\"${GIT_DESCRIBE}\",\"date\":\"${NOW}\"}" | ${JQ} . | tee cldr_info.json +# builder_echo "Updated cldr_info.json" + +# builder_echo heading "Converting XSD to JSON…" +# KEYMAN_CORE_LDML="../../../core/include/ldml" +for xsd in dtd/*.xsd; +do + base=$(basename "${xsd}" .xsd | tr A-Z a-z | sed -e 's%^ldml%ldml-%g' ) + json=${base}.schema.json + builder_echo debug "${xsd} -> ${json}" + # (cd .. ; npx -p jgexml xsd2json ${CLDR_VERSION}/"${xsd}" ${CLDR_VERSION}/"${json}") || exit + (cd .. ; npx -p jgexml xsd2json ${THIS_SCRIPT_PATH}/"${xsd}" ${THIS_SCRIPT_PATH}/"${json}") || exit + # builder_echo debug 'fixup-schema.js' "${json}" + # node ../fixup-schema.js "${json}" || builder_die "failed to fixup schema ${json}" + mv "${json}" tmp.json + ${JQ} . -S < tmp.json > "${json}" || (rm tmp.json ; builder_die "failed to transform final schema ${json}") + rm tmp.json +done + +# # verify that the CLDR version we just converted is the requested version. +# FOUND_VERSION=$(jq -r '.definitions.version.properties.cldrVersion.enum[0]' < ldml-keyboard3.schema.json) + +# if [ ${FOUND_VERSION} -ne ${CLDR_VERSION} ]; +# then +# # It's a little late to cleanup more gracefully, but we can at least complain. +# builder_die "You requested CLDR ${CLDR_VERSION} but the copied schema is for ${FOUND_VERSION} - something is wrong." +# fi + +echo +# builder_echo success "CLDR ${CLDR_VERSION} copied correctly from ${CLDR_DIR}" +builder_echo success "Keylayout copied correctly from ${DTD_DIR}" +echo diff --git a/resources/standards-data/keylayout/dtd/keylayout.xsd b/resources/standards-data/keylayout/dtd/keylayout.xsd new file mode 100644 index 00000000000..792d4f83074 --- /dev/null +++ b/resources/standards-data/keylayout/dtd/keylayout.xsd @@ -0,0 +1,146 @@ + + + + + + Data generated April 15 2025 + + Generated by S. Schmitt + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/resources/standards-data/keylayout/keylayout.schema.json b/resources/standards-data/keylayout/keylayout.schema.json new file mode 100644 index 00000000000..a33c754e558 --- /dev/null +++ b/resources/standards-data/keylayout/keylayout.schema.json @@ -0,0 +1,327 @@ +{ + "$schema": "http://json-schema.org/schema#", + "additionalProperties": false, + "properties": { + "keyboard": { + "additionalProperties": false, + "properties": { + "actions": { + "additionalProperties": false, + "properties": { + "action": { + "items": { + "additionalProperties": false, + "properties": { + "action": { + "items": { + "additionalProperties": false, + "properties": { + "id": { + "type": "string" + }, + "when": { + "items": { + "additionalProperties": false, + "properties": { + "#text": { + "type": "string" + }, + "next": { + "maximum": 127, + "minimum": -128, + "type": "integer" + }, + "output": { + "type": "string" + }, + "state": { + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + } + }, + "type": "object" + }, + "type": "array" + }, + "id": { + "type": "string" + }, + "when": { + "items": { + "additionalProperties": false, + "properties": { + "#text": { + "type": "string" + }, + "next": { + "maximum": 127, + "minimum": -128, + "type": "integer" + }, + "output": { + "type": "string" + }, + "state": { + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + } + }, + "type": "object" + }, + "type": "array" + } + }, + "type": "object" + }, + "group": { + "maximum": 127, + "minimum": -128, + "type": "integer" + }, + "id": { + "maximum": 32767, + "minimum": -32768, + "type": "integer" + }, + "keyMapSet": { + "additionalProperties": false, + "properties": { + "id": { + "type": "string" + }, + "keyMap": { + "items": { + "additionalProperties": false, + "properties": { + "index": { + "maximum": 127, + "minimum": -128, + "type": "integer" + }, + "key": { + "items": { + "additionalProperties": false, + "properties": { + "#text": { + "type": "string" + }, + "action": { + "type": "string" + }, + "code": { + "maximum": 127, + "minimum": -128, + "type": "integer" + }, + "output": { + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + } + }, + "type": "object" + }, + "type": "array" + } + }, + "type": "object" + }, + "layouts": { + "additionalProperties": false, + "properties": { + "layout": { + "additionalProperties": false, + "properties": { + "#text": { + "type": "string" + }, + "first": { + "maximum": 127, + "minimum": -128, + "type": "integer" + }, + "last": { + "maximum": 127, + "minimum": -128, + "type": "integer" + }, + "layout": { + "additionalProperties": false, + "properties": { + "#text": { + "type": "string" + }, + "first": { + "maximum": 127, + "minimum": -128, + "type": "integer" + }, + "last": { + "maximum": 127, + "minimum": -128, + "type": "integer" + }, + "mapSet": { + "maximum": 32767, + "minimum": -32768, + "type": "integer" + }, + "modifiers": { + "maximum": 127, + "minimum": -128, + "type": "integer" + } + }, + "type": "object" + }, + "mapSet": { + "maximum": 32767, + "minimum": -32768, + "type": "integer" + }, + "modifiers": { + "maximum": 127, + "minimum": -128, + "type": "integer" + } + }, + "required": [ + "layout" + ], + "type": "object" + } + }, + "required": [ + "layout" + ], + "type": "object" + }, + "maxout": { + "maximum": 127, + "minimum": -128, + "type": "integer" + }, + "modifierMap": { + "additionalProperties": false, + "properties": { + "defaultIndex": { + "maximum": 127, + "minimum": -128, + "type": "integer" + }, + "id": { + "maximum": 127, + "minimum": -128, + "type": "integer" + }, + "keyMapSelect": { + "items": { + "additionalProperties": false, + "properties": { + "mapIndex": { + "maximum": 127, + "minimum": -128, + "type": "integer" + }, + "modifier": { + "items": { + "additionalProperties": false, + "properties": { + "#text": { + "type": "string" + }, + "keys": { + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + } + }, + "type": "object" + }, + "type": "array" + } + }, + "type": "object" + }, + "name": { + "type": "string" + }, + "terminators": { + "additionalProperties": false, + "properties": { + "when": { + "items": { + "additionalProperties": false, + "properties": { + "#text": { + "type": "string" + }, + "output": { + "type": "string" + }, + "state": { + "maximum": 127, + "minimum": -128, + "type": "integer" + }, + "when": { + "items": { + "additionalProperties": false, + "properties": { + "#text": { + "type": "string" + }, + "output": { + "type": "string" + }, + "state": { + "maximum": 127, + "minimum": -128, + "type": "integer" + } + }, + "type": "object" + }, + "type": "array" + } + }, + "type": "object" + }, + "type": "array" + } + }, + "type": "object" + } + }, + "required": [ + "layouts", + "modifierMap", + "keyMapSet", + "actions", + "terminators" + ] + }, + "xs:annotation": { + "xs:documentation": "Data generated April 15 2025\r\n\r\n\tGenerated by S. Schmitt" + } + }, + "required": [ + "keyboard" + ], + "title": "C:/Projects/keyman/keyman/resources/standards-data/keylayout/dtd/keylayout.xsd", + "type": "object" +} diff --git a/resources/standards-data/keylayout/readme.md b/resources/standards-data/keylayout/readme.md new file mode 100644 index 00000000000..d1b79a78693 --- /dev/null +++ b/resources/standards-data/keylayout/readme.md @@ -0,0 +1,4 @@ +# keylayout + + +SAB: my text here From a9b8d544c712408073cc5a8733e1ce47463cce4c Mon Sep 17 00:00:00 2001 From: Sabine Date: Tue, 20 May 2025 12:40:50 +0200 Subject: [PATCH 102/251] feat(developer): push directly to 2D array; add Errors to ConverterMessages --- .../src/kmc-convert/src/converter-messages.ts | 16 +++ .../keylayout-to-kmn-converter.ts | 113 ++++++++---------- 2 files changed, 64 insertions(+), 65 deletions(-) diff --git a/developer/src/kmc-convert/src/converter-messages.ts b/developer/src/kmc-convert/src/converter-messages.ts index 7951edf1f81..afaf02a9fa8 100644 --- a/developer/src/kmc-convert/src/converter-messages.ts +++ b/developer/src/kmc-convert/src/converter-messages.ts @@ -30,4 +30,20 @@ export class ConverterMessages { static Error_FileNotFound = (o: { inputFilename: string; }) => m( this.ERROR_FileNotFound, `Input filename '${def(o.inputFilename)} ' does not exist or could not be loaded.`); + + static ERROR_UnableToRead = SevError | 0x0004; + static Error_UnableToRead = (o: { inputFilename: string; }) => m( + this.ERROR_UnableToRead, `Input file '${def(o.inputFilename)} + ' could not be read.`); + + static ERROR_UnableToConvert = SevError | 0x0005; + static Error_UnableToConvert = (o: { inputFilename: string; }) => m( + this.ERROR_UnableToConvert, `Input file '${def(o.inputFilename)} + ' could not be converted.`); + + static ERROR_UnableToWrite = SevError | 0x0006; + static Error_UnableToWrite = (o: { inputFilename: string; }) => m( + this.ERROR_UnableToWrite, `Output file for '${def(o.inputFilename)} + ' could not be written.`); + } diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 84e5c0e053c..507e64ccbfe 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -50,7 +50,7 @@ export class KeylayoutToKmnConverter { * @param outputFilename the resulting keyman .kmn-file * @return null on success */ - async run(inputFilename: string, outputFilename: string = ""): Promise { + async run(inputFilename: string, outputFilename?: string): Promise { if (!inputFilename) { this.callbacks.reportMessage(ConverterMessages.Error_FileNotFound({ inputFilename })); @@ -60,19 +60,21 @@ export class KeylayoutToKmnConverter { const KeylayoutReader = new KeylayoutFileReader(this.callbacks/*, this.options*/); const jsonO: object = KeylayoutReader.read(inputFilename); if (!jsonO) { - throw new Error('Error while processing read()'); + this.callbacks.reportMessage(ConverterMessages.Error_UnableToRead({ inputFilename })); + return null; } const outArray: convert_object = await this.convert(jsonO, outputFilename); if (!outArray) { - throw new Error('Error while processing convert()'); + this.callbacks.reportMessage(ConverterMessages.Error_UnableToConvert({ inputFilename })); + return null; } const kmnFileWriter = new KmnFileWriter(this.callbacks, this.options); const out_text_ok: boolean = kmnFileWriter.write(outArray); - if (!out_text_ok) { - throw new Error('Error while processing write()'); + this.callbacks.reportMessage(ConverterMessages.Error_UnableToWrite({ inputFilename })); + return null; } return null; } @@ -451,13 +453,12 @@ export class KeylayoutToKmnConverter { } if (isFirstUsedHere_dk) { - const ruleArray: string[] = []; object_array[i].unique_deadkey = unique_dkB_count; - ruleArray.push(object_array[i].modifier_deadkey); - ruleArray.push(object_array[i].deadkey); - ruleArray.push(String(unique_dkB_count)); + list_of_unique_Text2_rules.push([ + object_array[i].modifier_deadkey, + object_array[i].deadkey, + String(unique_dkB_count)]); unique_dkB_count++; - list_of_unique_Text2_rules.push(ruleArray); } } } @@ -493,13 +494,13 @@ export class KeylayoutToKmnConverter { } if (isFirstUsedHere_prev_dk) { - const ruleArray: string[] = []; object_array[i].unique_deadkey = unique_dkB_count; - ruleArray.push(object_array[i].modifier_prev_deadkey); - ruleArray.push(object_array[i].prev_deadkey); - ruleArray.push(String(unique_dkB_count)); + list_of_unique_Text2_rules.push([ + object_array[i].modifier_prev_deadkey, + object_array[i].prev_deadkey, + String(unique_dkB_count) + ]); unique_dkB_count++; - list_of_unique_Text2_rules.push(ruleArray); } } } @@ -801,17 +802,15 @@ export class KeylayoutToKmnConverter { for (let k = 0; k < search.length; k++) { for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { - const returnarray: string[] = []; if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search[k][0] && data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'] <= KeylayoutToKmnConverter.USED_KEYS_COUNT) { - returnarray.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']); - returnarray.push(this.map_UkeleleKC_To_VK(Number(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']))); - returnarray.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action']); - returnarray.push(data.keyboard.keyMapSet[0].keyMap[i]['@_index']); - returnarray.push(search[k][2]); - } - if (returnarray.length > 0) { - returnarray2D.push(returnarray); + returnarray2D.push([ + data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], + this.map_UkeleleKC_To_VK(Number(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), + data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'], + data.keyboard.keyMapSet[0].keyMap[i]['@_index'], + search[k][2] + ]); } } } @@ -830,14 +829,12 @@ export class KeylayoutToKmnConverter { for (let i = 0; i < data.keyboard.actions.action.length; i++) { for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { - const returnarray: string[] = []; if ((data.keyboard.actions.action[i].when[j]['@_state'] === search)) { - returnarray.push(data.keyboard.actions.action[i]['@_id']); - returnarray.push(data.keyboard.actions.action[i].when[j]['@_state']); - returnarray.push(data.keyboard.actions.action[i].when[j]['@_output']); - } - if (returnarray.length > 0) { - returnarray2D.push(returnarray); + returnarray2D.push([ + data.keyboard.actions.action[i]['@_id'], + data.keyboard.actions.action[i].when[j]['@_state'], + data.keyboard.actions.action[i].when[j]['@_output'] + ]); } } } @@ -857,23 +854,19 @@ export class KeylayoutToKmnConverter { if (!((search === undefined) || (search === null) || (search.length === 0))) { for (let i = 0; i < search.length; i++) { const behaviour: number = Number(search[i][3]); - for (let j = 0; j < data.keyboard.modifierMap.keyMapSelect[behaviour].modifier.length; j++) { - const returnarray1D: string[] = []; - // KeyName - returnarray1D.push(String(search[i][1])); - // actionId - returnarray1D.push(String(search[i][2])); - // behaviour - returnarray1D.push(String(search[i][3])); - // modifier - returnarray1D.push(String(this.create_kmn_modifier(data.keyboard.modifierMap.keyMapSelect[behaviour].modifier[j]['@_keys'], isCAPSused))); - // output - returnarray1D.push(String(search[i][4])); - - if (returnarray1D.length > 0) { - returnarray.push(returnarray1D); - } + returnarray.push([ + // KeyName + String(search[i][1]), + // actionId + String(search[i][2]), + // behaviour + String(search[i][3]), + // modifier + String(this.create_kmn_modifier(data.keyboard.modifierMap.keyMapSelect[behaviour].modifier[j]['@_keys'], isCAPSused)), + // output + String(search[i][4]) + ]); } } } @@ -912,21 +905,16 @@ export class KeylayoutToKmnConverter { for (let j = 0; j <= KeylayoutToKmnConverter.USED_KEYS_COUNT; j++) { if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { for (let k = 0; k < modi[data.keyboard.keyMapSet[0].keyMap[i]['@_index']].length; k++) { - const returnarray: string[] = []; const behaviour: string = data.keyboard.keyMapSet[0].keyMap[i]['@_index']; const modifierkmn: string = this.create_kmn_modifier(modi[behaviour][k], isCapsused); const keyName: string = this.map_UkeleleKC_To_VK(Number(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])); - - returnarray.push(search); - returnarray.push(outchar); - returnarray.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action']); - returnarray.push(behaviour); - returnarray.push(keyName); - returnarray.push(modifierkmn); - - if (returnarray.length > 0) { - returnarray2D.push(returnarray); - } + returnarray2D.push([ + search, + outchar, + data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'], + behaviour, + keyName, + modifierkmn]); } } } @@ -956,13 +944,8 @@ export class KeylayoutToKmnConverter { const mapIndexArray_2D: number[][] = []; for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { for (let j = 0; j <= KeylayoutToKmnConverter.USED_KEYS_COUNT; j++) { - const mapIndexArrayperKey: number[] = []; if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { - mapIndexArrayperKey.push(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']); - mapIndexArrayperKey.push(i); - } - if (mapIndexArrayperKey.length > 0) { - mapIndexArray_2D.push(mapIndexArrayperKey); + mapIndexArray_2D.push([data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], i]); } } } From 00158fdeeefc98e7d2b507729e91fab845415f6f Mon Sep 17 00:00:00 2001 From: Sabine Date: Wed, 21 May 2025 11:20:25 +0200 Subject: [PATCH 103/251] feat(developer): readme; add keylayout to schema-bundler.js; remove comments in create_keylayout_schema.sh --- common/web/types/tools/schema-bundler.js | 1 + .../src/kmc-convert/test/data/Test.keylayout | 2 +- .../keylayout/create_keylayout_schema.sh | 117 ++--------- .../keylayout/dtd/keylayout.xsd | 111 ++++------- .../keylayout/keylayout.schema.json | 182 +++++++++++------- resources/standards-data/keylayout/readme.md | 19 +- 6 files changed, 182 insertions(+), 250 deletions(-) diff --git a/common/web/types/tools/schema-bundler.js b/common/web/types/tools/schema-bundler.js index c8086e06509..99a51b11818 100644 --- a/common/web/types/tools/schema-bundler.js +++ b/common/web/types/tools/schema-bundler.js @@ -11,6 +11,7 @@ await esbuild.build({ 'obj/schemas/kvks.schema.validator.cjs', 'obj/schemas/ldml-keyboard3.schema.validator.cjs', 'obj/schemas/ldml-keyboardtest3.schema.validator.cjs', + 'obj/schemas/keylayout.schema.validator.cjs', 'obj/schemas/displaymap.schema.validator.cjs', 'obj/schemas/keyman-touch-layout.clean.spec.validator.cjs', 'obj/schemas/keyman-touch-layout.spec.validator.cjs', diff --git a/developer/src/kmc-convert/test/data/Test.keylayout b/developer/src/kmc-convert/test/data/Test.keylayout index a6b697b4d71..2c903b418bf 100644 --- a/developer/src/kmc-convert/test/data/Test.keylayout +++ b/developer/src/kmc-convert/test/data/Test.keylayout @@ -1,5 +1,5 @@ - + VK_US - if (pos === 0x0A) return "K_BKQUOTE"; /* ^ */ - else if (pos === 0x12) return "K_1"; /* 1 */ - else if (pos === 0x13) return "K_2"; /* 2 */ - else if (pos === 0x14) return "K_3"; /* 3 */ - else if (pos === 0x15) return "K_4"; /* 4 */ - else if (pos === 0x17) return "K_5"; /* 5 */ - else if (pos === 0x16) return "K_6"; /* 6 */ - else if (pos === 0x1A) return "K_7"; /* 7 */ - else if (pos === 0x1C) return "K_8"; /* 8 */ - else if (pos === 0x19) return "K_9"; /* 9 */ - else if (pos === 0x1D) return "K_0"; /* 0 */ - else if (pos === 0x1B) return "K_HYPHEN"; /* ß */ - else if (pos === 0x18) return "K_EQUAL"; /* ´ */ - - else if (pos === 0x0C) return "K_Q"; /* Q */ - else if (pos === 0x0D) return "K_W"; /* W */ - else if (pos === 0x0E) return "K_E"; /* E */ - else if (pos === 0x0F) return "K_R"; /* R */ - else if (pos === 0x11) return "K_T"; /* T */ - else if (pos === 0x10) return "K_Y"; /* Y */ - else if (pos === 0x20) return "K_U"; /* U */ - else if (pos === 0x22) return "K_I"; /* I */ - else if (pos === 0x1F) return "K_O"; /* O */ - else if (pos === 0x23) return "K_P"; /* P */ - else if (pos === 0x21) return "K_LBRKT"; /* [ */ - else if (pos === 0x1E) return "K_RBRKT"; /* ] */ - else if (pos === 0x31) return "K_SPACE"; /* \ */ - else if (pos === 0x2A) return "K_BKSLASH"; /* \ */ // 42 for ISO correct?? - // else if (pos === 0x30) return "K_?C1" /* \ */ // 48 for ANSI correct?? - - else if (pos === 0x00) return "K_A"; /* A */ - else if (pos === 0x01) return "K_S"; /* S */ - else if (pos === 0x02) return "K_D"; /* D */ - else if (pos === 0x03) return "K_F"; /* F */ - else if (pos === 0x05) return "K_G"; /* G */ - else if (pos === 0x04) return "K_H"; /* H */ - else if (pos === 0x26) return "K_J"; /* J */ - else if (pos === 0x28) return "K_K"; /* K */ - else if (pos === 0x25) return "K_L"; /* L */ - else if (pos === 0x29) return "K_COLON"; /* : */ - else if (pos === 0x27) return "K_QUOTE"; /* " */ - - else if (pos === 0x23) return "K_oE2"; /* | */ - else if (pos === 0x06) return "K_Z"; /* Z */ - else if (pos === 0x07) return "K_X"; /* X */ - else if (pos === 0x08) return "K_C"; /* C */ - else if (pos === 0x09) return "K_V"; /* V */ - else if (pos === 0x0B) return "K_B"; /* B */ - else if (pos === 0x2D) return "K_N"; /* N */ - else if (pos === 0x2E) return "K_M"; /* M */ - else if (pos === 0x2B) return "K_COMMA"; /* , */ - else if (pos === 0x2F) return "K_PERIOD"; /* . */ - else if (pos === 0x2C) return "K_SLASH"; /* / */ - - else if (pos === 0x24) return "K_ENTER"; + const vk = [ + "K_A" /* A */, + "K_S" /* S */, + "K_D" /* D */, + "K_F" /* F */, + "K_H" /* H */, + "K_G" /* G */, + "K_Z" /* Z */, + "K_X" /* X */, + "K_C" /* C */, + "K_V" /* V */, + "K_BKQUOTE" /* ^ */, + "K_B" /* B */, + "K_Q" /* Q */, + "K_W" /* W */, + "K_E" /* E */, + "K_R" /* R */, + "K_Y" /* Y */, + "K_T" /* T */, + "K_1" /* 1 */, + "K_2" /* 2 */, + "K_3" /* 3 */, + "K_4" /* 4 */, + "K_6" /* 6 */, + "K_5" /* 5 */, + "K_EQUAL" /* ´ */, + "K_9" /* 9 */, + "K_7" /* 7 */, + "K_HYPHEN" /* ß */, + "K_8" /* 8 */, + "K_0" /* 0 */, + "K_RBRKT" /* ] */, + "K_O" /* O */, + "K_U" /* U */, + "K_LBRKT" /* [ */, + "K_I" /* I */, + "K_P" /* P */, + "K_ENTER", + "K_L" /* L */, + "K_J" /* J */, + "K_QUOTE" /* " */, + "K_K" /* K */, + "K_COLON" /* : */, + "K_BKSLASH" /* \ */, // 42 for ISO correct?? + "K_COMMA" /* , */, + "K_SLASH" /* / */, + "K_N" /* N */, + "K_M" /* M */, + "K_PERIOD" /* . */, + "K_?C1" /* \ */, // 48 for ANSI correct?? + "K_SPACE" /* \ */ + ]; + + if ((pos >= 0 && pos <= 0x31)) + return vk[pos]; else return ""; - } - /** - * @brief member function to return an index for a given actionID - * @param data :any - an object containing all data read from a .keylayout file - * @param search :string - value 'id' to be found - * @return a number specifying the index of an actionId - */ + + /*if (!(pos >= 0 && pos <= 0x31) || (pos === null) || (pos === undefined)) + return ""; + else return vk[pos];*/ + + } + /* @brief member function to return an index for a given actionID + * @param data :any - an object containing all data read from a .keylayout file + * @param search :string - value 'id' to be found + * @return a number specifying the index of an actionId + */ public get_ActionIndex__From__ActionId(data: any, search: string): number { for (let i = 0; i < data.keyboard.actions.action.length; i++) { if (data.keyboard.actions.action[i]['@_id'] === search) { diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index a476d650b3a..daec2fbbb6d 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -20,7 +20,7 @@ describe('KeylayoutToKmnConverter', function () { before(function () { compilerTestCallbacks.clear(); }); - // todo remove + // todo remove describe('RunOneFile', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const inputFilename = makePathToFixture('../data/Italian.keylayout'); @@ -41,9 +41,9 @@ describe('KeylayoutToKmnConverter', function () { [makePathToFixture('../data/Polish.keylayout')], [makePathToFixture('../data/French.keylayout')], [makePathToFixture('../data/Latin_American.keylayout')], - /* [makePathToFixture('../data/German_complete.keylayout')], - [makePathToFixture('../data/German_complete_reduced.keylayout')], - [makePathToFixture('../data/German_Standard.keylayout')],*/ + [makePathToFixture('../data/German_complete.keylayout')], + /* [makePathToFixture('../data/German_complete_reduced.keylayout')], + [makePathToFixture('../data/German_Standard.keylayout')],*/ ].forEach(function (files_) { sut.run(files_[0]); assert.isTrue(true); @@ -246,7 +246,6 @@ describe('KeylayoutToKmnConverter', function () { describe('map_UkeleleKC_To_VK ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - [ [0x00, 'K_A'], [0x31, 'K_SPACE'], @@ -257,6 +256,8 @@ describe('KeylayoutToKmnConverter', function () { [0x999, ''], [-1, ''], [null, ''], + [undefined, ''], + [, ''], ].forEach(function (values) { it(("map_UkeleleKC_To_VK(" + values[0] + ")").padEnd(26, " ") + "should return " + "'" + values[1] + "'", async function () { const result = sut.map_UkeleleKC_To_VK(values[0] as number); diff --git a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts index 4b8bde1a458..fbacb6d3131 100644 --- a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts +++ b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts @@ -250,6 +250,7 @@ describe('KmnFileWriter', function () { ["a", 'a'], ["ሴ", 'ሴ'], ['😎', '😎'], + ["W̊", "W̊"], ["ab", undefined], ["", ''], [undefined, undefined], From f86bd1f23594fb53bfd64af95107366d24673021 Mon Sep 17 00:00:00 2001 From: Sabine Date: Wed, 25 Jun 2025 17:53:55 +0200 Subject: [PATCH 111/251] feat(developer): started with run returning artifacts --- .../keylayout-to-kmn-converter.ts | 80 +++++++++++++++++-- 1 file changed, 72 insertions(+), 8 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index c4041ad37e5..7f27983c721 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -106,6 +106,75 @@ export class KeylayoutToKmnConverter { return null; } + async run_new(inputFilename: string, outputFilename?: string): Promise { + + if (!inputFilename) { + this.callbacks.reportMessage(ConverterMessages.Error_FileNotFound({ inputFilename })); + return null; + } + + const KeylayoutReader = new KeylayoutFileReader(this.callbacks/*, this.options*/); + const jsonO: object = KeylayoutReader.read(inputFilename); + if (!jsonO) { + this.callbacks.reportMessage(ConverterMessages.Error_UnableToRead({ inputFilename })); + return null; + } + + const outArray: convert_object = await this.convert(jsonO, outputFilename); + if (!outArray) { + this.callbacks.reportMessage(ConverterMessages.Error_UnableToConvert({ inputFilename })); + return null; + } + + const kmnFileWriter = new KmnFileWriter(this.callbacks, this.options); + + const out_text_ok: boolean = kmnFileWriter.write(outArray); + if (!out_text_ok) { + this.callbacks.reportMessage(ConverterMessages.Error_UnableToWrite({ inputFilename })); + return null; + } + + + // xxx write my data + const out_Uint8: Uint8Array = kmnFileWriter.writeToUint8Array(outArray); + if (!out_Uint8) { + this.callbacks.reportMessage(ConverterMessages.Error_UnableToWrite({ inputFilename })); + return null; + } + // xxx get my name + outputFilename = outputFilename ?? inputFilename.replace(/\.keylayout$/, '.kmn'); + // xxx return filled artifact + /* return { + artifacts: { + kmx: { data: out_Uint8, filename: outputFilename }, + } + }; + */ + + /*const out_str: string = kmnFileWriter.writeToString(outArray); + if (!out_str) { + this.callbacks.reportMessage(ConverterMessages.Error_UnableToWrite({ inputFilename })); + return null; + }*/ + + + /* + const a: ConverterToKmnArtifacts = null; + const ddd= a.data + return a ? a : null; + + data of convert_object needs to be in ConverterToKmnArtifacts: + (ConverterToKmnArtifacts= outArray ???) + return ConverterToKmnArtifacts ? { ConverterToKmnArtifacts } : null; + --- + const converter = new ConverterClass(this.callbacks, converterOptions); + const artifacts = await converter.run(inputFilename, outputFilename); + return artifacts ? { artifacts } : null; + */ + + return null; + } + /** * @brief member function to read filename and behaviour of a json object into a convert_object * @param jsonObj containing filename, behaviour and rules of a json object @@ -749,16 +818,11 @@ export class KeylayoutToKmnConverter { "K_SPACE" /* \ */ ]; - if ((pos >= 0 && pos <= 0x31)) - return vk[pos]; - else return ""; - - - /*if (!(pos >= 0 && pos <= 0x31) || (pos === null) || (pos === undefined)) + if (!(pos >= 0 && pos <= 0x31) || (pos === null) || (pos === undefined)) return ""; - else return vk[pos];*/ - + else return vk[pos]; } + /* @brief member function to return an index for a given actionID * @param data :any - an object containing all data read from a .keylayout file * @param search :string - value 'id' to be found From 96025af32e732fd604adfc06001787a18c47b8aa Mon Sep 17 00:00:00 2001 From: Sabine Date: Thu, 26 Jun 2025 11:45:59 +0200 Subject: [PATCH 112/251] feat(developer): write output to in-memory artifact finished --- developer/src/kmc-convert/src/converter.ts | 5 +- .../keylayout-to-kmn-converter.ts | 113 ++++-------------- 2 files changed, 24 insertions(+), 94 deletions(-) diff --git a/developer/src/kmc-convert/src/converter.ts b/developer/src/kmc-convert/src/converter.ts index 0d886aab8fe..f36530fcf8c 100644 --- a/developer/src/kmc-convert/src/converter.ts +++ b/developer/src/kmc-convert/src/converter.ts @@ -65,7 +65,7 @@ export class Converter implements KeymanCompiler { // _S2 finds converter e.g.keylayout->kmn ( uses converter-class-factory) // _S2 factory uses/instanciates child class ( ~ in C++ virtual function in base class <-> use fun of derived class) // _S2 loads file - // _S2 creates a new converter (-object) + // _S2 creates a new (derived) converter (-object) // _S2 runs conversion for this object ( run-method of this converter of keylayout-to-kmn-tonverter.ts ) async run(inputFilename: string, outputFilename?: string): Promise { const converterOptions: CompilerOptions = { @@ -93,7 +93,8 @@ export class Converter implements KeymanCompiler { const converter = new ConverterClass(this.callbacks, converterOptions); const artifacts = await converter.run(inputFilename, outputFilename); // Note: any subsequent errors in conversion will have been reported by the converter - return artifacts ? { artifacts } : null; + //return artifacts ? { artifacts } : null; + return artifacts ? artifacts : null; } /** diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 7f27983c721..a9cb3af913e 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -7,12 +7,20 @@ * */ -import { CompilerCallbacks, CompilerOptions } from "@keymanapp/developer-utils"; +import { CompilerCallbacks, CompilerOptions, KeymanCompilerResult, } from "@keymanapp/developer-utils"; import { ConverterToKmnArtifacts } from "../converter-artifacts.js"; import { KmnFileWriter } from './kmn-file-writer.js'; import { KeylayoutFileReader } from './keylayout-file-reader.js'; import { ConverterMessages } from '../converter-messages.js'; +import { ConverterArtifacts } from "../converter-artifacts.js"; +export interface ConverterResult extends KeymanCompilerResult { + /** + * Internal in-memory build artifacts from a successful compilation. Caller + * can write these to disk with {@link Converter.write} + */ + artifacts: ConverterArtifacts; +}; export interface convert_object { keylayout_filename: string, @@ -49,7 +57,7 @@ export class KeylayoutToKmnConverter { * @param outputFilename the resulting keyman .kmn-file * @return null on success */ - async run(inputFilename: string, outputFilename?: string): Promise { + async run(inputFilename: string, outputFilename?: string): Promise { if (!inputFilename) { this.callbacks.reportMessage(ConverterMessages.Error_FileNotFound({ inputFilename })); @@ -71,108 +79,29 @@ export class KeylayoutToKmnConverter { const kmnFileWriter = new KmnFileWriter(this.callbacks, this.options); + // _S2 still write to file - may be removed later const out_text_ok: boolean = kmnFileWriter.write(outArray); if (!out_text_ok) { this.callbacks.reportMessage(ConverterMessages.Error_UnableToWrite({ inputFilename })); return null; } - /*const out_Uint8: Uint8Array = kmnFileWriter.writeToUint8Array(outArray); - if (!out_Uint8) { - this.callbacks.reportMessage(ConverterMessages.Error_UnableToWrite({ inputFilename })); - return null; - }*/ - - /*const out_str: string = kmnFileWriter.writeToString(outArray); - if (!out_str) { - this.callbacks.reportMessage(ConverterMessages.Error_UnableToWrite({ inputFilename })); - return null; - }*/ - - - /* - const a: ConverterToKmnArtifacts = null; - const ddd= a.data - return a ? a : null; - - data of convert_object needs to be in ConverterToKmnArtifacts: - (ConverterToKmnArtifacts= outArray ???) - return ConverterToKmnArtifacts ? { ConverterToKmnArtifacts } : null; - --- - const converter = new ConverterClass(this.callbacks, converterOptions); - const artifacts = await converter.run(inputFilename, outputFilename); - return artifacts ? { artifacts } : null;*/ - - return null; - } - - async run_new(inputFilename: string, outputFilename?: string): Promise { - - if (!inputFilename) { - this.callbacks.reportMessage(ConverterMessages.Error_FileNotFound({ inputFilename })); - return null; - } - - const KeylayoutReader = new KeylayoutFileReader(this.callbacks/*, this.options*/); - const jsonO: object = KeylayoutReader.read(inputFilename); - if (!jsonO) { - this.callbacks.reportMessage(ConverterMessages.Error_UnableToRead({ inputFilename })); - return null; - } - - const outArray: convert_object = await this.convert(jsonO, outputFilename); - if (!outArray) { - this.callbacks.reportMessage(ConverterMessages.Error_UnableToConvert({ inputFilename })); - return null; - } - - const kmnFileWriter = new KmnFileWriter(this.callbacks, this.options); - - const out_text_ok: boolean = kmnFileWriter.write(outArray); - if (!out_text_ok) { - this.callbacks.reportMessage(ConverterMessages.Error_UnableToWrite({ inputFilename })); - return null; - } - - - // xxx write my data - const out_Uint8: Uint8Array = kmnFileWriter.writeToUint8Array(outArray); - if (!out_Uint8) { - this.callbacks.reportMessage(ConverterMessages.Error_UnableToWrite({ inputFilename })); - return null; - } - // xxx get my name + // write to object/ConverterResult outputFilename = outputFilename ?? inputFilename.replace(/\.keylayout$/, '.kmn'); - // xxx return filled artifact - /* return { + const out_Uint8: Uint8Array = kmnFileWriter.writeToUint8Array(outArray); + const Result_toBeReturned = { artifacts: { - kmx: { data: out_Uint8, filename: outputFilename }, + kmn: { data: out_Uint8, filename: outputFilename }, } }; - */ - /*const out_str: string = kmnFileWriter.writeToString(outArray); - if (!out_str) { - this.callbacks.reportMessage(ConverterMessages.Error_UnableToWrite({ inputFilename })); - return null; - }*/ - - - /* - const a: ConverterToKmnArtifacts = null; - const ddd= a.data - return a ? a : null; - - data of convert_object needs to be in ConverterToKmnArtifacts: - (ConverterToKmnArtifacts= outArray ???) - return ConverterToKmnArtifacts ? { ConverterToKmnArtifacts } : null; - --- - const converter = new ConverterClass(this.callbacks, converterOptions); - const artifacts = await converter.run(inputFilename, outputFilename); - return artifacts ? { artifacts } : null; - */ + // _S2 does this still work? + if (!out_Uint8) { + this.callbacks.reportMessage(ConverterMessages.Error_UnableToWrite({ inputFilename })); + return null; + } - return null; + return Result_toBeReturned; } /** From 04a08a984c03402e578f64acbc5737537284b7a3 Mon Sep 17 00:00:00 2001 From: Sabine Date: Thu, 26 Jun 2025 11:47:50 +0200 Subject: [PATCH 113/251] feat(developer): type added for definition of result --- .../src/keylayout-to-kmn/keylayout-to-kmn-converter.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index a9cb3af913e..9029f466c8d 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -89,9 +89,9 @@ export class KeylayoutToKmnConverter { // write to object/ConverterResult outputFilename = outputFilename ?? inputFilename.replace(/\.keylayout$/, '.kmn'); const out_Uint8: Uint8Array = kmnFileWriter.writeToUint8Array(outArray); - const Result_toBeReturned = { + const Result_toBeReturned: ConverterResult = { artifacts: { - kmn: { data: out_Uint8, filename: outputFilename }, + kmn: { data: out_Uint8, filename: outputFilename } } }; From e0a7d70d3a0e78d37ed39d733ac4d3baa72063d5 Mon Sep 17 00:00:00 2001 From: Sabine Date: Thu, 26 Jun 2025 14:26:39 +0200 Subject: [PATCH 114/251] feat(developer): typos --- .../src/keylayout-to-kmn/keylayout-to-kmn-converter.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 9029f466c8d..13879807f2b 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -100,7 +100,6 @@ export class KeylayoutToKmnConverter { this.callbacks.reportMessage(ConverterMessages.Error_UnableToWrite({ inputFilename })); return null; } - return Result_toBeReturned; } From c6da5468d0620c69bc60b7f213c06adc8dad5ca7 Mon Sep 17 00:00:00 2001 From: Sabine Date: Thu, 26 Jun 2025 14:26:39 +0200 Subject: [PATCH 115/251] feat(developer): remove import --- .../src/keylayout-to-kmn/keylayout-to-kmn-converter.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 9029f466c8d..ad68b81e3e4 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -8,7 +8,7 @@ */ import { CompilerCallbacks, CompilerOptions, KeymanCompilerResult, } from "@keymanapp/developer-utils"; -import { ConverterToKmnArtifacts } from "../converter-artifacts.js"; +//import { ConverterToKmnArtifacts } from "../converter-artifacts.js"; import { KmnFileWriter } from './kmn-file-writer.js'; import { KeylayoutFileReader } from './keylayout-file-reader.js'; import { ConverterMessages } from '../converter-messages.js'; @@ -100,7 +100,6 @@ export class KeylayoutToKmnConverter { this.callbacks.reportMessage(ConverterMessages.Error_UnableToWrite({ inputFilename })); return null; } - return Result_toBeReturned; } From 615ebe6c0b7c69a1ab81e44844d8488022056424 Mon Sep 17 00:00:00 2001 From: Sabine Date: Thu, 26 Jun 2025 15:10:28 +0200 Subject: [PATCH 116/251] feat(developer):kmc-convert write ConverterToKmnResult instead of ConverterResult --- .../keylayout-to-kmn-converter.ts | 16 ++++++--- .../test/keylayout-to-kmn-converter.tests.ts | 36 ------------------- 2 files changed, 12 insertions(+), 40 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index ad68b81e3e4..e457ef150de 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -8,11 +8,11 @@ */ import { CompilerCallbacks, CompilerOptions, KeymanCompilerResult, } from "@keymanapp/developer-utils"; -//import { ConverterToKmnArtifacts } from "../converter-artifacts.js"; import { KmnFileWriter } from './kmn-file-writer.js'; import { KeylayoutFileReader } from './keylayout-file-reader.js'; import { ConverterMessages } from '../converter-messages.js'; import { ConverterArtifacts } from "../converter-artifacts.js"; +import { ConverterToKmnArtifacts } from "../converter-artifacts.js"; export interface ConverterResult extends KeymanCompilerResult { /** @@ -22,6 +22,14 @@ export interface ConverterResult extends KeymanCompilerResult { artifacts: ConverterArtifacts; }; +export interface ConverterToKmnResult extends ConverterResult { + /** + * Internal in-memory build artifacts from a successful compilation. Caller + * can write these to disk with {@link Converter.write} + */ + artifacts: ConverterToKmnArtifacts; +}; + export interface convert_object { keylayout_filename: string, kmn_filename: string, @@ -57,7 +65,7 @@ export class KeylayoutToKmnConverter { * @param outputFilename the resulting keyman .kmn-file * @return null on success */ - async run(inputFilename: string, outputFilename?: string): Promise { + async run(inputFilename: string, outputFilename?: string): Promise { if (!inputFilename) { this.callbacks.reportMessage(ConverterMessages.Error_FileNotFound({ inputFilename })); @@ -86,10 +94,10 @@ export class KeylayoutToKmnConverter { return null; } - // write to object/ConverterResult + // write to object/ConverterToKmnResult outputFilename = outputFilename ?? inputFilename.replace(/\.keylayout$/, '.kmn'); const out_Uint8: Uint8Array = kmnFileWriter.writeToUint8Array(outArray); - const Result_toBeReturned: ConverterResult = { + const Result_toBeReturned: ConverterToKmnResult = { artifacts: { kmn: { data: out_Uint8, filename: outputFilename } } diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index daec2fbbb6d..230d9cea4f3 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -20,42 +20,6 @@ describe('KeylayoutToKmnConverter', function () { before(function () { compilerTestCallbacks.clear(); }); - // todo remove - describe('RunOneFile', function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const inputFilename = makePathToFixture('../data/Italian.keylayout'); - sut.run(inputFilename); - assert.isTrue(true); - }); - - // todo remove - describe('RunAllFiles', function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - [ - [makePathToFixture('../data/Italian.keylayout')], - [makePathToFixture('../data/Italian_command.keylayout')], - [makePathToFixture('../data/Swiss_French.keylayout')], - [makePathToFixture('../data/Spanish.keylayout')], - [makePathToFixture('../data/Swiss_German.keylayout')], - [makePathToFixture('../data/US.keylayout')], - [makePathToFixture('../data/Polish.keylayout')], - [makePathToFixture('../data/French.keylayout')], - [makePathToFixture('../data/Latin_American.keylayout')], - [makePathToFixture('../data/German_complete.keylayout')], - /* [makePathToFixture('../data/German_complete_reduced.keylayout')], - [makePathToFixture('../data/German_Standard.keylayout')],*/ - ].forEach(function (files_) { - sut.run(files_[0]); - assert.isTrue(true); - }); - }); - // todo remove - describe('RunOneFile', function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const inputFilename = makePathToFixture('../data/Test.keylayout'); - sut.run(inputFilename); - assert.isTrue(true); - }); describe('run() ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); From 5984b15d517b841a54326c97ae34416e8c128961 Mon Sep 17 00:00:00 2001 From: Sabine Date: Fri, 27 Jun 2025 10:21:49 +0200 Subject: [PATCH 117/251] feat(developer): input filenae - remove process.cwd(), create outputFilename from inputFilename --- .../src/kmc-convert/src/converter-messages.ts | 4 +- .../keylayout-to-kmn/keylayout-file-reader.ts | 1 - .../keylayout-to-kmn-converter.ts | 107 +++--------------- .../test/keylayout-to-kmn-converter.tests.ts | 56 +++++---- .../kmc-convert/test/kmn-file-reader.tests.ts | 7 +- .../kmc-convert/test/kmn-file-writer.tests.ts | 44 +++---- 6 files changed, 69 insertions(+), 150 deletions(-) diff --git a/developer/src/kmc-convert/src/converter-messages.ts b/developer/src/kmc-convert/src/converter-messages.ts index 937a7dd339c..8e2e60aee1e 100644 --- a/developer/src/kmc-convert/src/converter-messages.ts +++ b/developer/src/kmc-convert/src/converter-messages.ts @@ -42,8 +42,8 @@ export class ConverterMessages { ' could not be converted.`); static ERROR_UnableToWrite = SevError | 0x0006; - static Error_UnableToWrite = (o: { inputFilename: string; }) => m( - this.ERROR_UnableToWrite, `Output file for '${def(o.inputFilename)} + static Error_UnableToWrite = (o: { outputFilename: string; }) => m( + this.ERROR_UnableToWrite, `Output file for '${def(o.outputFilename)} ' could not be written.`); static ERROR_UnsupportedCharactersDetected = SevError | 0x0007; diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts index 99b871243a0..8df50c09378 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts @@ -54,7 +54,6 @@ export class KeylayoutFileReader { }; try { - //const xmlFile = this.callbacks.fs.readFileSync(this.callbacks.path.join(process.cwd(), KeylayoutToKmnConverter.TEST_SUBFOLDER, KeylayoutToKmnConverter.DATA_SUBFOLDER, this.callbacks.path.basename(inputFilename)), 'utf8'); const xmlFile = this.callbacks.fs.readFileSync(inputFilename, 'utf8'); const parser = new XMLParser(options); const jsonObj = parser.parse(xmlFile); // get plain Object diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 7f27983c721..12ae110f25f 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -23,16 +23,12 @@ export interface convert_object { export class KeylayoutToKmnConverter { - static readonly INPUT_FILE_EXTENSION = '.keylayout'; static readonly OUTPUT_FILE_EXTENSION = '.kmn'; static readonly USED_KEYS_COUNT = 49; // we use key Nr 0 (A) -> key Nr 49 (Space) static readonly MAX_CTRL_CHARACTER = 32; static readonly SKIP_COMMENTED_LINES = false; - static readonly DATA_SUBFOLDER = 'data'; - static readonly TEST_SUBFOLDER = 'test'; - private options: CompilerOptions; async init(callbacks: CompilerCallbacks, options: CompilerOptions): Promise { @@ -51,6 +47,7 @@ export class KeylayoutToKmnConverter { */ async run(inputFilename: string, outputFilename?: string): Promise { + if (!inputFilename) { this.callbacks.reportMessage(ConverterMessages.Error_FileNotFound({ inputFilename })); return null; @@ -63,6 +60,8 @@ export class KeylayoutToKmnConverter { return null; } + outputFilename = outputFilename ?? inputFilename.replace(/\.keylayout$/, '.kmn'); + const outArray: convert_object = await this.convert(jsonO, outputFilename); if (!outArray) { this.callbacks.reportMessage(ConverterMessages.Error_UnableToConvert({ inputFilename })); @@ -73,7 +72,7 @@ export class KeylayoutToKmnConverter { const out_text_ok: boolean = kmnFileWriter.write(outArray); if (!out_text_ok) { - this.callbacks.reportMessage(ConverterMessages.Error_UnableToWrite({ inputFilename })); + this.callbacks.reportMessage(ConverterMessages.Error_UnableToWrite({ outputFilename })); return null; } @@ -106,82 +105,13 @@ export class KeylayoutToKmnConverter { return null; } - async run_new(inputFilename: string, outputFilename?: string): Promise { - - if (!inputFilename) { - this.callbacks.reportMessage(ConverterMessages.Error_FileNotFound({ inputFilename })); - return null; - } - - const KeylayoutReader = new KeylayoutFileReader(this.callbacks/*, this.options*/); - const jsonO: object = KeylayoutReader.read(inputFilename); - if (!jsonO) { - this.callbacks.reportMessage(ConverterMessages.Error_UnableToRead({ inputFilename })); - return null; - } - - const outArray: convert_object = await this.convert(jsonO, outputFilename); - if (!outArray) { - this.callbacks.reportMessage(ConverterMessages.Error_UnableToConvert({ inputFilename })); - return null; - } - - const kmnFileWriter = new KmnFileWriter(this.callbacks, this.options); - - const out_text_ok: boolean = kmnFileWriter.write(outArray); - if (!out_text_ok) { - this.callbacks.reportMessage(ConverterMessages.Error_UnableToWrite({ inputFilename })); - return null; - } - - - // xxx write my data - const out_Uint8: Uint8Array = kmnFileWriter.writeToUint8Array(outArray); - if (!out_Uint8) { - this.callbacks.reportMessage(ConverterMessages.Error_UnableToWrite({ inputFilename })); - return null; - } - // xxx get my name - outputFilename = outputFilename ?? inputFilename.replace(/\.keylayout$/, '.kmn'); - // xxx return filled artifact - /* return { - artifacts: { - kmx: { data: out_Uint8, filename: outputFilename }, - } - }; - */ - - /*const out_str: string = kmnFileWriter.writeToString(outArray); - if (!out_str) { - this.callbacks.reportMessage(ConverterMessages.Error_UnableToWrite({ inputFilename })); - return null; - }*/ - - - /* - const a: ConverterToKmnArtifacts = null; - const ddd= a.data - return a ? a : null; - - data of convert_object needs to be in ConverterToKmnArtifacts: - (ConverterToKmnArtifacts= outArray ???) - return ConverterToKmnArtifacts ? { ConverterToKmnArtifacts } : null; - --- - const converter = new ConverterClass(this.callbacks, converterOptions); - const artifacts = await converter.run(inputFilename, outputFilename); - return artifacts ? { artifacts } : null; - */ - - return null; - } /** * @brief member function to read filename and behaviour of a json object into a convert_object * @param jsonObj containing filename, behaviour and rules of a json object * @return an convert_object containing all data ready to print out */ - private convert(jsonObj: any, outputfilename: string = ""): convert_object { - + private convert(jsonObj: any, outputfilename: string): convert_object { const modifierBehavior: string[][] = []; // modifier for each behaviour const rules: Rule[] = []; // an array of data for a kmn rule @@ -195,25 +125,14 @@ export class KeylayoutToKmnConverter { // ToDo in a new PR: check tags ( issue # 13599) if ((jsonObj !== null) && (jsonObj.hasOwnProperty("keyboard"))) { - // get filename from data that had been read - const fileNameNoExtention = jsonObj.keyboard['@_name']; - const filePath = this.callbacks.path.join(process.cwd(), KeylayoutToKmnConverter.TEST_SUBFOLDER, KeylayoutToKmnConverter.DATA_SUBFOLDER); - - data_object.keylayout_filename = this.callbacks.path.join(filePath, (fileNameNoExtention + ".keylayout")); - - // if no outputfile name is specified: create one from input file name - if ((outputfilename === "") || (outputfilename === null)) { - data_object.kmn_filename = this.callbacks.path.join(filePath, fileNameNoExtention + ".kmn"); - } - // if outputfile name is specified: use it - else - data_object.kmn_filename = outputfilename; - - console.log("RUN kmc convert - input file: ", data_object.keylayout_filename, " --> output file: ", data_object.kmn_filename); - + data_object.keylayout_filename = outputfilename.replace(/\.kmn$/, '.keylayout'); + data_object.kmn_filename = outputfilename; data_object.arrayOf_Modifiers = modifierBehavior; // ukelele uses behaviours e.g. 18 modifiersCombinations in 8 KeyMapSelect(behaviors) data_object.arrayOf_Rules = rules; + // _S2 ToDo remove this console.log + console.log("RUN kmc convert - input file: ",data_object.keylayout_filename, " --> output file: ", data_object.kmn_filename); + // create an array of modifier combinations and store in data_object for (let j = 0; j < jsonObj.keyboard.modifierMap.keyMapSelect.length; j++) { const singleModifierSet: string[] = []; @@ -818,9 +737,11 @@ export class KeylayoutToKmnConverter { "K_SPACE" /* \ */ ]; - if (!(pos >= 0 && pos <= 0x31) || (pos === null) || (pos === undefined)) + if (!(pos >= 0 && pos <= 0x31) || (pos === null) || (pos === undefined)) { return ""; - else return vk[pos]; + } else { + return vk[pos]; + } } /* @brief member function to return an index for a given actionID diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index daec2fbbb6d..421ec6e640e 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -41,7 +41,7 @@ describe('KeylayoutToKmnConverter', function () { [makePathToFixture('../data/Polish.keylayout')], [makePathToFixture('../data/French.keylayout')], [makePathToFixture('../data/Latin_American.keylayout')], - [makePathToFixture('../data/German_complete.keylayout')], + [makePathToFixture('../data/German_Complete.keylayout')], /* [makePathToFixture('../data/German_complete_reduced.keylayout')], [makePathToFixture('../data/German_Standard.keylayout')],*/ ].forEach(function (files_) { @@ -84,7 +84,7 @@ describe('KeylayoutToKmnConverter', function () { }); it('run() should throw on unavailable input file name and null output file name', async function () { - const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Unavailable.keylayout'); + const inputFilename = makePathToFixture('../data/Unavailable.keylayout'); const result = sut.run(inputFilename, null); assert.isNotNull(result); assert.equal(compilerTestCallbacks.messages.length, 2); @@ -93,24 +93,24 @@ describe('KeylayoutToKmnConverter', function () { }); it('run() should return on correct input file name and empty output file name ', async function () { - const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); await NodeAssert.doesNotReject(async () => sut.run(inputFilename, '')); }); it('run() should return on correct input file name and null output file name', async function () { - const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); await NodeAssert.doesNotReject(async () => sut.run(inputFilename, null)); }); it('run() should return on correct input file name and given output file name ', async function () { - const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Test.keylayout'); - const outputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/OutputName.kmn'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); + const outputFilename = makePathToFixture('../data/OutputName.kmn'); await NodeAssert.doesNotReject(async () => sut.run(inputFilename, outputFilename)); }); it('run() should throw on incorrect input file extention and output file extention', async function () { - const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Test_command.A'); - const outputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/data/OutputXName.B'); + const inputFilename = makePathToFixture('../data/Test_command.A'); + const outputFilename = makePathToFixture('../data/data/OutputXName.B'); const result = sut.run(inputFilename, outputFilename); assert.isNotNull(result); assert.equal(compilerTestCallbacks.messages.length, 2); @@ -119,8 +119,8 @@ describe('KeylayoutToKmnConverter', function () { }); it('run() return on correct input file extention and unsupperted output file extention', async function () { - const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Test.keylayout'); - const outputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/OutputXName.B'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); + const outputFilename = makePathToFixture('../data/OutputXName.B'); await NodeAssert.doesNotReject(async () => sut.run(inputFilename, outputFilename)); }); }); @@ -128,19 +128,19 @@ describe('KeylayoutToKmnConverter', function () { describe('convert() ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const read = sut_r.read(inputFilename); - const converted = sut.convert_bound.convert(read); + const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); // empty convert_object from unavailable file name const inputFilename_unavailable = makePathToFixture('X.keylayout'); const read_unavailable = sut_r.read(inputFilename_unavailable); - const converted_unavailable = sut.convert_bound.convert(read_unavailable); + const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); // empty convert_object from empty filename const inputFilename_empty = makePathToFixture(''); const read_empty = sut_r.read(inputFilename_empty); - const converted_empty = sut.convert_bound.convert(read_empty); + const converted_empty = sut.convert_bound.convert(read_empty, inputFilename_empty.replace(/\.keylayout$/, '.kmn')); it('should return converted array on correct input', async function () { assert.isTrue(converted.arrayOf_Rules.length !== 0); @@ -163,7 +163,7 @@ describe('KeylayoutToKmnConverter', function () { keylayout_filename: '', arrayOf_Modifiers: [['caps'], ['Shift'], ['command']], arrayOf_Rules: [] - }); + }, ''); assert.isTrue((converted_mod.keylayout_filename === '' && converted_mod.arrayOf_Modifiers.length === 0 && converted_mod.arrayOf_Rules.length === 0)); @@ -174,7 +174,7 @@ describe('KeylayoutToKmnConverter', function () { keylayout_filename: '', arrayOf_Modifiers: [], arrayOf_Rules: [['C0', '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_A', 'A']] - }); + }, ''); assert.isTrue((converted_rule.keylayout_filename === '' && converted_rule.arrayOf_Modifiers.length === 0 && converted_rule.arrayOf_Rules.length === 0)); @@ -289,9 +289,9 @@ describe('KeylayoutToKmnConverter', function () { describe('get_Modifier_array__From__KeyModifier_array ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const read = sut_r.read(inputFilename); - const converted = sut.convert_bound.convert(read); + const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); [ [[['0', 0]], [['', 'shift? caps? ']]], @@ -302,8 +302,6 @@ describe('KeylayoutToKmnConverter', function () { [[['0', -999]], [null]], [[['0']], [null]], - - ].forEach(function (values) { it((values[1][0] !== null) ? ("get_Modifier_array__From__KeyModifier_array(['" + values[0][0][0] + "', '" + values[0][0][1] + "'])").padEnd(68, " ") + " should return ['" + values[1][0][0] + "', '" + values[1][0][1] + "']" : @@ -327,7 +325,7 @@ describe('KeylayoutToKmnConverter', function () { describe('get_KeyModifier_array__From__ActionID ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const read = sut_r.read(inputFilename); [ @@ -360,7 +358,7 @@ describe('KeylayoutToKmnConverter', function () { describe('get_ActionID__From__ActionNext ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const read = sut_r.read(inputFilename); [ @@ -393,7 +391,7 @@ describe('KeylayoutToKmnConverter', function () { describe('get_ActionIndex__From__ActionId ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const read = sut_r.read(inputFilename); [ @@ -421,7 +419,7 @@ describe('KeylayoutToKmnConverter', function () { describe('get_Output__From__ActionId_None ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const read = sut_r.read(inputFilename); [ @@ -454,7 +452,7 @@ describe('KeylayoutToKmnConverter', function () { describe('get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const read = sut_r.read(inputFilename); /*Italian: @@ -640,7 +638,7 @@ describe('KeylayoutToKmnConverter', function () { describe('get_ActionStateOutput_array__From__ActionState ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const read = sut_r.read(inputFilename); /* @@ -712,9 +710,9 @@ describe('KeylayoutToKmnConverter', function () { describe('get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const read = sut_r.read(inputFilename); - const converted = sut.convert_bound.convert(read); + const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); /* Italian: [ ['a1', 'A', true, [ ['a1', 'A', 'a1', '1', 'K_A', 'NCAPS SHIFT'], @@ -770,7 +768,7 @@ describe('KeylayoutToKmnConverter', function () { describe('get_KeyActionOutput_array__From__ActionStateOutput_array ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const read = sut_r.read(inputFilename); /* Italian: const b6_actionId_arr = [ diff --git a/developer/src/kmc-convert/test/kmn-file-reader.tests.ts b/developer/src/kmc-convert/test/kmn-file-reader.tests.ts index 428d61e3ad2..c6bdcca108c 100644 --- a/developer/src/kmc-convert/test/kmn-file-reader.tests.ts +++ b/developer/src/kmc-convert/test/kmn-file-reader.tests.ts @@ -11,7 +11,6 @@ import 'mocha'; import { assert } from 'chai'; import { compilerTestCallbacks, makePathToFixture } from './helpers/index.js'; import { KeylayoutFileReader } from '../src/keylayout-to-kmn/keylayout-file-reader.js'; -import { KeylayoutToKmnConverter } from '../src/keylayout-to-kmn/keylayout-to-kmn-converter.js'; //----------------------------------------------------------------------------------------------------------------------- @@ -26,7 +25,7 @@ describe('KeylayoutFileReader', function () { const sut_r = new KeylayoutFileReader(compilerTestCallbacks); it('read() should return filled array on correct input', async function () { - const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const result = sut_r.read(inputFilename); assert.isNotEmpty(result); }); @@ -47,13 +46,13 @@ describe('KeylayoutFileReader', function () { }); it('read() should return empty array on unavailable file name', async function () { - const inputFilename_unavailable = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/X.keylayout'); + const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); const result = sut_r.read(inputFilename_unavailable); assert.isNull(result); }); it('read() should return empty array on typo in path', async function () { - const result = sut_r.read(makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '|Test.keylayout')); + const result = sut_r.read(makePathToFixture('../data|Test.keylayout')); assert.isNull(result); }); }); diff --git a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts index fbacb6d3131..17c810ed1a1 100644 --- a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts +++ b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts @@ -23,17 +23,17 @@ describe('KmnFileWriter', function () { }); describe("write() ", function () { - const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); const read = sut_r.read(inputFilename); - const converted = sut.convert_bound.convert(read); + const converted = sut.convert_bound.convert(read, '/Test.keylayout'.replace(/\.keylayout$/, '.kmn')); // empty convert_object from unavailable file name - const inputFilename_unavailable = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/X.keylayout'); + const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); const read_unavailable = sut_r.read(inputFilename_unavailable); - const converted_unavailable = sut.convert_bound.convert(read_unavailable); + const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); it('write() should return true (no error) if written', async function () { @@ -49,12 +49,12 @@ describe('KmnFileWriter', function () { }); describe("writeToString() ", function () { - const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); const read = sut_r.read(inputFilename); - const converted = sut.convert_bound.convert(read); + const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); const out_expected_first: string = "c ..................................................................................................................\n" + "c ..................................................................................................................\n" @@ -72,9 +72,10 @@ describe('KmnFileWriter', function () { + "\n"; // empty convert_object from unavailable file name - const inputFilename_unavailable = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/X.keylayout'); + //const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); + const inputFilename_unavailable = '/X.keylayout'; const read_unavailable = sut_r.read(inputFilename_unavailable); - const converted_unavailable = sut.convert_bound.convert(read_unavailable); + const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); it('writeToString() should return result', async function () { const result = sut_w.writeToString(converted); @@ -88,12 +89,13 @@ describe('KmnFileWriter', function () { }); describe("writeToUint8Array() ", function () { - const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Test.keylayout'); + //const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = '/Test.keylayout'; const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); const read = sut_r.read(inputFilename); - const converted = sut.convert_bound.convert(read); + const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); const out_expected_first: string = "c ..................................................................................................................\n" @@ -113,9 +115,9 @@ describe('KmnFileWriter', function () { // empty convert_object from unavailable file name - const inputFilename_unavailable = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/X.keylayout'); + const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); const read_unavailable = sut_r.read(inputFilename_unavailable); - const converted_unavailable = sut.convert_bound.convert(read_unavailable); + const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); it('writeToUint8Array() should return header in case of missing inputfile', async function () { const result = sut_w.writeToUint8Array(converted_unavailable); assert.equal(new TextDecoder().decode(result), ("\n" + out_expected_first + out_expected_last)); @@ -128,17 +130,17 @@ describe('KmnFileWriter', function () { }); describe("writeData_Rules() ", function () { - const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); const read = sut_r.read(inputFilename); - const converted = sut.convert_bound.convert(read); + const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); // empty convert_object from unavailable file name - const inputFilename_unavailable = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/X.keylayout'); + const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); const read_unavailable = sut_r.read(inputFilename_unavailable); - const converted_unavailable = sut.convert_bound.convert(read_unavailable); + const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); it('writeData_Rules() should return true (no error) if written', async function () { const result = sut_w.writeData_Rules(converted); @@ -156,19 +158,19 @@ describe('KmnFileWriter', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); - const inputFilename = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const read = sut_r.read(inputFilename); - const converted = sut.convert_bound.convert(read); + const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); // empty convert_object from unavailable file name - const inputFilename_unavailable = makePathToFixture('../' + KeylayoutToKmnConverter.DATA_SUBFOLDER + '/X.keylayout'); + const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); const read_unavailable = sut_r.read(inputFilename_unavailable); - const converted_unavailable = sut.convert_bound.convert(read_unavailable); + const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); // empty convert_object from empty filename const inputFilename_empty = makePathToFixture(''); const read_empty = sut_r.read(inputFilename_empty); - const converted_empty = sut.convert_bound.convert(read_empty); + const converted_empty = sut.convert_bound.convert(read_empty, inputFilename_empty.replace(/\.keylayout$/, '.kmn')); const out_expected_first: string = "c ..................................................................................................................\n" From c0d64f82a8229d9f9d04aae7e0ef6a23850b547c Mon Sep 17 00:00:00 2001 From: Sabine Date: Fri, 27 Jun 2025 11:23:47 +0200 Subject: [PATCH 118/251] feat(developer): remove my own tests --- .../test/keylayout-to-kmn-converter.tests.ts | 36 ------------------- 1 file changed, 36 deletions(-) diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index 421ec6e640e..48034f682ea 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -20,42 +20,6 @@ describe('KeylayoutToKmnConverter', function () { before(function () { compilerTestCallbacks.clear(); }); - // todo remove - describe('RunOneFile', function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const inputFilename = makePathToFixture('../data/Italian.keylayout'); - sut.run(inputFilename); - assert.isTrue(true); - }); - - // todo remove - describe('RunAllFiles', function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - [ - [makePathToFixture('../data/Italian.keylayout')], - [makePathToFixture('../data/Italian_command.keylayout')], - [makePathToFixture('../data/Swiss_French.keylayout')], - [makePathToFixture('../data/Spanish.keylayout')], - [makePathToFixture('../data/Swiss_German.keylayout')], - [makePathToFixture('../data/US.keylayout')], - [makePathToFixture('../data/Polish.keylayout')], - [makePathToFixture('../data/French.keylayout')], - [makePathToFixture('../data/Latin_American.keylayout')], - [makePathToFixture('../data/German_Complete.keylayout')], - /* [makePathToFixture('../data/German_complete_reduced.keylayout')], - [makePathToFixture('../data/German_Standard.keylayout')],*/ - ].forEach(function (files_) { - sut.run(files_[0]); - assert.isTrue(true); - }); - }); - // todo remove - describe('RunOneFile', function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const inputFilename = makePathToFixture('../data/Test.keylayout'); - sut.run(inputFilename); - assert.isTrue(true); - }); describe('run() ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); From 855ae40579adb413deb9be8907ea23ae9a51d25b Mon Sep 17 00:00:00 2001 From: Sabine Date: Fri, 27 Jun 2025 14:02:31 +0200 Subject: [PATCH 119/251] feat(developer): set timeout to 10000 ms for tests of the run() function --- .../src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index 48034f682ea..d196efe11e2 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -22,6 +22,11 @@ describe('KeylayoutToKmnConverter', function () { }); describe('run() ', function () { + + // _S2 can I do this??? - some tests of the run() function might take longer than 2000 ms + // see https://pramod-mallick.medium.com/mocha-with-selenium-webdriver-exception-timeout-of-2000ms-exceeded-89df7b6230c6 + this.timeout(10000); + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); it('run() should throw on null input file name and null output file name', async function () { From e85c4564ef31769013f84d636424aa0b7ecc7b6c Mon Sep 17 00:00:00 2001 From: Sabine Date: Fri, 27 Jun 2025 14:07:04 +0200 Subject: [PATCH 120/251] feat(developer): change timeout for run() test --- .../src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index 230d9cea4f3..b980a7c7422 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -22,6 +22,11 @@ describe('KeylayoutToKmnConverter', function () { }); describe('run() ', function () { + + // _S2 can I do this??? - some tests of the run() function might take longer than 2000 ms + // see https://pramod-mallick.medium.com/mocha-with-selenium-webdriver-exception-timeout-of-2000ms-exceeded-89df7b6230c6 + this.timeout(10000); + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); it('run() should throw on null input file name and null output file name', async function () { From cdb3634f418a90ba38af18f5e534cf8320d80ed6 Mon Sep 17 00:00:00 2001 From: Sabine Date: Sat, 28 Jun 2025 08:54:25 +0200 Subject: [PATCH 121/251] feat(developer): interfaces for attributes/nodes --- common/web/types/build.sh | 2 +- common/web/types/src/schema-validators.ts | 2 +- .../keylayout-to-kmn/keylayout-file-reader.ts | 20 ++++++++++++++++--- .../keylayout-to-kmn-converter.ts | 10 +++++++--- 4 files changed, 26 insertions(+), 8 deletions(-) diff --git a/common/web/types/build.sh b/common/web/types/build.sh index f5c30104a2c..a0211194f20 100755 --- a/common/web/types/build.sh +++ b/common/web/types/build.sh @@ -30,9 +30,9 @@ builder_parse "$@" function compile_schemas() { # We need the schema files at runtime and bundled, so always copy it for all actions except `clean` local schemas=( + "$KEYMAN_ROOT/resources/standards-data/keylayout/keylayout.schema.json" "$KEYMAN_ROOT/resources/standards-data/ldml-keyboards/46/ldml-keyboard3.schema.json" "$KEYMAN_ROOT/resources/standards-data/ldml-keyboards/46/ldml-keyboardtest3.schema.json" - "$KEYMAN_ROOT/resources/standards-data/keylayout/keylayout.schema.json" "$KEYMAN_ROOT/common/schemas/kvks/kvks.schema.json" "$KEYMAN_ROOT/common/schemas/kpj/kpj.schema.json" "$KEYMAN_ROOT/common/schemas/kpj-9.0/kpj-9.0.schema.json" diff --git a/common/web/types/src/schema-validators.ts b/common/web/types/src/schema-validators.ts index 7c4d337fefa..37a0f193674 100644 --- a/common/web/types/src/schema-validators.ts +++ b/common/web/types/src/schema-validators.ts @@ -16,8 +16,8 @@ const SchemaValidators = { kpj, kpj90, kvks, - ldmlKeyboard3, keylayout, + ldmlKeyboard3, ldmlKeyboardTest3, displayMap, touchLayoutClean, diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts index c3b2c758f6b..12556a65302 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts @@ -13,6 +13,10 @@ import { util } from '@keymanapp/common-types'; import { KeylayoutToKmnConverter } from './keylayout-to-kmn-converter.js'; import { ConverterMessages } from '../converter-messages.js'; import { SchemaValidators } from '@keymanapp/common-types'; + +// _S2 which folder should keylayout-xml.js live?? +import { KeylayoutXMLSourceFile } from '../../../common/web/utils/src/types/keylayout/keylayout-xml.js'; + import boxXmlArray = util.boxXmlArray; export class KeylayoutFileReader { @@ -23,7 +27,17 @@ export class KeylayoutFileReader { /** * @returns true if valid, false if invalid */ - public validate(source: any): boolean { + + //public validate(source: LDMLKeyboardXMLSourceFile | LDMLKeyboardTestDataXMLSourceFile): boolean { + public validate(source: KeylayoutXMLSourceFile): boolean { + // public validate(source: any): boolean { + console.log("SchemaValidators.default.keylayout(source) ", SchemaValidators.default.keylayout(source)); + + + //SchemaValidators.default.keylayout(source); + + + if (!SchemaValidators.default.keylayout(source)) { console.log("SchemaValidators.default.keylayout).errors ", (SchemaValidators.default.keylayout).errors); @@ -68,14 +82,14 @@ export class KeylayoutFileReader { * @param absolutefilename the ukelele .keylayout-file to be parsed * @return in case of success: json object containing data of the .keylayout file; else null */ - public read(inputFilename: string): Object { + public read(inputFilename: string): KeylayoutXMLSourceFile { const options = { ignoreAttributes: false, trimValues: false, // preserve spaces attributeNamePrefix: '@_', // to access the attribute - ignoreDeclaration:true + ignoreDeclaration: true }; try { diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 3216301b9ac..eaaf36b37c5 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -11,6 +11,10 @@ import { KmnFileWriter } from './kmn-file-writer.js'; import { KeylayoutFileReader } from './keylayout-file-reader.js'; import { ConverterMessages } from '../converter-messages.js'; + +// _S2 which folder should keylayout-xml.js live?? +import { KeylayoutXMLSourceFile } from '../../../common/web/utils/src/types/keylayout/keylayout-xml.js'; + export interface convert_object { keylayout_filename: string, kmn_filename: string, @@ -53,14 +57,14 @@ export class KeylayoutToKmnConverter { } const KeylayoutReader = new KeylayoutFileReader(this.callbacks/*, this.options*/); - const jsonO: object = KeylayoutReader.read(inputFilename); + const jsonO: KeylayoutXMLSourceFile = KeylayoutReader.read(inputFilename); // to check if it works: validate file with stevens schema file ------------------------------------------------- - console.log("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ I will validate ",inputFilename, "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); + console.log("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ I will validate ", inputFilename, "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); try { - if (!KeylayoutReader.validate(jsonO)) { + if (!KeylayoutReader.validate(jsonO)) { return null; } } catch (e) { From 70965c0dfe66a90ef250b7a4044f7e089b73c760 Mon Sep 17 00:00:00 2001 From: Sabine Date: Wed, 2 Jul 2025 14:51:18 +0200 Subject: [PATCH 122/251] feat(developer): validate: edit xsd-file-> validates files OK --- .../keylayout-to-kmn/keylayout-file-reader.ts | 15 +- .../test/keylayout-to-kmn-converter.tests.ts | 39 ++ .../keylayout/dtd/keylayout.dtd | 31 ++ .../keylayout/dtd/keylayout.xsd | 92 ++--- .../keylayout/fixup-keylayout-schema.js | 235 +----------- .../keylayout/keylayout.schema.json | 336 +++++------------- 6 files changed, 236 insertions(+), 512 deletions(-) create mode 100644 resources/standards-data/keylayout/dtd/keylayout.dtd diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts index 12556a65302..96cb1fc0633 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts @@ -82,14 +82,25 @@ export class KeylayoutFileReader { * @param absolutefilename the ukelele .keylayout-file to be parsed * @return in case of success: json object containing data of the .keylayout file; else null */ - public read(inputFilename: string): KeylayoutXMLSourceFile { + public read(inputFilename: string): KeylayoutXMLSourceFile { const options = { + /*ignoreAttributes: false, + attributeNamePrefix: '@_', // to access the attribute + ignoreDeclaration: true, + parseTagValue: false, // does this prevent output of #text ????, + // trimValues: false, // preserve spaces + trimValues: true, + textNodeName: "##text",*/ + ignoreAttributes: false, - trimValues: false, // preserve spaces + trimValues: true, + //textNodeName: "##text", + parseTagValue: false, // does this prevent output of #text ????, attributeNamePrefix: '@_', // to access the attribute ignoreDeclaration: true + }; try { diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index 87d842a6b54..12053b83b21 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -18,6 +18,45 @@ describe('KeylayoutToKmnConverter', function () { compilerTestCallbacks.clear(); }); + // todo remove + describe('RunOneFile', function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const inputFilename = makePathToFixture('../data/Test.keylayout'); + sut.run(inputFilename); + assert.isTrue(true); + }); + + // todo remove + describe('RunOneFile', function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const inputFilename = makePathToFixture('../data/Italian.keylayout'); + sut.run(inputFilename); + assert.isTrue(true); + }); + + // todo remove + describe('RunAllFiles', function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + [ + [makePathToFixture('../data/Italian.keylayout')], + [makePathToFixture('../data/Italian_command.keylayout')], + [makePathToFixture('../data/Swiss_French.keylayout')], + [makePathToFixture('../data/Spanish.keylayout')], + [makePathToFixture('../data/Swiss_German.keylayout')], + [makePathToFixture('../data/US.keylayout')], + [makePathToFixture('../data/Polish.keylayout')], + [makePathToFixture('../data/French.keylayout')], + [makePathToFixture('../data/Latin_American.keylayout')], + [makePathToFixture('../data/German_complete.keylayout')], + // [makePathToFixture('../data/German_complete_reduced.keylayout')], + // [makePathToFixture('../data/German_Standard.keylayout')], + ].forEach(function (files_) { + sut.run(files_[0]); + assert.isTrue(true); + }); + }); + + describe('run() ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); diff --git a/resources/standards-data/keylayout/dtd/keylayout.dtd b/resources/standards-data/keylayout/dtd/keylayout.dtd new file mode 100644 index 00000000000..55b41719718 --- /dev/null +++ b/resources/standards-data/keylayout/dtd/keylayout.dtd @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/standards-data/keylayout/dtd/keylayout.xsd b/resources/standards-data/keylayout/dtd/keylayout.xsd index 6d7f0f37e61..675ebd601ba 100644 --- a/resources/standards-data/keylayout/dtd/keylayout.xsd +++ b/resources/standards-data/keylayout/dtd/keylayout.xsd @@ -1,101 +1,105 @@ - + + + + + - - - - - - - + + + + + + + - + - - - - + + - + - - + + - + + - + - - - - - - + + + + - + + + + - + - + - - - - - - + + + + - + + + - - - - - + + + + + + + + + - - - - - \ No newline at end of file + diff --git a/resources/standards-data/keylayout/fixup-keylayout-schema.js b/resources/standards-data/keylayout/fixup-keylayout-schema.js index 6afec678cc0..7dd2bf37846 100644 --- a/resources/standards-data/keylayout/fixup-keylayout-schema.js +++ b/resources/standards-data/keylayout/fixup-keylayout-schema.js @@ -1,137 +1,24 @@ /* Copyright: © SIL International. Description: Fix up schema from xsd2js - Create Date: 17 Oct 2022 - Authors: Steven R. Loomis (SRL) + Create Date: 2 June 2025 + Authors: Sabine Schmitt + Copied and altered from SRL´s : resources\standards-data\ldml-keyboards\fixup-schema.js */ const { strict } = require('assert'); const { readFileSync, writeFileSync } = require('fs'); const { argv } = require('process'); -// Usage: -// node fixup-schema.js [filename.json] -// If no filename, reads and writes stdin/stdout - // Read stuff const input = readFileSync(argv[2] || 0, "utf-8"); -// uses C:\Projects\keyman\keyman\developer\src\common\web\utils\src\xml-utils.ts - parse() const data = JSON.parse(input); -const aaa = data.properties.keyboard.properties.id; -const b = data['$id']; -const c = data['id']; - - -// Fix stuff -// SAB brauch ich nicht -if (!data['$id'] && data['id']) { - data['$id'] = data['id']; - delete data['id']; -} - -/* -public parse(data: string): any { - const parser = this.parser(); - let result = parser.parse(data, true); - if (PARSER_OPTIONS[this.type].attributeNamePrefix === '$') { - result = KeymanXMLReader.fixupDollarAttributes(result); - } else if (PARSER_OPTIONS[this.type].attributeNamePrefix === '@__') { - result = KeymanXMLReader.fixupEmptyStringToEmptyObject(result); - } else if (PARSER_OPTIONS[this.type].preserveOrder) { - result = KeymanXMLReader.fixupPreserveOrder(result); - } - delete result['?xml']; - return result; - } - - - - - //** - // * Requires attribute prefix @__ (double underscore) - //* For attributes, just remove @__ and continue. - // * For objects, replace any empty string "" with an empty object {} - private static fixupEmptyStringToEmptyObject(data: any) : any { - if (typeof data === 'object') { - // For arrays of objects, we map "" to {} - // "" means an empty object - if (Array.isArray(data)) { - return data.map(v => { - if (v === '') { - return {}; - } else { - return KeymanXMLReader.fixupEmptyStringToEmptyObject(v); - } - }); - } - // otherwise: remove @__ for attributes, remap objects - const e: any = []; - Object.entries(data).forEach(([k, v]) => { - if (k.startsWith('@__')) { - e.push([k.substring(3), KeymanXMLReader.fixupEmptyStringToEmptyObject(v)]); - } else { - if (v === '') { - e.push([k, {}]); - } else { - e.push([k, KeymanXMLReader.fixupEmptyStringToEmptyObject(v)]); - } - } - }); - return Object.fromEntries(e); - } else { - return data; - } - } - - -*/ - - -function trysomething(o) { - console.log("trysomething ",); - if (!o) return; - if (o.type === 'object') { - o.type = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; - } -} -function trysomething1(o) { - console.log("trysomething1 ",); - console.log("data zuerts",data); - - data.type = 'string'; // change tag type - data.title = "blabla"; // change tag title - data.required = "myTag"; // change tag required - - data.properties.keyboard.properties.actions.type= "bool" -delete data.properties.keyboard.properties.terminators.properties.when.items - console.log("data dann ",data); -} - - - -/** - * Turn a schema node from an array into a singleton of the specified type - * @param {Object} o - */ -function arrayToSingle(o) { - console.log("arrayToSingle(o) ",); - - if (!o) return; - if (o.type === 'array') { - o["$ref"] = o.items["$ref"]; - delete o.items; - delete o.type; - } -} - /** * Turn a schema node from a singleton of some type into an array of that type * @param {Object} o */ function singleToArray(o) { - console.log("function singleToArray(o) { ",); - if (!o) return; if (!o.type) { o.items = { "$ref": o["$ref"] }; @@ -140,120 +27,18 @@ function singleToArray(o) { } } - -/** - * Requires attribute prefix @_ (double underscore) - * For attributes, just remove @_ and continue. - * For objects, replace any empty string "" with an empty object {} */ -function fixupEmptyStringToEmptyObject_keylayout_1(data) { - - //console.log("in fixupEmptyStringToEmptyObject_keylayout_1 ", data); - data.title = "blabla"; - trysomething1(data); - trysomething1(data.properties.keyboard.properties); - - if (typeof data === 'object') { - console.log(" ",); - trysomething(data); - trysomething(data.properties.keyboard.properties); - - } - /* - if (typeof data === 'object') { - // For arrays of objects, we map "" to {} - // "" means an empty object - if (Array.isArray(data)) { - return data.map(v => { - if (v === '') { - return {}; - } else { - return data.fixupEmptyStringToEmptyObject_keylayout_1(v); - } - }); - } - // otherwise: remove @_ for attributes, remap objects - const e = []; - Object.entries(data).forEach(([k, v]) => { - if (k.startsWith('@_')) { - e.push([k.substring(2), data.fixupEmptyStringToEmptyObject_keylayout_1(v)]); - } else { - if (v === '') { - e.push([k, {}]); - } else { - e.push([k, data.fixupEmptyStringToEmptyObject_keylayout_1(v)]); - } - } - }); - return Object.fromEntries(e); - } else { - return data; - }*/ -} -console.log("data ", data); - - - if (data.title.endsWith('keylayout.xsd')) { if (data?.properties?.keyboard) { data.properties.keyboard.type = 'object'; - - // SAB brauch ich nicht - // add the xmlns property as allowed - /* if (!data.properties.keyboard3?.properties?.xmlns) { - data.properties.keyboard3.properties.xmlns = { type: 'string' }; - }*/ } - // SAB da ruft er für verschiedene tags die funct. auf. - arrayToSingle(data?.properties?.keyboard3?.properties?.vkeys); - singleToArray(data?.definitions?.keys?.properties?.key); - singleToArray(data?.definitions?.keys?.properties?.flicks); - arrayToSingle(data?.definitions?.displays?.properties?.displayOptions); - fixupEmptyStringToEmptyObject_keylayout_1(data); - - - //let result = parser.parse(data, true); - //result = KeymanXMLReader.fixupEmptyStringToEmptyObject_keylayout(data); - - - - console.log("doneXX ",); - - - // So we have a little problem where the element 'string' becomes the schema built in type 'string' - // may be a bug. anyway, fix it - /*if (data.definitions["string"]) { - // if we have the problematic case - const oldName = "string"; - const newName = "stringVariable"; - // move the definition - data.definitions[newName] = data.definitions[oldName]; - delete data.definitions[oldName]; - // move the reference - const item = data.definitions.variables.properties[oldName]; - // Note: not renaming the property, just the type - if (item?.items?.type !== oldName) { - // sanity check! - throw `Couldn’t fixup type, at this location expected to find ${oldName}`; - } - // Change from a type to a ref - delete item.items.type; - item.items['$ref'] = `#/definitions/${newName}`; - } - // Workaround CLDR-18138 by not making 'cldr' the default for the base - delete data.definitions?.import?.properties?.base?.enum;*/ -} - -if (data.title.endsWith('ldmlKeyboardTest3.xsd')) { - if (data?.properties?.keyboardTest3) { - data.properties.keyboardTest3.type = 'object'; - - // SAB brauch ich nicht - // support this proactively - if (!data.properties.keyboardTest3?.properties?.xmlns) { - data.properties.keyboardTest3.properties.xmlns = { type: 'string' }; - } - } + /* + arrayToSingle(data?.properties?.keyboard3?.properties?.vkeys); + singleToArray(data?.definitions?.keys?.properties?.key); + singleToArray(data?.definitions?.keys?.properties?.key); + singleToArray(data?.definitions?.keys?.properties?.flicks); + arrayToSingle(data?.definitions?.displays?.properties?.displayOptions); + */ } // Write stuff diff --git a/resources/standards-data/keylayout/keylayout.schema.json b/resources/standards-data/keylayout/keylayout.schema.json index b866fc9bd40..4eca42df76a 100644 --- a/resources/standards-data/keylayout/keylayout.schema.json +++ b/resources/standards-data/keylayout/keylayout.schema.json @@ -5,6 +5,18 @@ "keyboard": { "additionalProperties": false, "properties": { + "@_group": { + "type": "string" + }, + "@_id": { + "type": "string" + }, + "@_maxout": { + "type": "string" + }, + "@_name": { + "type": "string" + }, "actions": { "additionalProperties": false, "properties": { @@ -12,69 +24,23 @@ "items": { "additionalProperties": false, "properties": { - "action": { - "items": { - "additionalProperties": false, - "properties": { - "id": { - "type": "string" - }, - "when": { - "items": { - "additionalProperties": false, - "properties": { - "next": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "output": { - "type": "string" - }, - "state": { - "type": "string" - } - }, - "required": [ - "state" - ], - "type": "object" - }, - "minItems": 1, - "type": "array" - } - }, - "required": [ - "when", - "id" - ], - "type": "object" - }, - "minItems": 1, - "type": "array" - }, - "id": { + "@_id": { "type": "string" }, "when": { "items": { "additionalProperties": false, "properties": { - "next": { - "maximum": 255, - "minimum": 0, - "type": "integer" + "@_next": { + "type": "string" }, - "output": { + "@_output": { "type": "string" }, - "state": { + "@_state": { "type": "string" } }, - "required": [ - "state" - ], "type": "object" }, "minItems": 1, @@ -82,9 +48,7 @@ } }, "required": [ - "when", - "id", - "action" + "when" ], "type": "object" }, @@ -97,139 +61,81 @@ ], "type": "object" }, - "group": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "id": { - "maximum": 32767, - "minimum": -32768, - "type": "integer" - }, "keyMapSet": { - "additionalProperties": false, - "properties": { - "id": { - "type": "string" - }, - "keyMap": { - "items": { - "additionalProperties": false, - "properties": { - "index": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "key": { - "items": { - "additionalProperties": false, - "properties": { - "action": { - "type": "string" - }, - "code": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "output": { - "type": "string" - } - }, - "required": [ - "code" - ], - "type": "object" - }, - "minItems": 1, - "type": "array" - } - }, - "required": [ - "key", - "index" - ], - "type": "object" + "items": { + "additionalProperties": false, + "properties": { + "@_id": { + "type": "string" }, - "minItems": 1, - "type": "array" - } - }, - "required": [ - "keyMap", - "id" - ], - "type": "object" - }, - "layouts": { - "additionalProperties": false, - "properties": { - "layout": { - "additionalProperties": false, - "properties": { - "first": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "last": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "layout": { + "keyMap": { + "items": { "additionalProperties": false, "properties": { - "first": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "last": { - "maximum": 255, - "minimum": 0, - "type": "integer" + "@_index": { + "type": "string" }, - "mapSet": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "modifiers": { - "maximum": 255, - "minimum": 0, - "type": "integer" + "key": { + "items": { + "additionalProperties": false, + "properties": { + "@_action": { + "type": "string" + }, + "@_code": { + "type": "string" + }, + "@_output": { + "type": "string" + } + }, + "type": "object" + }, + "minItems": 1, + "type": "array" } }, "required": [ - "first", - "last", - "mapSet", - "modifiers" + "key" ], "type": "object" }, - "mapSet": { - "maximum": 255, - "minimum": 0, - "type": "integer" + "minItems": 1, + "type": "array" + } + }, + "required": [ + "keyMap" + ], + "type": "object" + }, + "minItems": 1, + "type": "array" + }, + "layouts": { + "additionalProperties": false, + "properties": { + "layout": { + "items": { + "additionalProperties": false, + "properties": { + "@_first": { + "type": "string" + }, + "@_last": { + "type": "string" + }, + "@_mapSet": { + "type": "string" + }, + "@_modifiers": { + "type": "string" + } }, - "modifiers": { - "maximum": 255, - "minimum": 0, - "type": "integer" - } + "type": "object" }, - "required": [ - "first", - "last", - "mapSet", - "modifiers", - "layout" - ], - "type": "object" + "minItems": 1, + "type": "array" } }, "required": [ @@ -237,44 +143,30 @@ ], "type": "object" }, - "maxout": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, "modifierMap": { "additionalProperties": false, "properties": { - "defaultIndex": { - "maximum": 255, - "minimum": 0, - "type": "integer" + "@_defaultIndex": { + "type": "string" }, - "id": { - "maximum": 255, - "minimum": 0, - "type": "integer" + "@_id": { + "type": "string" }, "keyMapSelect": { "items": { "additionalProperties": false, "properties": { - "mapIndex": { - "maximum": 255, - "minimum": 0, - "type": "integer" + "@_mapIndex": { + "type": "string" }, "modifier": { "items": { "additionalProperties": false, "properties": { - "keys": { + "@_keys": { "type": "string" } }, - "required": [ - "keys" - ], "type": "object" }, "minItems": 1, @@ -282,8 +174,7 @@ } }, "required": [ - "modifier", - "mapIndex" + "modifier" ], "type": "object" }, @@ -292,15 +183,10 @@ } }, "required": [ - "keyMapSelect", - "id", - "defaultIndex" + "keyMapSelect" ], "type": "object" }, - "name": { - "type": "string" - }, "terminators": { "additionalProperties": false, "properties": { @@ -308,42 +194,13 @@ "items": { "additionalProperties": false, "properties": { - "output": { + "@_output": { "type": "string" }, - "state": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "when": { - "items": { - "additionalProperties": false, - "properties": { - "output": { - "type": "string" - }, - "state": { - "maximum": 255, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "state", - "output" - ], - "type": "object" - }, - "minItems": 1, - "type": "array" + "@_state": { + "type": "string" } }, - "required": [ - "state", - "output", - "when" - ], "type": "object" }, "minItems": 1, @@ -361,12 +218,9 @@ "modifierMap", "keyMapSet", "actions", - "terminators", - "group", - "id", - "name", - "maxout" - ] + "terminators" + ], + "type": "object" } }, "required": [ From 9937ce1ac418efa90f37b4d5c295bee749f6b979 Mon Sep 17 00:00:00 2001 From: Sabine Date: Wed, 2 Jul 2025 17:13:50 +0200 Subject: [PATCH 123/251] feat(developer): add keylayout to xml-utils --- developer/src/common/web/utils/src/xml-utils.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/developer/src/common/web/utils/src/xml-utils.ts b/developer/src/common/web/utils/src/xml-utils.ts index f83ca75dc76..be42131763c 100644 --- a/developer/src/common/web/utils/src/xml-utils.ts +++ b/developer/src/common/web/utils/src/xml-utils.ts @@ -15,8 +15,9 @@ const XML_META_DATA_SYMBOL = XMLParser.getMetaDataSymbol(); export const XML_FILENAME_SYMBOL = Symbol("XML Filename"); export type KeymanXMLType = - 'keyboard3' // LDML + 'keyboard3' // LDML | 'keyboardTest3' // LDML + | 'keylayout' // keylayout | 'kps' // | 'kvks' // | 'kpj' // @@ -64,6 +65,14 @@ const PARSER_OPTIONS: KeymanXMLParserOptionsBag = { ignorePiTags: true, preserveOrder: true, // Gives us a 'special' format }, + 'keylayout': { + attributeNamePrefix: '', // avoid @_ + htmlEntities: true, + ignoreAttributes: false, // We do not like attributes + ignorePiTags: true, + preserveOrder: true, // Gives us a 'special' format + ignoreDeclaration: true, + }, 'kps': { ...PARSER_COMMON_OPTIONS, }, From 4d307a5a0862f54d9eb52102bba07e40bf372b27 Mon Sep 17 00:00:00 2001 From: Sabine Date: Thu, 3 Jul 2025 09:59:46 +0200 Subject: [PATCH 124/251] feat(developer): remove commented code --- .../keylayout-to-kmn/keylayout-to-kmn-converter.ts | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 12ae110f25f..2cf4cd2731c 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -88,20 +88,6 @@ export class KeylayoutToKmnConverter { return null; }*/ - - /* - const a: ConverterToKmnArtifacts = null; - const ddd= a.data - return a ? a : null; - - data of convert_object needs to be in ConverterToKmnArtifacts: - (ConverterToKmnArtifacts= outArray ???) - return ConverterToKmnArtifacts ? { ConverterToKmnArtifacts } : null; - --- - const converter = new ConverterClass(this.callbacks, converterOptions); - const artifacts = await converter.run(inputFilename, outputFilename); - return artifacts ? { artifacts } : null;*/ - return null; } From 0e69f919406a49004134068ce015a2533f975ec1 Mon Sep 17 00:00:00 2001 From: Sabine Date: Thu, 3 Jul 2025 18:12:23 +0200 Subject: [PATCH 125/251] feat(developer): merged changes from 12564 into feat/developer/kmc-convert-validateKeylayout branch remove #text: first idea --- .../src/kmc-convert/src/converter-messages.ts | 20 ++--- .../keylayout-to-kmn/keylayout-file-reader.ts | 87 ++++++++++++++++++- .../test/keylayout-to-kmn-converter.tests.ts | 4 +- .../keylayout/dtd/keylayout.xsd | 21 ++++- .../keylayout/fixup-keylayout-schema.js | 1 + .../keylayout/keylayout.schema.json | 48 ++++++++++ 6 files changed, 164 insertions(+), 17 deletions(-) diff --git a/developer/src/kmc-convert/src/converter-messages.ts b/developer/src/kmc-convert/src/converter-messages.ts index 1ce694739aa..05bfec1ea37 100644 --- a/developer/src/kmc-convert/src/converter-messages.ts +++ b/developer/src/kmc-convert/src/converter-messages.ts @@ -30,16 +30,6 @@ export class ConverterMessages { static Error_FileNotFound = (o: { inputFilename: string; }) => m(this.ERROR_FileNotFound, `Input filename '${def(o.inputFilename)}' does not exist or could not be loaded.`); - // from SRL - static ERROR_InvalidFile = SevError | 0x0007; - static Error_InvalidFile = (o:{errorText: string}) => - m(this.ERROR_InvalidFile, `The source file has an invalid structure: ${def(o.errorText)}`); - - // from SRL - static ERROR_SchemaValidationError = SevError | 0x0011; - static Error_SchemaValidationError = (o:{instancePath:string, keyword:string, message: string, params: string}) => m(this.ERROR_SchemaValidationError, - `!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Error validating Keylayout XML file: ${def(o.instancePath)}: ${def(o.keyword)}: ${def(o.message)} ${def(o.params)}`); - static ERROR_UnableToRead = SevError | 0x0004; static Error_UnableToRead = (o: { inputFilename: string; }) => m( this.ERROR_UnableToRead, `Input file '${def(o.inputFilename)} @@ -59,4 +49,14 @@ export class ConverterMessages { static Error_UnsupportedCharactersDetected = (o: { inputFilename: string, keymap_index: string, key: string, output: string; }) => m( this.ERROR_UnsupportedCharactersDetected, `Input file ${def(o.inputFilename)} contains unsupported character ('${def(o.output)}') on key (${def(o.key)}) at keyMap index ${def(o.keymap_index)}`); + // from SRL + static ERROR_InvalidFile = SevError | 0x0008; + static Error_InvalidFile = (o:{errorText: string}) => + m(this.ERROR_InvalidFile, `The source file has an invalid structure: ${def(o.errorText)}`); + + // from SRL + static ERROR_SchemaValidationError = SevError | 0x009; + static Error_SchemaValidationError = (o:{instancePath:string, keyword:string, message: string, params: string}) => m(this.ERROR_SchemaValidationError, + `!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Error validating Keylayout XML file: ${def(o.instancePath)}: ${def(o.keyword)}: ${def(o.message)} ${def(o.params)}`); + } diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts index 4958b50fe2f..d912aa802cc 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts @@ -18,6 +18,50 @@ import { KeylayoutXMLSourceFile } from '../../../common/web/utils/src/types/keyl import boxXmlArray = util.boxXmlArray; +//.modifier[k]['@_keys'] + + +export function remove_text(o: any, x: string): void { +console.log("ooooooooooooo",o); + +console.log(" o.item ", o.layout); +console.log(" o.item ", o.layout['@_mapSet']); +//console.log(" o.item ", o.['@_first']); +console.log(" o.item", o['@_text'],"----", o['@_text']==="",o['@_text']==='\n \n '); + + +// assume tagName is the name of the tag you want to remove +//const tagsToRemove = o.getElementsByTagName('@_text'); +//const tagsToRemove = o.layout['@_mapSet'] +const tagsToRemove = o.layout +console.log("tagsToRemove ",/*tagsToRemove.length,*/tagsToRemove); + +for (let i = 4 - 1; i >= 0; i -- ) { +tagsToRemove[i].parentNode.removeChild(tagsToRemove[i]); +} + + +if(o['@_text']==='\n \n ') + o.remove(o['@_text']) + +if(o.item[0]==="@'_first'") + console.log("_first_first ",); + + + + if (typeof o == 'object' && !Array.isArray(o[x])) { + if (o[x] === null || o[x] === undefined) { + o[x] = []; + } + else { + o[x] = [o[x]]; + } + } + +} + + + export class KeylayoutFileReader { constructor(private callbacks: CompilerCallbacks /*,private options: CompilerOptions*/) { }; @@ -53,12 +97,17 @@ export class KeylayoutFileReader { return true; } + /** * @brief member function to box single-entry objects into arrays * @param source the object to be changed * @return objects that contain only boxed arrays */ public boxArray(source: any) { + +//remove_text(source.layouts, 'layout') + + boxXmlArray(source.layouts, 'layout'); boxXmlArray(source.terminators, 'when'); boxXmlArray(source, 'keyMapSet'); @@ -92,13 +141,49 @@ export class KeylayoutFileReader { trimValues: true, textNodeName: "##text",*/ + + + + //ignoreAttributes: false, + + ignoreAttributes: [''], + //ignoreAttributes: /^[ ]/, + //trimValues: true, // prevents '#text' but then cannot use ' ' as output character + trimValues: false, //_S2 was true !!! + textNodeName: "#_text", + parseTagValue: false, // does this prevent output of #text ????, + attributeNamePrefix: '@_', // to access the attribute + ignoreDeclaration: true + + + + /* ignoreAttributes: false, - trimValues: true, + //ignoreAttributes: ['#text', ''], + //ignoreAttributes: (aName) => aName.startsWith('ou') === 'tag.tag2' + //ignoreAttributes: false, + //ignoreAttributes: (/^[ ]/gm), + //ignoreAttributes: [/^[ ]/gm], + //ignoreAttributes: [/^[ ]/gm], + //ignoreAttributes: ('#text', jPath) => aName.startsWith('#tex'), + //trimValues: true, // prevents '#text' but then cannot use ' ' as output character + trimValues: false, //_S2 was true !!! //textNodeName: "##text", parseTagValue: false, // does this prevent output of #text ????, attributeNamePrefix: '@_', // to access the attribute ignoreDeclaration: true + + + + suppressBooleanAttributes?: boolean; + allowBooleanAttributes?: boolean; + stopNodes?: string[]; + allowBooleanAttributes?: boolean; + + cdataPropName?: false | string; + tagValueProcessor?: (tagName: string, tagValue: string, jPath: string, hasAttributes: boolean, isLeafNode: boolean) => unknown; +*/ }; try { diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index d48007029ff..ea624b41e34 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -50,8 +50,8 @@ describe('KeylayoutToKmnConverter', function () { [makePathToFixture('../data/Polish.keylayout')], [makePathToFixture('../data/French.keylayout')], [makePathToFixture('../data/Latin_American.keylayout')], - [makePathToFixture('../data/German_complete.keylayout')], - // [makePathToFixture('../data/German_complete_reduced.keylayout')], + // [makePathToFixture('../data/German_complete.keylayout')], + [makePathToFixture('../data/German_complete_reduced.keylayout')], // [makePathToFixture('../data/German_Standard.keylayout')], ].forEach(function (files_) { sut.run(files_[0]); diff --git a/resources/standards-data/keylayout/dtd/keylayout.xsd b/resources/standards-data/keylayout/dtd/keylayout.xsd index 675ebd601ba..df6dc1ee825 100644 --- a/resources/standards-data/keylayout/dtd/keylayout.xsd +++ b/resources/standards-data/keylayout/dtd/keylayout.xsd @@ -16,9 +16,10 @@ + - + @@ -30,14 +31,17 @@ + + + @@ -51,14 +55,19 @@ + + - + + + + @@ -73,13 +82,15 @@ + + - + @@ -89,9 +100,10 @@ + - + @@ -99,6 +111,7 @@ + diff --git a/resources/standards-data/keylayout/fixup-keylayout-schema.js b/resources/standards-data/keylayout/fixup-keylayout-schema.js index 7dd2bf37846..82f94f9a519 100644 --- a/resources/standards-data/keylayout/fixup-keylayout-schema.js +++ b/resources/standards-data/keylayout/fixup-keylayout-schema.js @@ -14,6 +14,7 @@ const { argv } = require('process'); const input = readFileSync(argv[2] || 0, "utf-8"); const data = JSON.parse(input); +// _S2 do I need this func & replace .xds´s type??? /** * Turn a schema node from a singleton of some type into an array of that type * @param {Object} o diff --git a/resources/standards-data/keylayout/keylayout.schema.json b/resources/standards-data/keylayout/keylayout.schema.json index 4eca42df76a..9b5bd2240a6 100644 --- a/resources/standards-data/keylayout/keylayout.schema.json +++ b/resources/standards-data/keylayout/keylayout.schema.json @@ -5,6 +5,9 @@ "keyboard": { "additionalProperties": false, "properties": { + "#_text": { + "type": "string" + }, "@_group": { "type": "string" }, @@ -20,10 +23,16 @@ "actions": { "additionalProperties": false, "properties": { + "#_text": { + "type": "string" + }, "action": { "items": { "additionalProperties": false, "properties": { + "#_text": { + "type": "string" + }, "@_id": { "type": "string" }, @@ -31,6 +40,9 @@ "items": { "additionalProperties": false, "properties": { + "#_text": { + "type": "string" + }, "@_next": { "type": "string" }, @@ -65,6 +77,9 @@ "items": { "additionalProperties": false, "properties": { + "#_text": { + "type": "string" + }, "@_id": { "type": "string" }, @@ -72,6 +87,15 @@ "items": { "additionalProperties": false, "properties": { + "#_text": { + "type": "string" + }, + "@_baseIndex": { + "type": "string" + }, + "@_baseMapSet": { + "type": "string" + }, "@_index": { "type": "string" }, @@ -79,6 +103,9 @@ "items": { "additionalProperties": false, "properties": { + "#_text": { + "type": "string" + }, "@_action": { "type": "string" }, @@ -115,10 +142,16 @@ "layouts": { "additionalProperties": false, "properties": { + "#_text": { + "type": "string" + }, "layout": { "items": { "additionalProperties": false, "properties": { + "#_text": { + "type": "string" + }, "@_first": { "type": "string" }, @@ -146,6 +179,9 @@ "modifierMap": { "additionalProperties": false, "properties": { + "#_text": { + "type": "string" + }, "@_defaultIndex": { "type": "string" }, @@ -156,6 +192,9 @@ "items": { "additionalProperties": false, "properties": { + "#_text": { + "type": "string" + }, "@_mapIndex": { "type": "string" }, @@ -163,6 +202,9 @@ "items": { "additionalProperties": false, "properties": { + "#_text": { + "type": "string" + }, "@_keys": { "type": "string" } @@ -190,10 +232,16 @@ "terminators": { "additionalProperties": false, "properties": { + "#_text": { + "type": "string" + }, "when": { "items": { "additionalProperties": false, "properties": { + "#_text": { + "type": "string" + }, "@_output": { "type": "string" }, From de9820d3c0089aad36f440aba5b89a21db4e933c Mon Sep 17 00:00:00 2001 From: Sabine Date: Fri, 4 Jul 2025 19:13:52 +0200 Subject: [PATCH 126/251] feat(developer): validation OK --- common/web/types/src/util/util.ts | 21 ++- .../keylayout-to-kmn/keylayout-file-reader.ts | 141 ++++-------------- .../test/keylayout-to-kmn-converter.tests.ts | 2 +- .../keylayout/dtd/keylayout.xsd | 20 +-- .../keylayout/fixup-keylayout-schema.js | 12 +- .../keylayout/keylayout.schema.json | 39 ----- 6 files changed, 58 insertions(+), 177 deletions(-) diff --git a/common/web/types/src/util/util.ts b/common/web/types/src/util/util.ts index 30016414312..165e30e6b2b 100644 --- a/common/web/types/src/util/util.ts +++ b/common/web/types/src/util/util.ts @@ -1,6 +1,19 @@ import { MATCH_HEX_ESCAPE, CONTAINS_QUAD_ESCAPE, MATCH_QUAD_ESCAPE } from './consts.js'; export { MATCH_HEX_ESCAPE, CONTAINS_QUAD_ESCAPE, MATCH_QUAD_ESCAPE }; + +/** + * If object contains attribute #text this will be removed + * this is to box them ourselves as needed. Ensures that o.x is an array. + * + * @param o Object with possible property #text + */ +export function remove_text(o: any): void { + if (o['#_text'] ) { + delete o['#_text']; + } +} + /** * xml2js will not place single-entry objects into arrays. Easiest way to fix * this is to box them ourselves as needed. Ensures that o.x is an array. @@ -9,6 +22,12 @@ export { MATCH_HEX_ESCAPE, CONTAINS_QUAD_ESCAPE, MATCH_QUAD_ESCAPE }; * @param x Name of element to box */ export function boxXmlArray(o: any, x: string): void { + + /*if (o['#_text'] ) { + delete o['#_text']; + }*/ + remove_text(o) + if (typeof o == 'object' && !Array.isArray(o[x])) { if (o[x] === null || o[x] === undefined) { o[x] = []; @@ -272,7 +291,7 @@ export function convertToUnicodeCharacter(in_str: string): string { return decodeUniHexValue(in_str); } - else if ( [...new Intl.Segmenter().segment(in_str)].length <= 1) { + else if ([...new Intl.Segmenter().segment(in_str)].length <= 1) { return in_str; } else { diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts index d912aa802cc..0ffddb0e80b 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts @@ -18,50 +18,6 @@ import { KeylayoutXMLSourceFile } from '../../../common/web/utils/src/types/keyl import boxXmlArray = util.boxXmlArray; -//.modifier[k]['@_keys'] - - -export function remove_text(o: any, x: string): void { -console.log("ooooooooooooo",o); - -console.log(" o.item ", o.layout); -console.log(" o.item ", o.layout['@_mapSet']); -//console.log(" o.item ", o.['@_first']); -console.log(" o.item", o['@_text'],"----", o['@_text']==="",o['@_text']==='\n \n '); - - -// assume tagName is the name of the tag you want to remove -//const tagsToRemove = o.getElementsByTagName('@_text'); -//const tagsToRemove = o.layout['@_mapSet'] -const tagsToRemove = o.layout -console.log("tagsToRemove ",/*tagsToRemove.length,*/tagsToRemove); - -for (let i = 4 - 1; i >= 0; i -- ) { -tagsToRemove[i].parentNode.removeChild(tagsToRemove[i]); -} - - -if(o['@_text']==='\n \n ') - o.remove(o['@_text']) - -if(o.item[0]==="@'_first'") - console.log("_first_first ",); - - - - if (typeof o == 'object' && !Array.isArray(o[x])) { - if (o[x] === null || o[x] === undefined) { - o[x] = []; - } - else { - o[x] = [o[x]]; - } - } - -} - - - export class KeylayoutFileReader { constructor(private callbacks: CompilerCallbacks /*,private options: CompilerOptions*/) { }; @@ -71,16 +27,9 @@ export class KeylayoutFileReader { * @returns true if valid, false if invalid */ - //public validate(source: LDMLKeyboardXMLSourceFile | LDMLKeyboardTestDataXMLSourceFile): boolean { public validate(source: KeylayoutXMLSourceFile): boolean { - // public validate(source: any): boolean { console.log("SchemaValidators.default.keylayout(source) ", SchemaValidators.default.keylayout(source)); - - //SchemaValidators.default.keylayout(source); - - - if (!SchemaValidators.default.keylayout(source)) { console.log("SchemaValidators.default.keylayout).errors ", (SchemaValidators.default.keylayout).errors); @@ -105,23 +54,40 @@ export class KeylayoutFileReader { */ public boxArray(source: any) { -//remove_text(source.layouts, 'layout') - - boxXmlArray(source.layouts, 'layout'); - boxXmlArray(source.terminators, 'when'); - boxXmlArray(source, 'keyMapSet'); - boxXmlArray(source.keyMapSet, 'keyMap'); - boxXmlArray(source.action, 'actions'); + //_S2 todo do not use remove_text in util.ts!! boxXmlArray(source?.modifierMap, 'keyMapSelect'); for (const keyMapSelect of source?.modifierMap?.keyMapSelect) { boxXmlArray(keyMapSelect, 'modifier'); } + + if (!Array.isArray(source?.keyMapSet) === false) { + for (let i = 0; i < source?.keyMapSet.length; i++) { + for (const keyMap of source?.keyMapSet[i]?.keyMap) { + boxXmlArray(keyMap, 'key'); + } + boxXmlArray(source.keyMapSet[i], 'keyMap'); + } + } else { + for (const keyMap of source?.keyMapSet?.keyMap) { + boxXmlArray(keyMap, 'key'); + } + boxXmlArray(source.keyMapSet, 'keyMap'); + // keyMapSet is the only top level tag that might occur several times + boxXmlArray(source, 'keyMapSet'); + } + boxXmlArray(source?.actions, 'action'); for (const action of source?.actions?.action) { boxXmlArray(action, 'when'); } + + boxXmlArray(source.terminators, 'when'); + for (const action of source?.actions?.action) { + boxXmlArray(action, 'when'); + } + return source; } @@ -133,64 +99,19 @@ export class KeylayoutFileReader { public read(inputFilename: string): KeylayoutXMLSourceFile { const options = { - /*ignoreAttributes: false, - attributeNamePrefix: '@_', // to access the attribute - ignoreDeclaration: true, - parseTagValue: false, // does this prevent output of #text ????, - // trimValues: false, // preserve spaces - trimValues: true, - textNodeName: "##text",*/ - - - - - //ignoreAttributes: false, - - ignoreAttributes: [''], - //ignoreAttributes: /^[ ]/, - //trimValues: true, // prevents '#text' but then cannot use ' ' as output character - trimValues: false, //_S2 was true !!! - textNodeName: "#_text", - parseTagValue: false, // does this prevent output of #text ????, - attributeNamePrefix: '@_', // to access the attribute + ignoreAttributes: [''], + trimValues: false, // we do not trim values because if we do we cannot process an output character of " " (whitespace) + textNodeName: "#_text", // #_text will be added for textnodes and will be removed later ( in remove_text() in boxXmlArray + parseTagValue: false, + attributeNamePrefix: '@_', // to access the attribute ignoreDeclaration: true - - - - /* - ignoreAttributes: false, - //ignoreAttributes: ['#text', ''], - //ignoreAttributes: (aName) => aName.startsWith('ou') === 'tag.tag2' - //ignoreAttributes: false, - //ignoreAttributes: (/^[ ]/gm), - //ignoreAttributes: [/^[ ]/gm], - //ignoreAttributes: [/^[ ]/gm], - //ignoreAttributes: ('#text', jPath) => aName.startsWith('#tex'), - //trimValues: true, // prevents '#text' but then cannot use ' ' as output character - trimValues: false, //_S2 was true !!! - //textNodeName: "##text", - parseTagValue: false, // does this prevent output of #text ????, - attributeNamePrefix: '@_', // to access the attribute - ignoreDeclaration: true - - - - - suppressBooleanAttributes?: boolean; - allowBooleanAttributes?: boolean; - stopNodes?: string[]; - allowBooleanAttributes?: boolean; - - cdataPropName?: false | string; - tagValueProcessor?: (tagName: string, tagValue: string, jPath: string, hasAttributes: boolean, isLeafNode: boolean) => unknown; -*/ }; try { const xmlFile = this.callbacks.fs.readFileSync(inputFilename, 'utf8'); const parser = new XMLParser(options); - const jsonObj = parser.parse(xmlFile); // get plain Object - this.boxArray(jsonObj.keyboard); // jsonObj now contains arrays; no single fields + const jsonObj = parser.parse(xmlFile); // get plain Object + this.boxArray(jsonObj.keyboard); // jsonObj now contains arrays; no single fields return jsonObj; } catch (err) { diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index ea624b41e34..c8943f48241 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -50,7 +50,7 @@ describe('KeylayoutToKmnConverter', function () { [makePathToFixture('../data/Polish.keylayout')], [makePathToFixture('../data/French.keylayout')], [makePathToFixture('../data/Latin_American.keylayout')], - // [makePathToFixture('../data/German_complete.keylayout')], + //[makePathToFixture('../data/German_complete.keylayout')], [makePathToFixture('../data/German_complete_reduced.keylayout')], // [makePathToFixture('../data/German_Standard.keylayout')], ].forEach(function (files_) { diff --git a/resources/standards-data/keylayout/dtd/keylayout.xsd b/resources/standards-data/keylayout/dtd/keylayout.xsd index df6dc1ee825..4b2cc977166 100644 --- a/resources/standards-data/keylayout/dtd/keylayout.xsd +++ b/resources/standards-data/keylayout/dtd/keylayout.xsd @@ -16,10 +16,9 @@ - - + @@ -31,17 +30,14 @@ - - - @@ -55,19 +51,14 @@ - - - - - - + @@ -82,15 +73,13 @@ - - - + @@ -100,10 +89,9 @@ - - + diff --git a/resources/standards-data/keylayout/fixup-keylayout-schema.js b/resources/standards-data/keylayout/fixup-keylayout-schema.js index 82f94f9a519..d7e8076660b 100644 --- a/resources/standards-data/keylayout/fixup-keylayout-schema.js +++ b/resources/standards-data/keylayout/fixup-keylayout-schema.js @@ -19,7 +19,7 @@ const data = JSON.parse(input); * Turn a schema node from a singleton of some type into an array of that type * @param {Object} o */ -function singleToArray(o) { +/*function singleToArray(o) { if (!o) return; if (!o.type) { o.items = { "$ref": o["$ref"] }; @@ -32,15 +32,7 @@ if (data.title.endsWith('keylayout.xsd')) { if (data?.properties?.keyboard) { data.properties.keyboard.type = 'object'; } - - /* - arrayToSingle(data?.properties?.keyboard3?.properties?.vkeys); - singleToArray(data?.definitions?.keys?.properties?.key); - singleToArray(data?.definitions?.keys?.properties?.key); - singleToArray(data?.definitions?.keys?.properties?.flicks); - arrayToSingle(data?.definitions?.displays?.properties?.displayOptions); - */ -} +}*/ // Write stuff const outstr = JSON.stringify(data, null, " "); diff --git a/resources/standards-data/keylayout/keylayout.schema.json b/resources/standards-data/keylayout/keylayout.schema.json index 9b5bd2240a6..1e67065fa9d 100644 --- a/resources/standards-data/keylayout/keylayout.schema.json +++ b/resources/standards-data/keylayout/keylayout.schema.json @@ -23,16 +23,10 @@ "actions": { "additionalProperties": false, "properties": { - "#_text": { - "type": "string" - }, "action": { "items": { "additionalProperties": false, "properties": { - "#_text": { - "type": "string" - }, "@_id": { "type": "string" }, @@ -40,9 +34,6 @@ "items": { "additionalProperties": false, "properties": { - "#_text": { - "type": "string" - }, "@_next": { "type": "string" }, @@ -77,9 +68,6 @@ "items": { "additionalProperties": false, "properties": { - "#_text": { - "type": "string" - }, "@_id": { "type": "string" }, @@ -87,9 +75,6 @@ "items": { "additionalProperties": false, "properties": { - "#_text": { - "type": "string" - }, "@_baseIndex": { "type": "string" }, @@ -103,9 +88,6 @@ "items": { "additionalProperties": false, "properties": { - "#_text": { - "type": "string" - }, "@_action": { "type": "string" }, @@ -142,16 +124,10 @@ "layouts": { "additionalProperties": false, "properties": { - "#_text": { - "type": "string" - }, "layout": { "items": { "additionalProperties": false, "properties": { - "#_text": { - "type": "string" - }, "@_first": { "type": "string" }, @@ -179,9 +155,6 @@ "modifierMap": { "additionalProperties": false, "properties": { - "#_text": { - "type": "string" - }, "@_defaultIndex": { "type": "string" }, @@ -192,9 +165,6 @@ "items": { "additionalProperties": false, "properties": { - "#_text": { - "type": "string" - }, "@_mapIndex": { "type": "string" }, @@ -202,9 +172,6 @@ "items": { "additionalProperties": false, "properties": { - "#_text": { - "type": "string" - }, "@_keys": { "type": "string" } @@ -232,16 +199,10 @@ "terminators": { "additionalProperties": false, "properties": { - "#_text": { - "type": "string" - }, "when": { "items": { "additionalProperties": false, "properties": { - "#_text": { - "type": "string" - }, "@_output": { "type": "string" }, From faaf5c9abc7e6397d1b5eab9f824b2997a0706c0 Mon Sep 17 00:00:00 2001 From: Sabine Date: Mon, 7 Jul 2025 11:42:00 +0200 Subject: [PATCH 127/251] feat(developer): validation finished --- common/web/types/src/util/util.ts | 18 ----- .../src/common/web/utils/src/xml-utils.ts | 41 ------------ .../src/kmc-convert/src/converter-messages.ts | 27 +++----- .../keylayout-to-kmn/keylayout-file-reader.ts | 65 ++++++++++++------- .../keylayout-to-kmn-converter.ts | 21 ------ .../keylayout/create_keylayout_schema.sh | 4 -- .../keylayout/dtd/keylayout.xsd | 1 - 7 files changed, 51 insertions(+), 126 deletions(-) diff --git a/common/web/types/src/util/util.ts b/common/web/types/src/util/util.ts index 165e30e6b2b..5dc61ff6774 100644 --- a/common/web/types/src/util/util.ts +++ b/common/web/types/src/util/util.ts @@ -1,19 +1,6 @@ import { MATCH_HEX_ESCAPE, CONTAINS_QUAD_ESCAPE, MATCH_QUAD_ESCAPE } from './consts.js'; export { MATCH_HEX_ESCAPE, CONTAINS_QUAD_ESCAPE, MATCH_QUAD_ESCAPE }; - -/** - * If object contains attribute #text this will be removed - * this is to box them ourselves as needed. Ensures that o.x is an array. - * - * @param o Object with possible property #text - */ -export function remove_text(o: any): void { - if (o['#_text'] ) { - delete o['#_text']; - } -} - /** * xml2js will not place single-entry objects into arrays. Easiest way to fix * this is to box them ourselves as needed. Ensures that o.x is an array. @@ -23,11 +10,6 @@ export function remove_text(o: any): void { */ export function boxXmlArray(o: any, x: string): void { - /*if (o['#_text'] ) { - delete o['#_text']; - }*/ - remove_text(o) - if (typeof o == 'object' && !Array.isArray(o[x])) { if (o[x] === null || o[x] === undefined) { o[x] = []; diff --git a/developer/src/common/web/utils/src/xml-utils.ts b/developer/src/common/web/utils/src/xml-utils.ts index 77d4f43d222..5bfc01ca07e 100644 --- a/developer/src/common/web/utils/src/xml-utils.ts +++ b/developer/src/common/web/utils/src/xml-utils.ts @@ -239,45 +239,6 @@ export class KeymanXMLReader { } } - - /** - * Requires attribute prefix @_ (double underscore) - * For attributes, just remove @_ and continue. - * For objects, replace any empty string "" with an empty object {} */ - private static fixupEmptyStringToEmptyObject_keylayout(data: any) : any { - console.log("in fixupEmptyStringToEmptyObject_keylayout ",); - - if (typeof data === 'object') { - // For arrays of objects, we map "" to {} - // "" means an empty object - if (Array.isArray(data)) { - return data.map(v => { - if (v === '') { - return {}; - } else { - return KeymanXMLReader.fixupEmptyStringToEmptyObject_keylayout(v); - } - }); - } - // otherwise: remove @_ for attributes, remap objects - const e: any = []; - Object.entries(data).forEach(([k, v]) => { - if (k.startsWith('@_')) { - e.push([k.substring(3), KeymanXMLReader.fixupEmptyStringToEmptyObject_keylayout(v)]); - } else { - if (v === '') { - e.push([k, {}]); - } else { - e.push([k, KeymanXMLReader.fixupEmptyStringToEmptyObject_keylayout(v)]); - } - } - }); - return Object.fromEntries(e); - } else { - return data; - } - } - /** * Replace: * ```json @@ -344,8 +305,6 @@ export class KeymanXMLReader { let result = parser.parse(data, true); if (PARSER_OPTIONS[this.type].attributeNamePrefix === '$') { result = KeymanXMLReader.fixupDollarAttributes(result); - } else if (PARSER_OPTIONS[this.type].attributeNamePrefix === '@_') { - result = KeymanXMLReader.fixupEmptyStringToEmptyObject_keylayout(result); } else if (PARSER_OPTIONS[this.type].attributeNamePrefix === '@__') { result = KeymanXMLReader.fixupEmptyStringToEmptyObject(result); } else if (PARSER_OPTIONS[this.type].preserveOrder) { diff --git a/developer/src/kmc-convert/src/converter-messages.ts b/developer/src/kmc-convert/src/converter-messages.ts index 05bfec1ea37..d26f7e20707 100644 --- a/developer/src/kmc-convert/src/converter-messages.ts +++ b/developer/src/kmc-convert/src/converter-messages.ts @@ -18,13 +18,11 @@ const SevError = CompilerErrorSeverity.Error | Namespace; export class ConverterMessages { static ERROR_OutputFilenameIsRequired = SevError | 0x0001; static Error_OutputFilenameIsRequired = () => m( - this.ERROR_OutputFilenameIsRequired, - `An output filename is required for keyboard conversion.`); + this.ERROR_OutputFilenameIsRequired, `An output filename is required for keyboard conversion.`); static ERROR_NoConverterFound = SevError | 0x0002; static Error_NoConverterFound = (o: { inputFilename: string, outputFilename: string; }) => m( - this.ERROR_NoConverterFound, - `No converter is available that can convert from '${def(o.inputFilename)}' to '${def(o.outputFilename)}'.`); + this.ERROR_NoConverterFound, `No converter is available that can convert from '${def(o.inputFilename)}' to '${def(o.outputFilename)}'.`); static ERROR_FileNotFound = SevError | 0x0003; static Error_FileNotFound = (o: { inputFilename: string; }) => @@ -32,31 +30,26 @@ export class ConverterMessages { static ERROR_UnableToRead = SevError | 0x0004; static Error_UnableToRead = (o: { inputFilename: string; }) => m( - this.ERROR_UnableToRead, `Input file '${def(o.inputFilename)} - ' could not be read.`); + this.ERROR_UnableToRead, `Input file '${def(o.inputFilename)} ' could not be read.`); static ERROR_UnableToConvert = SevError | 0x0005; static Error_UnableToConvert = (o: { inputFilename: string; }) => m( - this.ERROR_UnableToConvert, `Input file '${def(o.inputFilename)} - ' could not be converted.`); + this.ERROR_UnableToConvert, `Input file '${def(o.inputFilename)} ' could not be converted.`); static ERROR_UnableToWrite = SevError | 0x0006; static Error_UnableToWrite = (o: { outputFilename: string; }) => m( - this.ERROR_UnableToWrite, `Output file for '${def(o.outputFilename)} - ' could not be written.`); + this.ERROR_UnableToWrite, `Output file for '${def(o.outputFilename)} ' could not be written.`); static ERROR_UnsupportedCharactersDetected = SevError | 0x0007; static Error_UnsupportedCharactersDetected = (o: { inputFilename: string, keymap_index: string, key: string, output: string; }) => m( this.ERROR_UnsupportedCharactersDetected, `Input file ${def(o.inputFilename)} contains unsupported character ('${def(o.output)}') on key (${def(o.key)}) at keyMap index ${def(o.keymap_index)}`); - // from SRL static ERROR_InvalidFile = SevError | 0x0008; - static Error_InvalidFile = (o:{errorText: string}) => - m(this.ERROR_InvalidFile, `The source file has an invalid structure: ${def(o.errorText)}`); + static Error_InvalidFile = (o: { errorText: string; }) => m( + this.ERROR_InvalidFile, `The source file has an invalid structure: ${def(o.errorText)}`); - // from SRL static ERROR_SchemaValidationError = SevError | 0x009; - static Error_SchemaValidationError = (o:{instancePath:string, keyword:string, message: string, params: string}) => m(this.ERROR_SchemaValidationError, - `!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Error validating Keylayout XML file: ${def(o.instancePath)}: ${def(o.keyword)}: ${def(o.message)} ${def(o.params)}`); + static Error_SchemaValidationError = (o: { instancePath: string, keyword: string, message: string, params: string; }) => m( + this.ERROR_SchemaValidationError, `Error validating Keylayout XML file: ${def(o.instancePath === "" ? "keyboard" : o.instancePath)} : ${def(o.keyword)}: ${def(o.message)} ${def(o.params)}`); - } +} diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts index 0ffddb0e80b..c1f7df1afd3 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts @@ -12,17 +12,13 @@ import { XMLParser } from 'fast-xml-parser'; import { util } from '@keymanapp/common-types'; import { ConverterMessages } from '../converter-messages.js'; import { SchemaValidators } from '@keymanapp/common-types'; - -// _S2 which folder should keylayout-xml.js live?? import { KeylayoutXMLSourceFile } from '../../../common/web/utils/src/types/keylayout/keylayout-xml.js'; - import boxXmlArray = util.boxXmlArray; export class KeylayoutFileReader { constructor(private callbacks: CompilerCallbacks /*,private options: CompilerOptions*/) { }; - /** * @returns true if valid, false if invalid */ @@ -46,6 +42,28 @@ export class KeylayoutFileReader { return true; } + /** + * If object contains attribute #text it will be removed. + * @param o Object with possible property #text + * @return objects that do not contain property #text + */ + public remove_whitespace(o: any): void { + if (o['#text']) { + delete o['#text']; + } + } + + /** + * @brief wrapper to remove whitespace and box single-entry objects into arrays + * @param o Object with property to box/remove whitespace from + * @param x Name of element to box + * @return objects that contain only boxed arrays + */ + public removeWhitespace_boxArray(o: any, x: string): void { + + this.remove_whitespace(o); + boxXmlArray(o, x); + } /** * @brief member function to box single-entry objects into arrays @@ -54,38 +72,39 @@ export class KeylayoutFileReader { */ public boxArray(source: any) { - boxXmlArray(source.layouts, 'layout'); + this.remove_whitespace(source); + + this.removeWhitespace_boxArray(source.layouts, 'layout'); - //_S2 todo do not use remove_text in util.ts!! - boxXmlArray(source?.modifierMap, 'keyMapSelect'); + this.removeWhitespace_boxArray(source?.modifierMap, 'keyMapSelect'); for (const keyMapSelect of source?.modifierMap?.keyMapSelect) { - boxXmlArray(keyMapSelect, 'modifier'); + this.removeWhitespace_boxArray(keyMapSelect, 'modifier'); } + // keyMapSet is the only top level tag that might occur several times => we need to consider 2 cases if (!Array.isArray(source?.keyMapSet) === false) { for (let i = 0; i < source?.keyMapSet.length; i++) { for (const keyMap of source?.keyMapSet[i]?.keyMap) { - boxXmlArray(keyMap, 'key'); + this.removeWhitespace_boxArray(keyMap, 'key'); } - boxXmlArray(source.keyMapSet[i], 'keyMap'); + this.removeWhitespace_boxArray(source.keyMapSet[i], 'keyMap'); } } else { for (const keyMap of source?.keyMapSet?.keyMap) { - boxXmlArray(keyMap, 'key'); + this.removeWhitespace_boxArray(keyMap, 'key'); } - boxXmlArray(source.keyMapSet, 'keyMap'); - // keyMapSet is the only top level tag that might occur several times - boxXmlArray(source, 'keyMapSet'); + this.removeWhitespace_boxArray(source.keyMapSet, 'keyMap'); + this.removeWhitespace_boxArray(source, 'keyMapSet'); } - boxXmlArray(source?.actions, 'action'); + this.removeWhitespace_boxArray(source?.actions, 'action'); for (const action of source?.actions?.action) { - boxXmlArray(action, 'when'); + this.removeWhitespace_boxArray(action, 'when'); } - boxXmlArray(source.terminators, 'when'); + this.removeWhitespace_boxArray(source.terminators, 'when'); for (const action of source?.actions?.action) { - boxXmlArray(action, 'when'); + this.removeWhitespace_boxArray(action, 'when'); } return source; @@ -93,15 +112,15 @@ export class KeylayoutFileReader { /** * @brief member function to parse data from a .keylayout-file and store to a json object - * @param absolutefilename the ukelele .keylayout-file to be parsed + * we need to be able to ignore an output character of "", process an output character of " " (space) and allow surrounding whitespace in #text (which will be removed later) + * @param inputFilename the ukelele .keylayout-file to be parsed * @return in case of success: json object containing data of the .keylayout file; else null */ public read(inputFilename: string): KeylayoutXMLSourceFile { const options = { - ignoreAttributes: [''], - trimValues: false, // we do not trim values because if we do we cannot process an output character of " " (whitespace) - textNodeName: "#_text", // #_text will be added for textnodes and will be removed later ( in remove_text() in boxXmlArray + ignoreAttributes: [''], // we do not process an output character of "" + trimValues: false, // we do not trim values because if we do we cannot process an output character of " " (space) parseTagValue: false, attributeNamePrefix: '@_', // to access the attribute ignoreDeclaration: true @@ -120,5 +139,3 @@ export class KeylayoutFileReader { } } } - - diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 385a7b9640b..d08725ca214 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -12,9 +12,6 @@ import { ConverterToKmnArtifacts } from "../converter-artifacts.js"; import { KmnFileWriter } from './kmn-file-writer.js'; import { KeylayoutFileReader } from './keylayout-file-reader.js'; import { ConverterMessages } from '../converter-messages.js'; - - -// _S2 which folder should keylayout-xml.js live?? import { KeylayoutXMLSourceFile } from '../../../common/web/utils/src/types/keylayout/keylayout-xml.js'; export interface convert_object { @@ -59,10 +56,6 @@ export class KeylayoutToKmnConverter { const KeylayoutReader = new KeylayoutFileReader(this.callbacks/*, this.options*/); const jsonO: KeylayoutXMLSourceFile = KeylayoutReader.read(inputFilename); - - // to check if it works: validate file with stevens schema file ------------------------------------------------- - - console.log("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ I will validate ", inputFilename, "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); try { if (!KeylayoutReader.validate(jsonO)) { return null; @@ -71,8 +64,6 @@ export class KeylayoutToKmnConverter { this.callbacks.reportMessage(ConverterMessages.Error_InvalidFile({ errorText: e.toString() })); return null; } - // to check if it works: validate file with stevens schema file ------------------------------------------------- - if (!jsonO) { this.callbacks.reportMessage(ConverterMessages.Error_UnableToRead({ inputFilename })); @@ -95,18 +86,6 @@ export class KeylayoutToKmnConverter { return null; } - /*const out_Uint8: Uint8Array = kmnFileWriter.writeToUint8Array(outArray); - if (!out_Uint8) { - this.callbacks.reportMessage(ConverterMessages.Error_UnableToWrite({ inputFilename })); - return null; - }*/ - - /*const out_str: string = kmnFileWriter.writeToString(outArray); - if (!out_str) { - this.callbacks.reportMessage(ConverterMessages.Error_UnableToWrite({ inputFilename })); - return null; - }*/ - return null; } diff --git a/resources/standards-data/keylayout/create_keylayout_schema.sh b/resources/standards-data/keylayout/create_keylayout_schema.sh index 84ee163a3fe..2214885e153 100644 --- a/resources/standards-data/keylayout/create_keylayout_schema.sh +++ b/resources/standards-data/keylayout/create_keylayout_schema.sh @@ -34,10 +34,6 @@ do builder_echo debug "${xsd} -> ${json}" (cd .. ; npx -p jgexml xsd2json ${THIS_SCRIPT_PATH}/"${xsd}" ${THIS_SCRIPT_PATH}/"${json}") || exit - #builder_echo debug 'fixup-schema.js' "${json}" - # old ldml: node ../fixup-schema.js "${json}" || builder_die "failed to fixup schema ${json}" - node fixup-keylayout-schema.js "${json}" || builder_die "failed to fixup schema ${json}" - mv "${json}" tmp.json # reformat with prettier(JQ) ${JQ} . -S < tmp.json > "${json}" || (rm tmp.json ; builder_die "failed to transform final schema ${json}") diff --git a/resources/standards-data/keylayout/dtd/keylayout.xsd b/resources/standards-data/keylayout/dtd/keylayout.xsd index 4b2cc977166..675ebd601ba 100644 --- a/resources/standards-data/keylayout/dtd/keylayout.xsd +++ b/resources/standards-data/keylayout/dtd/keylayout.xsd @@ -99,7 +99,6 @@ - From 6d850f971021b7b0f7cc857f4426261b9dfad3af Mon Sep 17 00:00:00 2001 From: Sabine Date: Mon, 7 Jul 2025 11:47:28 +0200 Subject: [PATCH 128/251] feat(developer): remove fixup-keylayout-schema --- .../test/keylayout-to-kmn-converter.tests.ts | 39 ------------------- .../keylayout/fixup-keylayout-schema.js | 39 ------------------- .../keylayout/keylayout.schema.json | 6 +-- 3 files changed, 1 insertion(+), 83 deletions(-) delete mode 100644 resources/standards-data/keylayout/fixup-keylayout-schema.js diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index c8943f48241..d196efe11e2 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -21,45 +21,6 @@ describe('KeylayoutToKmnConverter', function () { compilerTestCallbacks.clear(); }); - // todo remove - describe('RunOneFile', function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const inputFilename = makePathToFixture('../data/Test.keylayout'); - sut.run(inputFilename); - assert.isTrue(true); - }); - - // todo remove - describe('RunOneFile', function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const inputFilename = makePathToFixture('../data/Italian.keylayout'); - sut.run(inputFilename); - assert.isTrue(true); - }); - - // todo remove - describe('RunAllFiles', function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - [ - [makePathToFixture('../data/Italian.keylayout')], - [makePathToFixture('../data/Italian_command.keylayout')], - [makePathToFixture('../data/Swiss_French.keylayout')], - [makePathToFixture('../data/Spanish.keylayout')], - [makePathToFixture('../data/Swiss_German.keylayout')], - [makePathToFixture('../data/US.keylayout')], - [makePathToFixture('../data/Polish.keylayout')], - [makePathToFixture('../data/French.keylayout')], - [makePathToFixture('../data/Latin_American.keylayout')], - //[makePathToFixture('../data/German_complete.keylayout')], - [makePathToFixture('../data/German_complete_reduced.keylayout')], - // [makePathToFixture('../data/German_Standard.keylayout')], - ].forEach(function (files_) { - sut.run(files_[0]); - assert.isTrue(true); - }); - }); - - describe('run() ', function () { // _S2 can I do this??? - some tests of the run() function might take longer than 2000 ms diff --git a/resources/standards-data/keylayout/fixup-keylayout-schema.js b/resources/standards-data/keylayout/fixup-keylayout-schema.js deleted file mode 100644 index d7e8076660b..00000000000 --- a/resources/standards-data/keylayout/fixup-keylayout-schema.js +++ /dev/null @@ -1,39 +0,0 @@ -/* - Copyright: © SIL International. - Description: Fix up schema from xsd2js - Create Date: 2 June 2025 - Authors: Sabine Schmitt - Copied and altered from SRL´s : resources\standards-data\ldml-keyboards\fixup-schema.js -*/ - -const { strict } = require('assert'); -const { readFileSync, writeFileSync } = require('fs'); -const { argv } = require('process'); - -// Read stuff -const input = readFileSync(argv[2] || 0, "utf-8"); -const data = JSON.parse(input); - -// _S2 do I need this func & replace .xds´s type??? -/** - * Turn a schema node from a singleton of some type into an array of that type - * @param {Object} o - */ -/*function singleToArray(o) { - if (!o) return; - if (!o.type) { - o.items = { "$ref": o["$ref"] }; - o.type = "array"; - delete o["$ref"]; - } -} - -if (data.title.endsWith('keylayout.xsd')) { - if (data?.properties?.keyboard) { - data.properties.keyboard.type = 'object'; - } -}*/ - -// Write stuff -const outstr = JSON.stringify(data, null, " "); -writeFileSync(argv[2] || 1, outstr, "utf-8"); diff --git a/resources/standards-data/keylayout/keylayout.schema.json b/resources/standards-data/keylayout/keylayout.schema.json index 1e67065fa9d..e40580308d4 100644 --- a/resources/standards-data/keylayout/keylayout.schema.json +++ b/resources/standards-data/keylayout/keylayout.schema.json @@ -5,9 +5,6 @@ "keyboard": { "additionalProperties": false, "properties": { - "#_text": { - "type": "string" - }, "@_group": { "type": "string" }, @@ -228,8 +225,7 @@ "keyMapSet", "actions", "terminators" - ], - "type": "object" + ] } }, "required": [ From 952dba6a2f7404455ec1e4f314d63f98ea974411 Mon Sep 17 00:00:00 2001 From: Sabine Date: Mon, 7 Jul 2025 14:33:08 +0200 Subject: [PATCH 129/251] feat(developer): remove linebreak in Errormessages --- .../src/kmc-convert/src/converter-messages.ts | 17 ++++++----------- .../keylayout-to-kmn-converter.ts | 8 ++++---- 2 files changed, 10 insertions(+), 15 deletions(-) diff --git a/developer/src/kmc-convert/src/converter-messages.ts b/developer/src/kmc-convert/src/converter-messages.ts index 8e2e60aee1e..42b3bb825e0 100644 --- a/developer/src/kmc-convert/src/converter-messages.ts +++ b/developer/src/kmc-convert/src/converter-messages.ts @@ -23,31 +23,26 @@ export class ConverterMessages { static ERROR_NoConverterFound = SevError | 0x0002; static Error_NoConverterFound = (o: { inputFilename: string, outputFilename: string; }) => m( - this.ERROR_NoConverterFound, - `No converter is available that can convert from '${def(o.inputFilename)}' to '${def(o.outputFilename)}'.`); + this.ERROR_NoConverterFound, `No converter is available that can convert from '${def(o.inputFilename)}' to '${def(o.outputFilename)}'.`); static ERROR_FileNotFound = SevError | 0x0003; static Error_FileNotFound = (o: { inputFilename: string; }) => m( - this.ERROR_FileNotFound, `Input filename '${def(o.inputFilename)} - ' does not exist or could not be loaded.`); + this.ERROR_FileNotFound, `Input filename '${def(o.inputFilename)} ' does not exist or could not be loaded.`); static ERROR_UnableToRead = SevError | 0x0004; static Error_UnableToRead = (o: { inputFilename: string; }) => m( - this.ERROR_UnableToRead, `Input file '${def(o.inputFilename)} - ' could not be read.`); + this.ERROR_UnableToRead, `Input file '${def(o.inputFilename)} ' could not be read.`); static ERROR_UnableToConvert = SevError | 0x0005; static Error_UnableToConvert = (o: { inputFilename: string; }) => m( - this.ERROR_UnableToConvert, `Input file '${def(o.inputFilename)} - ' could not be converted.`); + this.ERROR_UnableToConvert, `Input file '${def(o.inputFilename)} ' could not be converted.`); static ERROR_UnableToWrite = SevError | 0x0006; static Error_UnableToWrite = (o: { outputFilename: string; }) => m( - this.ERROR_UnableToWrite, `Output file for '${def(o.outputFilename)} - ' could not be written.`); + this.ERROR_UnableToWrite, `Output file for '${def(o.outputFilename)} ' could not be written.`); static ERROR_UnsupportedCharactersDetected = SevError | 0x0007; static Error_UnsupportedCharactersDetected = (o: { inputFilename: string, keymap_index: string, key: string, output: string; }) => m( this.ERROR_UnsupportedCharactersDetected, `Input file ${def(o.inputFilename)} contains unsupported character ('${def(o.output)}') on key (${def(o.key)}) at keyMap index ${def(o.keymap_index)}`); - } +} diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 3f3784a8a25..0dd61ae9966 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -63,12 +63,13 @@ export class KeylayoutToKmnConverter { */ async run(inputFilename: string, outputFilename?: string): Promise { - if (!inputFilename) { this.callbacks.reportMessage(ConverterMessages.Error_FileNotFound({ inputFilename })); return null; } + outputFilename = outputFilename ?? inputFilename.replace(/\.keylayout$/, '.kmn'); + const KeylayoutReader = new KeylayoutFileReader(this.callbacks/*, this.options*/); const jsonO: object = KeylayoutReader.read(inputFilename); if (!jsonO) { @@ -87,12 +88,11 @@ export class KeylayoutToKmnConverter { // _S2 still write to file - may be removed later const out_text_ok: boolean = kmnFileWriter.write(outArray); if (!out_text_ok) { - this.callbacks.reportMessage(ConverterMessages.Error_UnableToWrite({ inputFilename })); + this.callbacks.reportMessage(ConverterMessages.Error_UnableToWrite({ outputFilename })); return null; } // write to object/ConverterToKmnResult - outputFilename = outputFilename ?? inputFilename.replace(/\.keylayout$/, '.kmn'); const out_Uint8: Uint8Array = kmnFileWriter.writeToUint8Array(outArray); const Result_toBeReturned: ConverterToKmnResult = { artifacts: { @@ -133,7 +133,7 @@ export class KeylayoutToKmnConverter { data_object.arrayOf_Rules = rules; // _S2 ToDo remove this console.log - console.log("RUN kmc convert - input file: ",data_object.keylayout_filename, " --> output file: ", data_object.kmn_filename); + console.log("RUN kmc convert - input file: ", data_object.keylayout_filename, " --> output file: ", data_object.kmn_filename); // create an array of modifier combinations and store in data_object for (let j = 0; j < jsonObj.keyboard.modifierMap.keyMapSelect.length; j++) { From 16696496c47aeb7802220c3640df2acbd9e7f8a3 Mon Sep 17 00:00:00 2001 From: Sabine Date: Mon, 7 Jul 2025 19:48:19 +0200 Subject: [PATCH 130/251] feat(developer): include create_schems.sh and configure in build.sh --- developer/src/kmc-convert/build.sh | 17 +++++++++++++++++ .../keylayout-to-kmn/keylayout-file-reader.ts | 3 --- .../test/keylayout-to-kmn-converter.tests.ts | 2 -- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/developer/src/kmc-convert/build.sh b/developer/src/kmc-convert/build.sh index 0ebfa2adca8..45c38580559 100755 --- a/developer/src/kmc-convert/build.sh +++ b/developer/src/kmc-convert/build.sh @@ -29,11 +29,27 @@ builder_parse "$@" #------------------------------------------------------------------------------------------------------------------- +do_kmc_convert_test() { + + builder_echo heading "Creating keylayout.schema.JSON" + cd $KEYMAN_ROOT/resources/standards-data/keylayout/ + ./create_keylayout_schema.sh + + builder_echo heading "Creating keylayout.schema.validator" + cd $KEYMAN_ROOT/common/web/types + ./build.sh configure + + builder_echo heading "Starting kmc-convert test" + cd $KEYMAN_ROOT/developer/src/kmc-convert +} + builder_run_action clean rm -rf ./build/ ./tsconfig.tsbuildinfo builder_run_action configure verify_npm_setup builder_run_action build tsc --build builder_run_action api api-extractor run --local --verbose +builder_run_action test do_kmc_convert_test + do_test() { eslint . cd test @@ -47,3 +63,4 @@ do_test() { builder_run_action test do_test builder_run_action publish builder_publish_npm + diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts index c1f7df1afd3..667520a2473 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts @@ -24,11 +24,8 @@ export class KeylayoutFileReader { */ public validate(source: KeylayoutXMLSourceFile): boolean { - console.log("SchemaValidators.default.keylayout(source) ", SchemaValidators.default.keylayout(source)); if (!SchemaValidators.default.keylayout(source)) { - console.log("SchemaValidators.default.keylayout).errors ", (SchemaValidators.default.keylayout).errors); - for (const err of (SchemaValidators.default.keylayout).errors) { this.callbacks.reportMessage(ConverterMessages.Error_SchemaValidationError({ instancePath: err.instancePath, diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index d196efe11e2..bb8249b7a56 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -58,7 +58,6 @@ describe('KeylayoutToKmnConverter', function () { assert.isNotNull(result); assert.equal(compilerTestCallbacks.messages.length, 2); assert.deepEqual(compilerTestCallbacks.messages[0], ConverterMessages.Error_FileNotFound({ inputFilename: inputFilename })); - assert.deepEqual(compilerTestCallbacks.messages[1], ConverterMessages.Error_UnableToRead({ inputFilename: inputFilename })); }); it('run() should return on correct input file name and empty output file name ', async function () { @@ -84,7 +83,6 @@ describe('KeylayoutToKmnConverter', function () { assert.isNotNull(result); assert.equal(compilerTestCallbacks.messages.length, 2); assert.deepEqual(compilerTestCallbacks.messages[0], ConverterMessages.Error_FileNotFound({ inputFilename: inputFilename })); - assert.deepEqual(compilerTestCallbacks.messages[1], ConverterMessages.Error_UnableToRead({ inputFilename: inputFilename })); }); it('run() return on correct input file extention and unsupperted output file extention', async function () { From 59cf3a00d1cc4cc32dfa231738de3943bde64af5 Mon Sep 17 00:00:00 2001 From: Sabine Date: Tue, 8 Jul 2025 09:07:58 +0200 Subject: [PATCH 131/251] feat(developer): changes in makePathToFixture in tests --- .../test/keylayout-to-kmn-converter.tests.ts | 39 ++++++++++--------- .../kmc-convert/test/kmn-file-reader.tests.ts | 6 +-- .../kmc-convert/test/kmn-file-writer.tests.ts | 20 +++++----- 3 files changed, 33 insertions(+), 32 deletions(-) diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index d196efe11e2..6d604660f99 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -53,7 +53,8 @@ describe('KeylayoutToKmnConverter', function () { }); it('run() should throw on unavailable input file name and null output file name', async function () { - const inputFilename = makePathToFixture('../data/Unavailable.keylayout'); + const inputFilename = makePathToFixture('../' + 'data' + '/Unavailable.keylayout'); + const result = sut.run(inputFilename, null); assert.isNotNull(result); assert.equal(compilerTestCallbacks.messages.length, 2); @@ -62,24 +63,24 @@ describe('KeylayoutToKmnConverter', function () { }); it('run() should return on correct input file name and empty output file name ', async function () { - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); await NodeAssert.doesNotReject(async () => sut.run(inputFilename, '')); }); it('run() should return on correct input file name and null output file name', async function () { - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); await NodeAssert.doesNotReject(async () => sut.run(inputFilename, null)); }); it('run() should return on correct input file name and given output file name ', async function () { - const inputFilename = makePathToFixture('../data/Test.keylayout'); - const outputFilename = makePathToFixture('../data/OutputName.kmn'); + const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); + const outputFilename = makePathToFixture('../' + 'data' + '/OutputName.kmn'); await NodeAssert.doesNotReject(async () => sut.run(inputFilename, outputFilename)); }); it('run() should throw on incorrect input file extention and output file extention', async function () { - const inputFilename = makePathToFixture('../data/Test_command.A'); - const outputFilename = makePathToFixture('../data/data/OutputXName.B'); + const inputFilename = makePathToFixture('../' + 'data' + '/Test_command.A'); + const outputFilename = makePathToFixture('../' + 'data' + '/data/OutputXName.B'); const result = sut.run(inputFilename, outputFilename); assert.isNotNull(result); assert.equal(compilerTestCallbacks.messages.length, 2); @@ -88,8 +89,8 @@ describe('KeylayoutToKmnConverter', function () { }); it('run() return on correct input file extention and unsupperted output file extention', async function () { - const inputFilename = makePathToFixture('../data/Test.keylayout'); - const outputFilename = makePathToFixture('../data/OutputXName.B'); + const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); + const outputFilename = makePathToFixture('../' + 'data' + '/OutputXName.B'); await NodeAssert.doesNotReject(async () => sut.run(inputFilename, outputFilename)); }); }); @@ -97,7 +98,7 @@ describe('KeylayoutToKmnConverter', function () { describe('convert() ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); const read = sut_r.read(inputFilename); const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); @@ -258,7 +259,7 @@ describe('KeylayoutToKmnConverter', function () { describe('get_Modifier_array__From__KeyModifier_array ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); const read = sut_r.read(inputFilename); const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); @@ -294,7 +295,7 @@ describe('KeylayoutToKmnConverter', function () { describe('get_KeyModifier_array__From__ActionID ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); const read = sut_r.read(inputFilename); [ @@ -327,7 +328,7 @@ describe('KeylayoutToKmnConverter', function () { describe('get_ActionID__From__ActionNext ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); const read = sut_r.read(inputFilename); [ @@ -360,7 +361,7 @@ describe('KeylayoutToKmnConverter', function () { describe('get_ActionIndex__From__ActionId ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); const read = sut_r.read(inputFilename); [ @@ -388,7 +389,7 @@ describe('KeylayoutToKmnConverter', function () { describe('get_Output__From__ActionId_None ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); const read = sut_r.read(inputFilename); [ @@ -421,7 +422,7 @@ describe('KeylayoutToKmnConverter', function () { describe('get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); const read = sut_r.read(inputFilename); /*Italian: @@ -607,7 +608,7 @@ describe('KeylayoutToKmnConverter', function () { describe('get_ActionStateOutput_array__From__ActionState ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); const read = sut_r.read(inputFilename); /* @@ -679,7 +680,7 @@ describe('KeylayoutToKmnConverter', function () { describe('get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); const read = sut_r.read(inputFilename); const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); /* Italian: [ @@ -737,7 +738,7 @@ describe('KeylayoutToKmnConverter', function () { describe('get_KeyActionOutput_array__From__ActionStateOutput_array ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); const read = sut_r.read(inputFilename); /* Italian: const b6_actionId_arr = [ diff --git a/developer/src/kmc-convert/test/kmn-file-reader.tests.ts b/developer/src/kmc-convert/test/kmn-file-reader.tests.ts index c6bdcca108c..99ca1171065 100644 --- a/developer/src/kmc-convert/test/kmn-file-reader.tests.ts +++ b/developer/src/kmc-convert/test/kmn-file-reader.tests.ts @@ -25,7 +25,7 @@ describe('KeylayoutFileReader', function () { const sut_r = new KeylayoutFileReader(compilerTestCallbacks); it('read() should return filled array on correct input', async function () { - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); const result = sut_r.read(inputFilename); assert.isNotEmpty(result); }); @@ -46,13 +46,13 @@ describe('KeylayoutFileReader', function () { }); it('read() should return empty array on unavailable file name', async function () { - const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); + const inputFilename_unavailable = makePathToFixture('../' + 'data' + '/X.keylayout'); const result = sut_r.read(inputFilename_unavailable); assert.isNull(result); }); it('read() should return empty array on typo in path', async function () { - const result = sut_r.read(makePathToFixture('../data|Test.keylayout')); + const result = sut_r.read(makePathToFixture('../' + 'data' + '|Test.keylayout')); assert.isNull(result); }); }); diff --git a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts index 17c810ed1a1..ef5b8521ca5 100644 --- a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts +++ b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts @@ -23,7 +23,7 @@ describe('KmnFileWriter', function () { }); describe("write() ", function () { - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); @@ -31,7 +31,7 @@ describe('KmnFileWriter', function () { const converted = sut.convert_bound.convert(read, '/Test.keylayout'.replace(/\.keylayout$/, '.kmn')); // empty convert_object from unavailable file name - const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); + const inputFilename_unavailable = makePathToFixture('../' + 'data' + '/X.keylayout'); const read_unavailable = sut_r.read(inputFilename_unavailable); const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); @@ -49,7 +49,7 @@ describe('KmnFileWriter', function () { }); describe("writeToString() ", function () { - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); @@ -72,7 +72,7 @@ describe('KmnFileWriter', function () { + "\n"; // empty convert_object from unavailable file name - //const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); + //const inputFilename_unavailable = makePathToFixture('../' + 'data' + '/X.keylayout'); const inputFilename_unavailable = '/X.keylayout'; const read_unavailable = sut_r.read(inputFilename_unavailable); const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); @@ -89,7 +89,7 @@ describe('KmnFileWriter', function () { }); describe("writeToUint8Array() ", function () { - //const inputFilename = makePathToFixture('../data/Test.keylayout'); + //const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); const inputFilename = '/Test.keylayout'; const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); @@ -115,7 +115,7 @@ describe('KmnFileWriter', function () { // empty convert_object from unavailable file name - const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); + const inputFilename_unavailable = makePathToFixture('../' + 'data' + '/X.keylayout'); const read_unavailable = sut_r.read(inputFilename_unavailable); const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); it('writeToUint8Array() should return header in case of missing inputfile', async function () { @@ -130,7 +130,7 @@ describe('KmnFileWriter', function () { }); describe("writeData_Rules() ", function () { - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); @@ -138,7 +138,7 @@ describe('KmnFileWriter', function () { const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); // empty convert_object from unavailable file name - const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); + const inputFilename_unavailable = makePathToFixture('../' + 'data' + '/X.keylayout'); const read_unavailable = sut_r.read(inputFilename_unavailable); const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); @@ -158,12 +158,12 @@ describe('KmnFileWriter', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); const read = sut_r.read(inputFilename); const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); // empty convert_object from unavailable file name - const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); + const inputFilename_unavailable = makePathToFixture('../' + 'data' + '/X.keylayout'); const read_unavailable = sut_r.read(inputFilename_unavailable); const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); From 979d74887d6b36b98675e848f5aa32b38bb4cb69 Mon Sep 17 00:00:00 2001 From: Sabine Date: Tue, 8 Jul 2025 11:35:02 +0200 Subject: [PATCH 132/251] feat(developer): failing test write(): convert() use correct filepath --- .../test/keylayout-to-kmn-converter.tests.ts | 206 +----------------- .../kmc-convert/test/kmn-file-reader.tests.ts | 2 - .../kmc-convert/test/kmn-file-writer.tests.ts | 9 +- 3 files changed, 7 insertions(+), 210 deletions(-) diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index 6d604660f99..cfb42889c8e 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -54,7 +54,6 @@ describe('KeylayoutToKmnConverter', function () { it('run() should throw on unavailable input file name and null output file name', async function () { const inputFilename = makePathToFixture('../' + 'data' + '/Unavailable.keylayout'); - const result = sut.run(inputFilename, null); assert.isNotNull(result); assert.equal(compilerTestCallbacks.messages.length, 2); @@ -102,12 +101,12 @@ describe('KeylayoutToKmnConverter', function () { const read = sut_r.read(inputFilename); const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); - // empty convert_object from unavailable file name - const inputFilename_unavailable = makePathToFixture('X.keylayout'); + // convert_object from unavailable file name + const inputFilename_unavailable = makePathToFixture('../' + 'data' + '/X.keylayout'); const read_unavailable = sut_r.read(inputFilename_unavailable); const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); - // empty convert_object from empty filename + // convert_object from empty filename const inputFilename_empty = makePathToFixture(''); const read_empty = sut_r.read(inputFilename_empty); const converted_empty = sut.convert_bound.convert(read_empty, inputFilename_empty.replace(/\.keylayout$/, '.kmn')); @@ -265,7 +264,6 @@ describe('KeylayoutToKmnConverter', function () { [ [[['0', 0]], [['', 'shift? caps? ']]], - // Italian: [[['0', 1]], [['anyShift caps?', 'shift? rightShift caps? ', 'shift? leftShift caps? ', 'shift leftShift caps ']]], [[['0', 2]], [['shift? leftShift caps? ', 'anyShift caps?', 'shift leftShift caps ', 'shift? rightShift caps? ']]], [[['0', 999]], [null]], [[['999',]], [null]], @@ -299,13 +297,9 @@ describe('KeylayoutToKmnConverter', function () { const read = sut_r.read(inputFilename); [ - // Italian: ['a16', [['32', 3]]], - // Italian: ['a19', [['45', 3]]], - // Italian: ['a18', [['24', 0], ['24', 3]]], ['A_16', [['32', 5]]], ['A_19', [['45', 5]]], ['A_18', [['24', 0], ['24', 5]]], - ['unknown', []], [undefined, []], [null, []], @@ -333,17 +327,11 @@ describe('KeylayoutToKmnConverter', function () { [ ['none', ''], - // Italian: ['a18', ''], ['0', ''], - // Italian: ['1', 'a16'], - // Italian: // Italian: ['2', 'a8'], - // Italian: ['3', 'a17'], - ['A_18', ''], ['1', 'A_16'], ['2', 'A_8'], ['3', 'A_17'], - ['', ''], [' ', ''], ['99', ''], @@ -366,9 +354,6 @@ describe('KeylayoutToKmnConverter', function () { [ ['none', 0], - // Italian: ['a16', 8], - // Italian: ['a18', 10], - // Italian: ['a19', 11], ['A_16', 8], ['A_18', 10], ['A_19', 11], @@ -393,11 +378,9 @@ describe('KeylayoutToKmnConverter', function () { const read = sut_r.read(inputFilename); [ - // Italian: ['a14', 'u'], ['A_14', 'u'], ['', ''], [' ', ''], - // Italian: ['a18', undefined], ['A_18', undefined], ['unknown', ''], ].forEach(function (values) { @@ -424,74 +407,6 @@ describe('KeylayoutToKmnConverter', function () { const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); const read = sut_r.read(inputFilename); - /*Italian: - - const b1_keycode_arr = [ - ['49', 'K_SPACE', 'a0', '0', 'ˆ'], - ['49', 'K_SPACE', 'a0', '1', 'ˆ'], - ['49', 'K_SPACE', 'a0', '2', 'ˆ'], - ['6', 'K_Z', 'a0', '4', 'ˆ'], - ['25', 'K_9', 'a0', '4', 'ˆ'], - ['43', 'K_COMMA', 'a0', '4', 'ˆ'], - ['49', 'K_SPACE', 'a0', '7', 'ˆ'], - ['0', 'K_A', 'a1', '1', 'Â'], - ['0', 'K_A', 'a1', '2', 'Â'], - ['14', 'K_E', 'a10', '0', 'ê'], - ['34', 'K_I', 'a11', '0', 'î'], - ['31', 'K_O', 'a13', '0', 'ô'], - ['32', 'K_U', 'a14', '0', 'û'], - ['14', 'K_E', 'a2', '1', 'Ê'], - ['14', 'K_E', 'a2', '2', 'Ê'], - ['34', 'K_I', 'a3', '1', 'Î'], - ['34', 'K_I', 'a3', '2', 'Î'], - ['31', 'K_O', 'a5', '1', 'Ô'], - ['31', 'K_O', 'a5', '2', 'Ô'], - ['32', 'K_U', 'a6', '1', 'Û'], - ['32', 'K_U', 'a6', '2', 'Û'], - ['0', 'K_A', 'a9', '0', 'â'] - ]; - const b1_modifierKey_arr = [ - ['K_SPACE', 'a0', '0', 'NCAPS', 'ˆ'], - ['K_SPACE', 'a0', '1', 'NCAPS SHIFT', 'ˆ'], - ['K_SPACE', 'a0', '1', 'SHIFT CAPS', 'ˆ'], - ['K_SPACE', 'a0', '2', 'CAPS', 'ˆ'], - ['K_Z', 'a0', '4', 'NCAPS SHIFT RALT', 'ˆ'], - ['K_9', 'a0', '4', 'NCAPS SHIFT RALT', 'ˆ'], - ['K_COMMA', 'a0', '4', 'NCAPS SHIFT RALT', 'ˆ'], - ['K_SPACE', 'a0', '7', 'NCAPS CTRL', 'ˆ'], - ['K_SPACE', 'a0', '7', 'NCAPS RALT CTRL', 'ˆ'], - ['K_A', 'a1', '1', 'NCAPS SHIFT', 'Â'], - ['K_A', 'a1', '1', 'SHIFT CAPS', 'Â'], - ['K_A', 'a1', '2', 'CAPS', 'Â'], - ['K_E', 'a10', '0', 'NCAPS', 'ê'], - ['K_I', 'a11', '0', 'NCAPS', 'î'], - ['K_O', 'a13', '0', 'NCAPS', 'ô'], - ['K_U', 'a14', '0', 'NCAPS', 'û'], - ['K_E', 'a2', '1', 'NCAPS SHIFT', 'Ê'], - ['K_E', 'a2', '1', 'SHIFT CAPS', 'Ê'], - ['K_E', 'a2', '2', 'CAPS', 'Ê'], - ['K_I', 'a3', '1', 'NCAPS SHIFT', 'Î'], - ['K_I', 'a3', '1', 'SHIFT CAPS', 'Î'], - ['K_I', 'a3', '2', 'CAPS', 'Î'], - ['K_O', 'a5', '1', 'NCAPS SHIFT', 'Ô'], - ['K_O', 'a5', '1', 'SHIFT CAPS', 'Ô'], - ['K_O', 'a5', '2', 'CAPS', 'Ô'], - ['K_U', 'a6', '1', 'NCAPS SHIFT', 'Û'], - ['K_U', 'a6', '1', 'SHIFT CAPS', 'Û'], - ['K_U', 'a6', '2', 'CAPS', 'Û'], - ['K_A', 'a9', '0', 'NCAPS', 'â'] - ]; - - [[b1_keycode_arr, b1_modifierKey_arr], - [[['49', 'K_SPACE', 'a0', '0', 'ˆ']], [['K_SPACE', 'a0', '0', 'NCAPS', 'ˆ']]], - [[['49', 'K_SPACE', 'a0', '0', '']], [['K_SPACE', 'a0', '0', 'NCAPS', '']]], - [[['49', 'K_SPACE', 'a0', '', 'ˆ']], [['K_SPACE', 'a0', '', 'NCAPS', 'ˆ']]], - [[['49', 'K_SPACE', '', '0', 'ˆ']], [['K_SPACE', '', '0', 'NCAPS', 'ˆ']]], - [[['49', '', 'a0', '0', 'ˆ']], [['', 'a0', '0', 'NCAPS', 'ˆ']]], - [[['', 'K_SPACE', 'a0', '0', 'ˆ']], [['K_SPACE', 'a0', '0', 'NCAPS', 'ˆ']]], - [[['', 'K_SPACE', 'a0', '0', 'ˆ']], [['K_SPACE', 'a0', '0', 'NCAPS', 'ˆ']]], - [[['', '', '', '', '']], [['', '', '', 'NCAPS', '']]], - */ const b1_keycode_arr = [ ['49', 'K_SPACE', 'A_0', '0', 'ˆ'], @@ -571,12 +486,6 @@ describe('KeylayoutToKmnConverter', function () { }); }); - /* Italian: [[[['49', 'K_SPACE', 'a0', '0', 'ˆ']], [['K_SPACE', 'a0', '0', '', 'ˆ']]], - [[['49', 'K_SPACE', 'a0', '0', '']], [['K_SPACE', 'a0', '0', '', '']]], - [[['', 'K_SPACE', 'a0', '0', 'ˆ']], [['K_SPACE', 'a0', '0', '', 'ˆ']]], - [[['', '', '', '', '']], [['', '', '', '', '']]], - ].forEach(function (values) { */ - [[[['49', 'K_SPACE', 'A_0', '0', 'ˆ']], [['K_SPACE', 'A_0', '0', '', 'ˆ']]], [[['49', 'K_SPACE', 'A_0', '0', '']], [['K_SPACE', 'A_0', '0', '', '']]], [[['', 'K_SPACE', 'A_0', '0', 'ˆ']], [['K_SPACE', 'A_0', '0', '', 'ˆ']]], @@ -611,32 +520,6 @@ describe('KeylayoutToKmnConverter', function () { const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); const read = sut_r.read(inputFilename); - /* - Italian:[['1', [ - ['a0', '1', 'ˆ'], - ['a1', '1', 'Â'], - ['a10', '1', 'ê'], - ['a11', '1', 'î'], - ['a13', '1', 'ô'], - ['a14', '1', 'û'], - ['a2', '1', 'Ê'], - ['a3', '1', 'Î'], - ['a5', '1', 'Ô'], - ['a6', '1', 'Û'], - ['a9', '1', 'â']],], - ['2', [ - ['a0', '2', '`'], - ['a1', '2', 'À'], - ['a10', '2', 'è'], - ['a11', '2', 'ì'], - ['a13', '2', 'ò'], - ['a14', '2', 'ù'], - ['a2', '2', 'È'], - ['a3', '2', 'Ì'], - ['a5', '2', 'Ò'], - ['a6', '2', 'Ù'], - ['a9', '2', 'à']],], - */ [['1', [ ['A_0', '1', 'ˆ'], ['A_1', '1', 'Â'], @@ -683,26 +566,6 @@ describe('KeylayoutToKmnConverter', function () { const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); const read = sut_r.read(inputFilename); const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); - /* Italian: [ - ['a1', 'A', true, [ - ['a1', 'A', 'a1', '1', 'K_A', 'NCAPS SHIFT'], - ['a1', 'A', 'a1', '1', 'K_A', 'SHIFT CAPS'], - ['a1', 'A', 'a1', '2', 'K_A', 'CAPS']] - ], - ['a1', 'A', false, [ - ['a1', 'A', 'a1', '1', 'K_A', 'SHIFT'], - ['a1', 'A', 'a1', '1', 'K_A', 'SHIFT CAPS'], - ['a1', 'A', 'a1', '2', 'K_A', 'CAPS']] - ], - ['a9', 'a', true, [['a9', 'a', 'a9', '0', 'K_A', 'NCAPS']]], - ['a9', 'a', false, [['a9', 'a', 'a9', '0', 'K_A', '']]], - ['a9', 'a', , [['a9', 'a', 'a9', '0', 'K_A', '']]], - ['a9', '', true, [['a9', '', 'a9', '0', 'K_A', 'NCAPS']]], - ['a9', '', false, [['a9', '', 'a9', '0', 'K_A', '']]], - ['', 'a', true, []], - ['', 'a', false, []], - ['', '', , []], - */ [ ['A_1', 'A', true, [ @@ -741,44 +604,6 @@ describe('KeylayoutToKmnConverter', function () { const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); const read = sut_r.read(inputFilename); - /* Italian: const b6_actionId_arr = [ - ['a0', '1', 'ˆ'], - ['a1', '1', 'Â'], - ['a10', '1', 'ê'], - ['a11', '1', 'î'], - ['a13', '1', 'ô'], - ['a14', '1', 'û'], - ['a2', '1', 'Ê'], - ['a3', '1', 'Î'], - ['a5', '1', 'Ô'], - ['a6', '1', 'Û'], - ['a9', '1', 'â'] - ]; - const b1_keycode_arr = [ - ['49', 'K_SPACE', 'a0', '0', 'ˆ'], - ['49', 'K_SPACE', 'a0', '1', 'ˆ'], - ['49', 'K_SPACE', 'a0', '2', 'ˆ'], - ['6', 'K_Z', 'a0', '4', 'ˆ'], - ['25', 'K_9', 'a0', '4', 'ˆ'], - ['43', 'K_COMMA', 'a0', '4', 'ˆ'], - ['49', 'K_SPACE', 'a0', '7', 'ˆ'], - ['0', 'K_A', 'a1', '1', 'Â'], - ['0', 'K_A', 'a1', '2', 'Â'], - ['14', 'K_E', 'a10', '0', 'ê'], - ['34', 'K_I', 'a11', '0', 'î'], - ['31', 'K_O', 'a13', '0', 'ô'], - ['32', 'K_U', 'a14', '0', 'û'], - ['14', 'K_E', 'a2', '1', 'Ê'], - ['14', 'K_E', 'a2', '2', 'Ê'], - ['34', 'K_I', 'a3', '1', 'Î'], - ['34', 'K_I', 'a3', '2', 'Î'], - ['31', 'K_O', 'a5', '1', 'Ô'], - ['31', 'K_O', 'a5', '2', 'Ô'], - ['32', 'K_U', 'a6', '1', 'Û'], - ['32', 'K_U', 'a6', '2', 'Û'], - ['0', 'K_A', 'a9', '0', 'â'] - ]; - */ const b6_actionId_arr = [ ['A_0', '1', 'ˆ'], ['A_1', '1', 'Â'], @@ -793,8 +618,6 @@ describe('KeylayoutToKmnConverter', function () { ['A_9', '1', 'â'] ]; const b1_keycode_arr = [ - - ['49', 'K_SPACE', 'A_0', '0', 'ˆ'], ['49', 'K_SPACE', 'A_0', '1', 'ˆ'], ['49', 'K_SPACE', 'A_0', '2', 'ˆ'], @@ -828,27 +651,6 @@ describe('KeylayoutToKmnConverter', function () { }); }); - //----------------- - /* Italian: const oneEntryResult = [ - ['49', 'K_SPACE', 'a0', '0', 'ˆ'], - ['49', 'K_SPACE', 'a0', '1', 'ˆ'], - ['49', 'K_SPACE', 'a0', '2', 'ˆ'], - ['6', 'K_Z', 'a0', '4', 'ˆ'], - ['25', 'K_9', 'a0', '4', 'ˆ'], - ['43', 'K_COMMA', 'a0', '4', 'ˆ'], - ['49', 'K_SPACE', 'a0', '7', 'ˆ'] - ]; - const oneEntryResultNoOutput = [ - ['49', 'K_SPACE', 'a0', '0', ''], - ['49', 'K_SPACE', 'a0', '1', ''], - ['49', 'K_SPACE', 'a0', '2', ''], - ['6', 'K_Z', 'a0', '4', ''], - ['25', 'K_9', 'a0', '4', ''], - ['43', 'K_COMMA', 'a0', '4', ''], - ['49', 'K_SPACE', 'a0', '7', ''] - ] ; - */ - const oneEntryResult = [ ['49', 'K_SPACE', 'A_0', '0', 'ˆ'], ['49', 'K_SPACE', 'A_0', '1', 'ˆ'], @@ -878,7 +680,6 @@ describe('KeylayoutToKmnConverter', function () { }); }); - //------------------------------------------------------------------------------------- [[[['', '1', 'ˆ']], []], [[['', '', '']], []], [[[' ', ' ', '']], []], @@ -889,7 +690,6 @@ describe('KeylayoutToKmnConverter', function () { }); }); - //------------------------------------------------------------------------------------- [[[], []], [undefined, []], [null, []], diff --git a/developer/src/kmc-convert/test/kmn-file-reader.tests.ts b/developer/src/kmc-convert/test/kmn-file-reader.tests.ts index 99ca1171065..60fe42c2f5d 100644 --- a/developer/src/kmc-convert/test/kmn-file-reader.tests.ts +++ b/developer/src/kmc-convert/test/kmn-file-reader.tests.ts @@ -12,8 +12,6 @@ import { assert } from 'chai'; import { compilerTestCallbacks, makePathToFixture } from './helpers/index.js'; import { KeylayoutFileReader } from '../src/keylayout-to-kmn/keylayout-file-reader.js'; -//----------------------------------------------------------------------------------------------------------------------- - describe('KeylayoutFileReader', function () { before(function () { diff --git a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts index ef5b8521ca5..6f005771b0b 100644 --- a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts +++ b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts @@ -28,7 +28,8 @@ describe('KmnFileWriter', function () { const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); const read = sut_r.read(inputFilename); - const converted = sut.convert_bound.convert(read, '/Test.keylayout'.replace(/\.keylayout$/, '.kmn')); + const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); + // empty convert_object from unavailable file name const inputFilename_unavailable = makePathToFixture('../' + 'data' + '/X.keylayout'); @@ -72,8 +73,7 @@ describe('KmnFileWriter', function () { + "\n"; // empty convert_object from unavailable file name - //const inputFilename_unavailable = makePathToFixture('../' + 'data' + '/X.keylayout'); - const inputFilename_unavailable = '/X.keylayout'; + const inputFilename_unavailable = makePathToFixture('../' + 'data' + '/X.keylayout'); const read_unavailable = sut_r.read(inputFilename_unavailable); const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); @@ -89,8 +89,7 @@ describe('KmnFileWriter', function () { }); describe("writeToUint8Array() ", function () { - //const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); - const inputFilename = '/Test.keylayout'; + const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); From 042a6a53f77336c0eb35bf7b4b57f2b84114e82e Mon Sep 17 00:00:00 2001 From: Sabine Date: Tue, 8 Jul 2025 12:21:03 +0200 Subject: [PATCH 133/251] feat(developer): adapt path in makePathToFixture --- .../test/keylayout-to-kmn-converter.tests.ts | 77 +++++-------------- .../kmc-convert/test/kmn-file-reader.tests.ts | 8 +- .../kmc-convert/test/kmn-file-writer.tests.ts | 22 +++--- 3 files changed, 32 insertions(+), 75 deletions(-) diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index bb8249b7a56..dec04980178 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -53,7 +53,7 @@ describe('KeylayoutToKmnConverter', function () { }); it('run() should throw on unavailable input file name and null output file name', async function () { - const inputFilename = makePathToFixture('../data/Unavailable.keylayout'); + const inputFilename = makePathToFixture('../' + 'data' + '/Unavailable.keylayout'); const result = sut.run(inputFilename, null); assert.isNotNull(result); assert.equal(compilerTestCallbacks.messages.length, 2); @@ -61,24 +61,24 @@ describe('KeylayoutToKmnConverter', function () { }); it('run() should return on correct input file name and empty output file name ', async function () { - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); await NodeAssert.doesNotReject(async () => sut.run(inputFilename, '')); }); it('run() should return on correct input file name and null output file name', async function () { - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); await NodeAssert.doesNotReject(async () => sut.run(inputFilename, null)); }); it('run() should return on correct input file name and given output file name ', async function () { - const inputFilename = makePathToFixture('../data/Test.keylayout'); - const outputFilename = makePathToFixture('../data/OutputName.kmn'); + const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); + const outputFilename = makePathToFixture('../' + 'data' + '/OutputName.kmn'); await NodeAssert.doesNotReject(async () => sut.run(inputFilename, outputFilename)); }); it('run() should throw on incorrect input file extention and output file extention', async function () { - const inputFilename = makePathToFixture('../data/Test_command.A'); - const outputFilename = makePathToFixture('../data/data/OutputXName.B'); + const inputFilename = makePathToFixture('../' + 'data' + '/Test_command.A'); + const outputFilename = makePathToFixture('../' + 'data' + '/data/OutputXName.B'); const result = sut.run(inputFilename, outputFilename); assert.isNotNull(result); assert.equal(compilerTestCallbacks.messages.length, 2); @@ -86,8 +86,8 @@ describe('KeylayoutToKmnConverter', function () { }); it('run() return on correct input file extention and unsupperted output file extention', async function () { - const inputFilename = makePathToFixture('../data/Test.keylayout'); - const outputFilename = makePathToFixture('../data/OutputXName.B'); + const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); + const outputFilename = makePathToFixture('../' + 'data' + '/OutputXName.B'); await NodeAssert.doesNotReject(async () => sut.run(inputFilename, outputFilename)); }); }); @@ -95,7 +95,7 @@ describe('KeylayoutToKmnConverter', function () { describe('convert() ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); const read = sut_r.read(inputFilename); const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); @@ -256,13 +256,12 @@ describe('KeylayoutToKmnConverter', function () { describe('get_Modifier_array__From__KeyModifier_array ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); const read = sut_r.read(inputFilename); const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); [ [[['0', 0]], [['', 'shift? caps? ']]], - // Italian: [[['0', 1]], [['anyShift caps?', 'shift? rightShift caps? ', 'shift? leftShift caps? ', 'shift leftShift caps ']]], [[['0', 2]], [['shift? leftShift caps? ', 'anyShift caps?', 'shift leftShift caps ', 'shift? rightShift caps? ']]], [[['0', 999]], [null]], [[['999',]], [null]], @@ -292,17 +291,13 @@ describe('KeylayoutToKmnConverter', function () { describe('get_KeyModifier_array__From__ActionID ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); const read = sut_r.read(inputFilename); [ - // Italian: ['a16', [['32', 3]]], - // Italian: ['a19', [['45', 3]]], - // Italian: ['a18', [['24', 0], ['24', 3]]], ['A_16', [['32', 5]]], ['A_19', [['45', 5]]], ['A_18', [['24', 0], ['24', 5]]], - ['unknown', []], [undefined, []], [null, []], @@ -325,22 +320,16 @@ describe('KeylayoutToKmnConverter', function () { describe('get_ActionID__From__ActionNext ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); const read = sut_r.read(inputFilename); [ ['none', ''], - // Italian: ['a18', ''], ['0', ''], - // Italian: ['1', 'a16'], - // Italian: // Italian: ['2', 'a8'], - // Italian: ['3', 'a17'], - ['A_18', ''], ['1', 'A_16'], ['2', 'A_8'], ['3', 'A_17'], - ['', ''], [' ', ''], ['99', ''], @@ -358,14 +347,11 @@ describe('KeylayoutToKmnConverter', function () { describe('get_ActionIndex__From__ActionId ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); const read = sut_r.read(inputFilename); [ ['none', 0], - // Italian: ['a16', 8], - // Italian: ['a18', 10], - // Italian: ['a19', 11], ['A_16', 8], ['A_18', 10], ['A_19', 11], @@ -386,15 +372,13 @@ describe('KeylayoutToKmnConverter', function () { describe('get_Output__From__ActionId_None ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); const read = sut_r.read(inputFilename); [ - // Italian: ['a14', 'u'], ['A_14', 'u'], ['', ''], [' ', ''], - // Italian: ['a18', undefined], ['A_18', undefined], ['unknown', ''], ].forEach(function (values) { @@ -419,7 +403,7 @@ describe('KeylayoutToKmnConverter', function () { describe('get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); const read = sut_r.read(inputFilename); /*Italian: @@ -605,7 +589,7 @@ describe('KeylayoutToKmnConverter', function () { describe('get_ActionStateOutput_array__From__ActionState ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); const read = sut_r.read(inputFilename); /* @@ -677,7 +661,7 @@ describe('KeylayoutToKmnConverter', function () { describe('get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); const read = sut_r.read(inputFilename); const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); /* Italian: [ @@ -735,7 +719,7 @@ describe('KeylayoutToKmnConverter', function () { describe('get_KeyActionOutput_array__From__ActionStateOutput_array ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); const read = sut_r.read(inputFilename); /* Italian: const b6_actionId_arr = [ @@ -825,27 +809,6 @@ describe('KeylayoutToKmnConverter', function () { }); }); - //----------------- - /* Italian: const oneEntryResult = [ - ['49', 'K_SPACE', 'a0', '0', 'ˆ'], - ['49', 'K_SPACE', 'a0', '1', 'ˆ'], - ['49', 'K_SPACE', 'a0', '2', 'ˆ'], - ['6', 'K_Z', 'a0', '4', 'ˆ'], - ['25', 'K_9', 'a0', '4', 'ˆ'], - ['43', 'K_COMMA', 'a0', '4', 'ˆ'], - ['49', 'K_SPACE', 'a0', '7', 'ˆ'] - ]; - const oneEntryResultNoOutput = [ - ['49', 'K_SPACE', 'a0', '0', ''], - ['49', 'K_SPACE', 'a0', '1', ''], - ['49', 'K_SPACE', 'a0', '2', ''], - ['6', 'K_Z', 'a0', '4', ''], - ['25', 'K_9', 'a0', '4', ''], - ['43', 'K_COMMA', 'a0', '4', ''], - ['49', 'K_SPACE', 'a0', '7', ''] - ] ; - */ - const oneEntryResult = [ ['49', 'K_SPACE', 'A_0', '0', 'ˆ'], ['49', 'K_SPACE', 'A_0', '1', 'ˆ'], @@ -875,7 +838,6 @@ describe('KeylayoutToKmnConverter', function () { }); }); - //------------------------------------------------------------------------------------- [[[['', '1', 'ˆ']], []], [[['', '', '']], []], [[[' ', ' ', '']], []], @@ -886,7 +848,6 @@ describe('KeylayoutToKmnConverter', function () { }); }); - //------------------------------------------------------------------------------------- [[[], []], [undefined, []], [null, []], diff --git a/developer/src/kmc-convert/test/kmn-file-reader.tests.ts b/developer/src/kmc-convert/test/kmn-file-reader.tests.ts index c6bdcca108c..1725c83ed56 100644 --- a/developer/src/kmc-convert/test/kmn-file-reader.tests.ts +++ b/developer/src/kmc-convert/test/kmn-file-reader.tests.ts @@ -12,8 +12,6 @@ import { assert } from 'chai'; import { compilerTestCallbacks, makePathToFixture } from './helpers/index.js'; import { KeylayoutFileReader } from '../src/keylayout-to-kmn/keylayout-file-reader.js'; -//----------------------------------------------------------------------------------------------------------------------- - describe('KeylayoutFileReader', function () { before(function () { @@ -25,7 +23,7 @@ describe('KeylayoutFileReader', function () { const sut_r = new KeylayoutFileReader(compilerTestCallbacks); it('read() should return filled array on correct input', async function () { - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); const result = sut_r.read(inputFilename); assert.isNotEmpty(result); }); @@ -46,13 +44,13 @@ describe('KeylayoutFileReader', function () { }); it('read() should return empty array on unavailable file name', async function () { - const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); + const inputFilename_unavailable = makePathToFixture('../' + 'data' + '/X.keylayout'); const result = sut_r.read(inputFilename_unavailable); assert.isNull(result); }); it('read() should return empty array on typo in path', async function () { - const result = sut_r.read(makePathToFixture('../data|Test.keylayout')); + const result = sut_r.read( makePathToFixture('../' + 'data' + '|Test.keylayout')); assert.isNull(result); }); }); diff --git a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts index 17c810ed1a1..bf229e08c7e 100644 --- a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts +++ b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts @@ -23,15 +23,15 @@ describe('KmnFileWriter', function () { }); describe("write() ", function () { - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); const read = sut_r.read(inputFilename); - const converted = sut.convert_bound.convert(read, '/Test.keylayout'.replace(/\.keylayout$/, '.kmn')); + const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); // empty convert_object from unavailable file name - const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); + const inputFilename_unavailable = makePathToFixture('../' + 'data' + '/X.keylayout'); const read_unavailable = sut_r.read(inputFilename_unavailable); const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); @@ -49,7 +49,7 @@ describe('KmnFileWriter', function () { }); describe("writeToString() ", function () { - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); @@ -72,7 +72,6 @@ describe('KmnFileWriter', function () { + "\n"; // empty convert_object from unavailable file name - //const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); const inputFilename_unavailable = '/X.keylayout'; const read_unavailable = sut_r.read(inputFilename_unavailable); const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); @@ -89,8 +88,7 @@ describe('KmnFileWriter', function () { }); describe("writeToUint8Array() ", function () { - //const inputFilename = makePathToFixture('../data/Test.keylayout'); - const inputFilename = '/Test.keylayout'; + const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); @@ -115,7 +113,7 @@ describe('KmnFileWriter', function () { // empty convert_object from unavailable file name - const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); + const inputFilename_unavailable = makePathToFixture('../' + 'data' + '/X.keylayout'); const read_unavailable = sut_r.read(inputFilename_unavailable); const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); it('writeToUint8Array() should return header in case of missing inputfile', async function () { @@ -130,7 +128,7 @@ describe('KmnFileWriter', function () { }); describe("writeData_Rules() ", function () { - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); @@ -138,7 +136,7 @@ describe('KmnFileWriter', function () { const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); // empty convert_object from unavailable file name - const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); + const inputFilename_unavailable = makePathToFixture('../' + 'data' + '/X.keylayout'); const read_unavailable = sut_r.read(inputFilename_unavailable); const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); @@ -158,12 +156,12 @@ describe('KmnFileWriter', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); const read = sut_r.read(inputFilename); const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); // empty convert_object from unavailable file name - const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); + const inputFilename_unavailable = makePathToFixture('../' + 'data' + '/X.keylayout'); const read_unavailable = sut_r.read(inputFilename_unavailable); const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); From a81a3f820e7f9f0dfd0dc23937a63e3943dce768 Mon Sep 17 00:00:00 2001 From: Sabine Date: Tue, 8 Jul 2025 13:56:55 +0200 Subject: [PATCH 134/251] feat(developer): remove line --- .../src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts index 8fdeb377a18..6f73aa47b46 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts @@ -76,7 +76,6 @@ export class KmnFileWriter { } } - /** * @brief member function to create data for stores that will be printed to the resulting kmn file * @param data_ukelele an object containing all data read from a .keylayout file From 461717808db9a1a32fa7d992b85512b3e0cd3e10 Mon Sep 17 00:00:00 2001 From: Sabine Date: Tue, 8 Jul 2025 15:37:27 +0200 Subject: [PATCH 135/251] feat(developer): version with broken schema.bundler --- common/web/types/package.json | 4 +- .../src/common/web/utils/src/xml-utils.ts | 76 +++++++++++++++++++ developer/src/kmc-convert/build.sh | 5 +- package-lock.json | 51 +++++++++++-- package.json | 4 +- .../keylayout/create_keylayout_schema.sh | 4 + 6 files changed, 129 insertions(+), 15 deletions(-) diff --git a/common/web/types/package.json b/common/web/types/package.json index 0bfda5f4edd..2ab86cf03ce 100644 --- a/common/web/types/package.json +++ b/common/web/types/package.json @@ -31,14 +31,14 @@ "url": "https://github.com/keymanapp/keyman/issues" }, "dependencies": { - "@keymanapp/ldml-keyboard-constants": "*", "@keymanapp/keyman-version": "*", + "@keymanapp/ldml-keyboard-constants": "*", "restructure": "3.0.1" }, "devDependencies": { "@types/mocha": "^5.2.7", "@types/node": "^20.4.1", - "ajv": "^8.12.0", + "ajv": "^8.17.1", "ajv-cli": "^5.0.0", "ajv-formats": "^2.1.1", "c8": "^7.12.0", diff --git a/developer/src/common/web/utils/src/xml-utils.ts b/developer/src/common/web/utils/src/xml-utils.ts index 5bfc01ca07e..2134b9cf78d 100644 --- a/developer/src/common/web/utils/src/xml-utils.ts +++ b/developer/src/common/web/utils/src/xml-utils.ts @@ -239,6 +239,43 @@ export class KeymanXMLReader { } } + + /** + * Requires attribute prefix @_ (double underscore) + * For attributes, just remove @_ and continue. + * For objects, replace any empty string "" with an empty object {} */ + private static fixupEmptyStringToEmptyObject_keylayout(data: any) : any { + + if (typeof data === 'object') { + // For arrays of objects, we map "" to {} + // "" means an empty object + if (Array.isArray(data)) { + return data.map(v => { + if (v === '') { + return {}; + } else { + return KeymanXMLReader.fixupEmptyStringToEmptyObject_keylayout(v); + } + }); + } + // otherwise: remove @_ for attributes, remap objects + const e: any = []; + Object.entries(data).forEach(([k, v]) => { + if (k.startsWith('@_')) { + e.push([k.substring(3), KeymanXMLReader.fixupEmptyStringToEmptyObject_keylayout(v)]); + } else { + if (v === '') { + e.push([k, {}]); + } else { + e.push([k, KeymanXMLReader.fixupEmptyStringToEmptyObject_keylayout(v)]); + } + } + }); + return Object.fromEntries(e); + } else { + return data; + } + } /** * Replace: * ```json @@ -305,6 +342,8 @@ export class KeymanXMLReader { let result = parser.parse(data, true); if (PARSER_OPTIONS[this.type].attributeNamePrefix === '$') { result = KeymanXMLReader.fixupDollarAttributes(result); + } else if (PARSER_OPTIONS[this.type].attributeNamePrefix === '@_') { + result = KeymanXMLReader.fixupEmptyStringToEmptyObject_keylayout(result); } else if (PARSER_OPTIONS[this.type].attributeNamePrefix === '@__') { result = KeymanXMLReader.fixupEmptyStringToEmptyObject(result); } else if (PARSER_OPTIONS[this.type].preserveOrder) { @@ -376,3 +415,40 @@ export class KeymanXMLWriter { } } + +/** + * traverse an AJV instancePath and map to an object if possible + * @param source object tree root (contains the root object) + * @param path ajv split instancePath, such as '/keyboard3/layers/0'.split('/') + * @returns undefined if the path was not present, null if path went to something that wasn't an object, otherwise the compileContext object is returned. + */ +export function findInstanceObject(source: any, path: string[]) : any { + if(!path || !source || path.length == 0) { + return source; + } else if(path[0] == '') { + return findInstanceObject(source, path.slice(1)); + } else if(Array.isArray(source) || typeof source == 'object') { + const child = source[path[0]]; + if (child == undefined) return child; // nothing here + if (!child || typeof child == 'string') { + return source; // return the *parent* object if the child is empty (could be a property) + } + return findInstanceObject(child, path.slice(1)); + } else { + return null; + } +} +/** + * Return an object simulating an XML object with an offset number + * For use in calling message functions + * @param c number for the offset setting + * @param x if set, this object will be used as the base object instead of {} + */ +export function withOffset(c: number, compileContext?: any) : KeymanXMLMetadata { + // set metadata on an empty object + const o = Object.assign({}, compileContext); + KeymanXMLReader.setMetaData(o, { + startIndex: c + }); + return o; +} \ No newline at end of file diff --git a/developer/src/kmc-convert/build.sh b/developer/src/kmc-convert/build.sh index 45c38580559..78531000e5d 100755 --- a/developer/src/kmc-convert/build.sh +++ b/developer/src/kmc-convert/build.sh @@ -32,7 +32,7 @@ builder_parse "$@" do_kmc_convert_test() { builder_echo heading "Creating keylayout.schema.JSON" - cd $KEYMAN_ROOT/resources/standards-data/keylayout/ + cd $KEYMAN_ROOT/resources/standards-data/keylayout ./create_keylayout_schema.sh builder_echo heading "Creating keylayout.schema.validator" @@ -48,8 +48,6 @@ builder_run_action configure verify_npm_setup builder_run_action build tsc --build builder_run_action api api-extractor run --local --verbose -builder_run_action test do_kmc_convert_test - do_test() { eslint . cd test @@ -61,6 +59,7 @@ do_test() { builder_echo warning "Please increase threshold in build.sh as test coverage improves." } +builder_run_action test do_kmc_convert_test builder_run_action test do_test builder_run_action publish builder_publish_npm diff --git a/package-lock.json b/package-lock.json index 0b952d7fa57..74f8eeaef80 100644 --- a/package-lock.json +++ b/package-lock.json @@ -54,7 +54,7 @@ "@web/dev-server-import-maps": "^0.2.0", "@web/test-runner": "^0.18.1", "@web/test-runner-playwright": "^0.11.0", - "ajv": "^8.12.0", + "ajv": "^8.17.1", "ajv-cli": "^5.0.0", "ajv-formats": "^2.1.1", "chai": "^5.1.0", @@ -154,7 +154,7 @@ "devDependencies": { "@types/mocha": "^5.2.7", "@types/node": "^20.4.1", - "ajv": "^8.12.0", + "ajv": "^8.17.1", "ajv-cli": "^5.0.0", "ajv-formats": "^2.1.1", "c8": "^7.12.0", @@ -2072,6 +2072,23 @@ "string-argv": "~0.3.1" } }, + "node_modules/@microsoft/api-extractor/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, "node_modules/@microsoft/api-extractor/node_modules/ajv-formats": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", @@ -4682,15 +4699,16 @@ } }, "node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "dev": true, + "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.1", + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" + "require-from-string": "^2.0.2" }, "funding": { "type": "github", @@ -7806,6 +7824,23 @@ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, + "node_modules/fast-uri": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz", + "integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, "node_modules/fast-xml-parser": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.2.2.tgz", diff --git a/package.json b/package.json index 1e7b65507c6..5cdef982557 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "@web/dev-server-import-maps": "^0.2.0", "@web/test-runner": "^0.18.1", "@web/test-runner-playwright": "^0.11.0", - "ajv": "^8.12.0", + "ajv": "^8.17.1", "ajv-cli": "^5.0.0", "ajv-formats": "^2.1.1", "chai": "^5.1.0", @@ -62,11 +62,11 @@ ], "dependencies": { "@keymanapp/common-types": "file:common/web/types", - "@keymanapp/langtags": "file:common/web/langtags", "@keymanapp/developer-test-helpers": "file:developer/src/common/web/test-helpers", "@keymanapp/developer-utils": "file:developer/src/common/web/utils", "@keymanapp/hextobin": "file:common/tools/hextobin", "@keymanapp/keyman-version": "file:common/web/keyman-version", + "@keymanapp/langtags": "file:common/web/langtags", "@keymanapp/ldml-keyboard-constants": "file:core/include/ldml" }, "overrides": { diff --git a/resources/standards-data/keylayout/create_keylayout_schema.sh b/resources/standards-data/keylayout/create_keylayout_schema.sh index 2214885e153..123a5f47a0e 100644 --- a/resources/standards-data/keylayout/create_keylayout_schema.sh +++ b/resources/standards-data/keylayout/create_keylayout_schema.sh @@ -34,6 +34,10 @@ do builder_echo debug "${xsd} -> ${json}" (cd .. ; npx -p jgexml xsd2json ${THIS_SCRIPT_PATH}/"${xsd}" ${THIS_SCRIPT_PATH}/"${json}") || exit + #builder_echo debug 'fixup-schema.js' "${json}" + # old ldml: node ../fixup-schema.js "${json}" || builder_die "failed to fixup schema ${json}" + #node fixup-keylayout-schema.js "${json}" || builder_die "failed to fixup schema ${json}" + mv "${json}" tmp.json # reformat with prettier(JQ) ${JQ} . -S < tmp.json > "${json}" || (rm tmp.json ; builder_die "failed to transform final schema ${json}") From 9ecbd58aa7bd149fab8d6b431cae74527df93465 Mon Sep 17 00:00:00 2001 From: Sabine Date: Tue, 8 Jul 2025 16:54:28 +0200 Subject: [PATCH 136/251] feat(developer): add keylayout-xml.ts --- .../src/types/keylayout/keylayout-xml.ts | 374 ++++++++++++++++++ 1 file changed, 374 insertions(+) create mode 100644 developer/src/common/web/utils/src/types/keylayout/keylayout-xml.ts diff --git a/developer/src/common/web/utils/src/types/keylayout/keylayout-xml.ts b/developer/src/common/web/utils/src/types/keylayout/keylayout-xml.ts new file mode 100644 index 00000000000..8b89a330810 --- /dev/null +++ b/developer/src/common/web/utils/src/types/keylayout/keylayout-xml.ts @@ -0,0 +1,374 @@ + + +export interface KeylayoutXMLSourceFile { + /** + * -- the root element. + */ + keyboard: KL_keyboard; +}; +export interface KL_keyboard { + group?: string; + id?: string; + name?: string; + maxoutS?: string; + + layoutsMM: KL_Layouts[]; + layouts?: KL_Layouts[]; + modifierMap?: KL_modifierMap[]; + keyMapSet?: KL_keyMapSet[]; + actions?: KL_actions[]; + terminators?: KL_terminators[]; +}; + +export interface KL_Layouts { + layouts?: KL_Layout; +}; +export interface KL_Layout { + first?: string; + last?: string; + mapSet?: string; + modifiers?: string; +}; + + +export interface KL_modifierMap { + id?: string; + defaultIndex?: string; + + keyMapSelect?: KL_keyMapSelect[]; +}; +export interface KL_keyMapSelect { + mapIndex?: string; + modifier?: KL_modifier[]; +}; +export interface KL_modifier { + keys?: string; +}; + + +export interface KL_keyMapSet { + id?: string; + keyMap?: KL_keyMap[]; +}; +export interface KL_keyMap { + index?: string; + key?: KL_key[]; +}; +export interface KL_key { + code?: string; + action?: string; + output?: string; +}; + + +export interface KL_actions { + action?: KL_action[]; +}; +export interface KL_action { + id?: string; + when?: KL_when[]; +}; +export interface KL_when { + state?: string; + output?: string; + next?: string; +}; + +export interface KL_terminators { + when?: KL_when[]; +}; + + +//-------------------------------------------------------- + +export interface LDMLKeyboardTestDataXMLSourceFile { + /** + * -- the root element. + */ + keyboardTest3: LKTKeyboardTest; // keyboardTest3 is root +} + +export interface LKTKeyboardTest { // ubergeordneter node keyboardTest3 + conformsTo?: string; // keyboardTest3 has attrib? conformsTo + info?: LKTInfo; // keyboardTest3 has tag info, rep, tests + repertoire?: LKTRepertoire[]; + tests?: LKTTests[]; +}; + +export interface LKTInfo { + author?: string; + keyboard?: string; + name?: string; +}; + +export interface LKTRepertoire { + name?: string; + chars?: string; + type?: string; +}; + +export interface LKTTests { // subtag tests has tag ?/attrib? name, test + name?: string; + test?: LKTTest[]; +}; + +export interface LKTTest { // sub-subtag test has tag ?/attrib? name, startContext, actions + name?: string; + startContext?: LKTStartContext; + actions?: LKTAnyAction[]; // differs from XML, to represent order of actions +}; + +/** + * Test Actions. + * The expectation is that each LKTAction object will have exactly one non-falsy field. + */ +export interface LKTAction { + type?: "check" | "emit" | "keystroke" | "backspace"; +}; + +export interface LKTCheck extends LKTAction { + type: "check"; + result?: string; +}; + +export interface LKTEmit extends LKTAction { + type: "emit"; + to?: string; +}; + +export interface LKTKeystroke extends LKTAction { + type: "keystroke"; + key?: string; + flick?: string; + longPress?: string; + tapCount?: string; +}; +export interface LKTStartContext { + to?: string; +}; + +export interface LDMLKeyboardXMLSourceFile { + /** + * -- the root element. + */ + keyboard3: LKKeyboard; +}; + + +export interface LKTBackspace extends LKTAction { + type: "backspace"; +} + +export type LKTAnyAction = LKTCheck | LKTEmit | LKTKeystroke | LKTBackspace; + + + + + + + + + + +export interface LKKeyboard { + locale?: string; + conformsTo?: string; + + locales?: LKLocales; + version?: LKVersion; + info?: LKInfo; + settings?: LKSettings; + keys?: LKKeys; + flicks?: LKFlicks; + forms?: LKForms; + displays?: LKDisplays; + layers?: LKLayers[]; + variables?: LKVariables; + transforms?: LKTransforms[]; +}; + +/** + * This is defined as an interface, but actually is resolved during the reading phase + */ +export interface LKImport { + /** + * import base, currently `cldr` is supported + */ + base?: 'cldr' | ''; + /** + * path to imported resource, of the form `45/*.xml` + */ + path: string; +}; + +export interface LKLocales { + locale: LKLocale[]; +}; + +export interface LKLocale { + id?: string; +}; + +export interface LKVersion { + number: string; // semver string +} + +export interface LKInfo { + name?: string; + author?: string; + layout?: string; + indicator?: string; +}; + +export interface LKSettings { + normalization: "disabled"; +}; + +export interface LKKeys { + key: LKKey[]; + flicks: LKFlicks[]; +}; + +export interface LKKey { + id?: string; + flickId?: string; + output?: string; + gap?: boolean; + layerId?: string; + longPressKeyIds?: string; + longPressDefaultKeyId?: string; + multiTapKeyIds?: string; + width?: number; +}; + +export interface LKFlicks { + flick?: LKFlick[]; +}; + +export interface LKFlick { + id?: string; + flickSegment?: LKFlickSegment[]; +}; + +export interface LKFlickSegment { + directions?: string; + keyId?: string; +} + +export interface LKLayers { + /** + * `touch`, or hardware `us`, `iso`, `jis`, `abnt2` + */ + formId?: string; + /** + * Minimum width in millimeters + */ + minDeviceWidth?: number; + layer?: LKLayer[]; +}; + +export interface LKLayer { + id?: string; + modifiers?: string; + row?: LKRow[]; +}; + +export interface LKRow { + keys?: string; +}; + +export interface LKVariables { + string?: LKString[]; + set?: LKSet[]; + uset?: LKUSet[]; +}; + +/** + * Shared interface for all three variable types + */ +export interface Variable { + id?: string; + value?: string; +}; + +export interface LKString extends Variable { }; +export interface LKSet extends Variable { }; +export interface LKUSet extends Variable { }; + +export interface LKTransforms { + type?: "simple" | "backspace"; + transformGroup?: LKTransformGroup[]; +}; + +export interface LKTransform { + from?: string; + to?: string; +}; + +export interface LKTransformGroup { + // one or the other, not both + transform?: LKTransform[]; + reorder?: LKReorder[]; +}; +export interface LKReorder { + from?: string; + before?: string; + order?: string; + tertiary?: string; + tertiaryBase?: string; + preBase?: string; +}; + +export interface LKDisplayOptions { + baseCharacter?: string; +}; + +export interface LKDisplay { + output?: string; + display?: string; + keyId?: string; +}; + +export interface LKDisplays { + display?: LKDisplay[]; + displayOptions?: LKDisplayOptions; +}; + +export interface LKForms { + form?: LKForm[]; +}; + +export interface LKForm { + id?: string; + scanCodes?: LKScanCodes[]; +}; + +export interface LKScanCodes { + codes?: string; +}; + +/** + * Utilities for determining the import status of items + */ +export class ImportStatus { + /** item came in via implied (spec based) import, such as keys-Latn-implied.xml */ + static impliedImport = Symbol('LDML implied import'); + /** item came in via import */ + static import = Symbol('LDML import'); + /** item came in via local (not CLDR) import */ + static localImport = Symbol('LDML local import'); + + /** @returns true if the object was loaded through an implied import */ + static isImpliedImport(o: any): boolean { + return o && !!o[ImportStatus.impliedImport]; + } + /** @returns true if the object was loaded through an explicit import */ + static isImport(o: any): boolean { + return o && !!o[ImportStatus.import]; + } + /** @returns true if the object was loaded through an explicit import */ + static isLocalImport(o: any): boolean { + return o && !!o[ImportStatus.localImport]; + } +}; + From 761403c782288df67c92be8694603ff832c3e750 Mon Sep 17 00:00:00 2001 From: Sabine Date: Wed, 9 Jul 2025 08:00:55 +0200 Subject: [PATCH 137/251] feat(developer): remove unnecessary code --- .../src/types/keylayout/keylayout-xml.ts | 293 ------------------ .../test/keylayout-to-kmn-converter.tests.ts | 2 +- .../kmc-convert/test/kmn-file-writer.tests.ts | 2 +- 3 files changed, 2 insertions(+), 295 deletions(-) diff --git a/developer/src/common/web/utils/src/types/keylayout/keylayout-xml.ts b/developer/src/common/web/utils/src/types/keylayout/keylayout-xml.ts index 8b89a330810..69c4a849dd8 100644 --- a/developer/src/common/web/utils/src/types/keylayout/keylayout-xml.ts +++ b/developer/src/common/web/utils/src/types/keylayout/keylayout-xml.ts @@ -79,296 +79,3 @@ export interface KL_terminators { }; -//-------------------------------------------------------- - -export interface LDMLKeyboardTestDataXMLSourceFile { - /** - * -- the root element. - */ - keyboardTest3: LKTKeyboardTest; // keyboardTest3 is root -} - -export interface LKTKeyboardTest { // ubergeordneter node keyboardTest3 - conformsTo?: string; // keyboardTest3 has attrib? conformsTo - info?: LKTInfo; // keyboardTest3 has tag info, rep, tests - repertoire?: LKTRepertoire[]; - tests?: LKTTests[]; -}; - -export interface LKTInfo { - author?: string; - keyboard?: string; - name?: string; -}; - -export interface LKTRepertoire { - name?: string; - chars?: string; - type?: string; -}; - -export interface LKTTests { // subtag tests has tag ?/attrib? name, test - name?: string; - test?: LKTTest[]; -}; - -export interface LKTTest { // sub-subtag test has tag ?/attrib? name, startContext, actions - name?: string; - startContext?: LKTStartContext; - actions?: LKTAnyAction[]; // differs from XML, to represent order of actions -}; - -/** - * Test Actions. - * The expectation is that each LKTAction object will have exactly one non-falsy field. - */ -export interface LKTAction { - type?: "check" | "emit" | "keystroke" | "backspace"; -}; - -export interface LKTCheck extends LKTAction { - type: "check"; - result?: string; -}; - -export interface LKTEmit extends LKTAction { - type: "emit"; - to?: string; -}; - -export interface LKTKeystroke extends LKTAction { - type: "keystroke"; - key?: string; - flick?: string; - longPress?: string; - tapCount?: string; -}; -export interface LKTStartContext { - to?: string; -}; - -export interface LDMLKeyboardXMLSourceFile { - /** - * -- the root element. - */ - keyboard3: LKKeyboard; -}; - - -export interface LKTBackspace extends LKTAction { - type: "backspace"; -} - -export type LKTAnyAction = LKTCheck | LKTEmit | LKTKeystroke | LKTBackspace; - - - - - - - - - - -export interface LKKeyboard { - locale?: string; - conformsTo?: string; - - locales?: LKLocales; - version?: LKVersion; - info?: LKInfo; - settings?: LKSettings; - keys?: LKKeys; - flicks?: LKFlicks; - forms?: LKForms; - displays?: LKDisplays; - layers?: LKLayers[]; - variables?: LKVariables; - transforms?: LKTransforms[]; -}; - -/** - * This is defined as an interface, but actually is resolved during the reading phase - */ -export interface LKImport { - /** - * import base, currently `cldr` is supported - */ - base?: 'cldr' | ''; - /** - * path to imported resource, of the form `45/*.xml` - */ - path: string; -}; - -export interface LKLocales { - locale: LKLocale[]; -}; - -export interface LKLocale { - id?: string; -}; - -export interface LKVersion { - number: string; // semver string -} - -export interface LKInfo { - name?: string; - author?: string; - layout?: string; - indicator?: string; -}; - -export interface LKSettings { - normalization: "disabled"; -}; - -export interface LKKeys { - key: LKKey[]; - flicks: LKFlicks[]; -}; - -export interface LKKey { - id?: string; - flickId?: string; - output?: string; - gap?: boolean; - layerId?: string; - longPressKeyIds?: string; - longPressDefaultKeyId?: string; - multiTapKeyIds?: string; - width?: number; -}; - -export interface LKFlicks { - flick?: LKFlick[]; -}; - -export interface LKFlick { - id?: string; - flickSegment?: LKFlickSegment[]; -}; - -export interface LKFlickSegment { - directions?: string; - keyId?: string; -} - -export interface LKLayers { - /** - * `touch`, or hardware `us`, `iso`, `jis`, `abnt2` - */ - formId?: string; - /** - * Minimum width in millimeters - */ - minDeviceWidth?: number; - layer?: LKLayer[]; -}; - -export interface LKLayer { - id?: string; - modifiers?: string; - row?: LKRow[]; -}; - -export interface LKRow { - keys?: string; -}; - -export interface LKVariables { - string?: LKString[]; - set?: LKSet[]; - uset?: LKUSet[]; -}; - -/** - * Shared interface for all three variable types - */ -export interface Variable { - id?: string; - value?: string; -}; - -export interface LKString extends Variable { }; -export interface LKSet extends Variable { }; -export interface LKUSet extends Variable { }; - -export interface LKTransforms { - type?: "simple" | "backspace"; - transformGroup?: LKTransformGroup[]; -}; - -export interface LKTransform { - from?: string; - to?: string; -}; - -export interface LKTransformGroup { - // one or the other, not both - transform?: LKTransform[]; - reorder?: LKReorder[]; -}; -export interface LKReorder { - from?: string; - before?: string; - order?: string; - tertiary?: string; - tertiaryBase?: string; - preBase?: string; -}; - -export interface LKDisplayOptions { - baseCharacter?: string; -}; - -export interface LKDisplay { - output?: string; - display?: string; - keyId?: string; -}; - -export interface LKDisplays { - display?: LKDisplay[]; - displayOptions?: LKDisplayOptions; -}; - -export interface LKForms { - form?: LKForm[]; -}; - -export interface LKForm { - id?: string; - scanCodes?: LKScanCodes[]; -}; - -export interface LKScanCodes { - codes?: string; -}; - -/** - * Utilities for determining the import status of items - */ -export class ImportStatus { - /** item came in via implied (spec based) import, such as keys-Latn-implied.xml */ - static impliedImport = Symbol('LDML implied import'); - /** item came in via import */ - static import = Symbol('LDML import'); - /** item came in via local (not CLDR) import */ - static localImport = Symbol('LDML local import'); - - /** @returns true if the object was loaded through an implied import */ - static isImpliedImport(o: any): boolean { - return o && !!o[ImportStatus.impliedImport]; - } - /** @returns true if the object was loaded through an explicit import */ - static isImport(o: any): boolean { - return o && !!o[ImportStatus.import]; - } - /** @returns true if the object was loaded through an explicit import */ - static isLocalImport(o: any): boolean { - return o && !!o[ImportStatus.localImport]; - } -}; - diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index 002b414d3b4..c37a9e8e8cf 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -107,7 +107,7 @@ describe('KeylayoutToKmnConverter', function () { // convert_object from empty filename const inputFilename_empty = makePathToFixture(''); const read_empty = sut_r.read(inputFilename_empty); - const converted_empty = sut.convert_bound.convert(read_empty, inputFilename_empty.replace(/\.keylayout$/, '.kmn')); + const converted_empty = sut.convert_bound.convert(read_empty, inputFilename_empty); it('should return converted array on correct input', async function () { assert.isTrue(converted.arrayOf_Rules.length !== 0); diff --git a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts index 2a372e7a268..ad350f967fe 100644 --- a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts +++ b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts @@ -168,7 +168,7 @@ describe('KmnFileWriter', function () { // empty convert_object from empty filename const inputFilename_empty = makePathToFixture(''); const read_empty = sut_r.read(inputFilename_empty); - const converted_empty = sut.convert_bound.convert(read_empty, inputFilename_empty.replace(/\.keylayout$/, '.kmn')); + const converted_empty = sut.convert_bound.convert(read_empty, inputFilename_empty); const out_expected_first: string = "c ..................................................................................................................\n" From 5f25f647afff8ef10f81b65be736ae94f3637c52 Mon Sep 17 00:00:00 2001 From: Sabine Date: Wed, 9 Jul 2025 09:49:56 +0200 Subject: [PATCH 138/251] feat(developer): changes in build.sh --- developer/src/kmc-convert/build.sh | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/developer/src/kmc-convert/build.sh b/developer/src/kmc-convert/build.sh index 78531000e5d..7bdba0bbb80 100755 --- a/developer/src/kmc-convert/build.sh +++ b/developer/src/kmc-convert/build.sh @@ -33,14 +33,17 @@ do_kmc_convert_test() { builder_echo heading "Creating keylayout.schema.JSON" cd $KEYMAN_ROOT/resources/standards-data/keylayout - ./create_keylayout_schema.sh + #./create_keylayout_schema.sh + "$KEYMAN_ROOT/resources/standards-data/keylayout/create_keylayout_schema.sh" builder_echo heading "Creating keylayout.schema.validator" cd $KEYMAN_ROOT/common/web/types - ./build.sh configure + #./build.sh configure + # _S2 how would I start configure??? + "$KEYMAN_ROOT/common/web/types/build.sh" builder_echo heading "Starting kmc-convert test" - cd $KEYMAN_ROOT/developer/src/kmc-convert + cd $THIS_SCRIPT_PATH } builder_run_action clean rm -rf ./build/ ./tsconfig.tsbuildinfo From 87d6e07062473de9eb8f6d312994ea63973f1eaf Mon Sep 17 00:00:00 2001 From: Sabine Date: Wed, 9 Jul 2025 13:34:37 +0200 Subject: [PATCH 139/251] feat(developer): change path in makePathToFixture --- .../keylayout-to-kmn-converter.ts | 1 - .../src/keylayout-to-kmn/kmn-file-writer.ts | 6 +- .../test/keylayout-to-kmn-converter.tests.ts | 247 ++---------------- .../kmc-convert/test/kmn-file-reader.tests.ts | 6 +- .../kmc-convert/test/kmn-file-writer.tests.ts | 26 +- 5 files changed, 40 insertions(+), 246 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 0dd61ae9966..fdd14406d88 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -124,7 +124,6 @@ export class KeylayoutToKmnConverter { arrayOf_Rules: [] }; - // ToDo in a new PR: check tags ( issue # 13599) if ((jsonObj !== null) && (jsonObj.hasOwnProperty("keyboard"))) { data_object.keylayout_filename = outputfilename.replace(/\.kmn$/, '.keylayout'); diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts index 8fdeb377a18..705bd7b53ed 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts @@ -37,7 +37,7 @@ export class KmnFileWriter { this.callbacks.fs.writeFileSync(data_ukelele.kmn_filename, new TextEncoder().encode(data)); return true; } catch (err) { - this.callbacks.reportMessage(ConverterMessages.Error_OutputFilenameIsRequired()); + this.callbacks.reportMessage(ConverterMessages.Error_UnableToWrite({outputFilename: data_ukelele.kmn_filename})); return false; } } @@ -54,7 +54,7 @@ export class KmnFileWriter { try { return data; } catch (err) { - this.callbacks.reportMessage(ConverterMessages.Error_OutputFilenameIsRequired()); + this.callbacks.reportMessage(ConverterMessages.Error_UnableToWrite({outputFilename: data_ukelele.kmn_filename})); return null; } } @@ -71,7 +71,7 @@ export class KmnFileWriter { try { return new TextEncoder().encode(data); } catch (err) { - this.callbacks.reportMessage(ConverterMessages.Error_OutputFilenameIsRequired()); + this.callbacks.reportMessage(ConverterMessages.Error_UnableToWrite({outputFilename: data_ukelele.kmn_filename})); return null; } } diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index d196efe11e2..c37a9e8e8cf 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -53,43 +53,41 @@ describe('KeylayoutToKmnConverter', function () { }); it('run() should throw on unavailable input file name and null output file name', async function () { - const inputFilename = makePathToFixture('../data/Unavailable.keylayout'); + const inputFilename = makePathToFixture('../' + 'data' + '/Unavailable.keylayout'); const result = sut.run(inputFilename, null); assert.isNotNull(result); assert.equal(compilerTestCallbacks.messages.length, 2); assert.deepEqual(compilerTestCallbacks.messages[0], ConverterMessages.Error_FileNotFound({ inputFilename: inputFilename })); - assert.deepEqual(compilerTestCallbacks.messages[1], ConverterMessages.Error_UnableToRead({ inputFilename: inputFilename })); }); it('run() should return on correct input file name and empty output file name ', async function () { - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); await NodeAssert.doesNotReject(async () => sut.run(inputFilename, '')); }); it('run() should return on correct input file name and null output file name', async function () { - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); await NodeAssert.doesNotReject(async () => sut.run(inputFilename, null)); }); it('run() should return on correct input file name and given output file name ', async function () { - const inputFilename = makePathToFixture('../data/Test.keylayout'); - const outputFilename = makePathToFixture('../data/OutputName.kmn'); + const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); + const outputFilename = makePathToFixture('../' + 'data' + '/OutputName.kmn'); await NodeAssert.doesNotReject(async () => sut.run(inputFilename, outputFilename)); }); it('run() should throw on incorrect input file extention and output file extention', async function () { - const inputFilename = makePathToFixture('../data/Test_command.A'); - const outputFilename = makePathToFixture('../data/data/OutputXName.B'); + const inputFilename = makePathToFixture('../' + 'data' + '/Test_command.A'); + const outputFilename = makePathToFixture('../' + 'data' + '/data/OutputXName.B'); const result = sut.run(inputFilename, outputFilename); assert.isNotNull(result); assert.equal(compilerTestCallbacks.messages.length, 2); assert.deepEqual(compilerTestCallbacks.messages[0], ConverterMessages.Error_FileNotFound({ inputFilename: inputFilename })); - assert.deepEqual(compilerTestCallbacks.messages[1], ConverterMessages.Error_UnableToRead({ inputFilename: inputFilename })); }); it('run() return on correct input file extention and unsupperted output file extention', async function () { - const inputFilename = makePathToFixture('../data/Test.keylayout'); - const outputFilename = makePathToFixture('../data/OutputXName.B'); + const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); + const outputFilename = makePathToFixture('../' + 'data' + '/OutputXName.B'); await NodeAssert.doesNotReject(async () => sut.run(inputFilename, outputFilename)); }); }); @@ -97,19 +95,19 @@ describe('KeylayoutToKmnConverter', function () { describe('convert() ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); const read = sut_r.read(inputFilename); const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); - // empty convert_object from unavailable file name - const inputFilename_unavailable = makePathToFixture('X.keylayout'); + // convert_object from unavailable file name + const inputFilename_unavailable = makePathToFixture('../' + 'data' + '/X.keylayout'); const read_unavailable = sut_r.read(inputFilename_unavailable); const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); - // empty convert_object from empty filename + // convert_object from empty filename const inputFilename_empty = makePathToFixture(''); const read_empty = sut_r.read(inputFilename_empty); - const converted_empty = sut.convert_bound.convert(read_empty, inputFilename_empty.replace(/\.keylayout$/, '.kmn')); + const converted_empty = sut.convert_bound.convert(read_empty, inputFilename_empty); it('should return converted array on correct input', async function () { assert.isTrue(converted.arrayOf_Rules.length !== 0); @@ -258,13 +256,12 @@ describe('KeylayoutToKmnConverter', function () { describe('get_Modifier_array__From__KeyModifier_array ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); const read = sut_r.read(inputFilename); const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); [ [[['0', 0]], [['', 'shift? caps? ']]], - // Italian: [[['0', 1]], [['anyShift caps?', 'shift? rightShift caps? ', 'shift? leftShift caps? ', 'shift leftShift caps ']]], [[['0', 2]], [['shift? leftShift caps? ', 'anyShift caps?', 'shift leftShift caps ', 'shift? rightShift caps? ']]], [[['0', 999]], [null]], [[['999',]], [null]], @@ -294,17 +291,13 @@ describe('KeylayoutToKmnConverter', function () { describe('get_KeyModifier_array__From__ActionID ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); const read = sut_r.read(inputFilename); [ - // Italian: ['a16', [['32', 3]]], - // Italian: ['a19', [['45', 3]]], - // Italian: ['a18', [['24', 0], ['24', 3]]], ['A_16', [['32', 5]]], ['A_19', [['45', 5]]], ['A_18', [['24', 0], ['24', 5]]], - ['unknown', []], [undefined, []], [null, []], @@ -327,22 +320,16 @@ describe('KeylayoutToKmnConverter', function () { describe('get_ActionID__From__ActionNext ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); const read = sut_r.read(inputFilename); [ ['none', ''], - // Italian: ['a18', ''], ['0', ''], - // Italian: ['1', 'a16'], - // Italian: // Italian: ['2', 'a8'], - // Italian: ['3', 'a17'], - ['A_18', ''], ['1', 'A_16'], ['2', 'A_8'], ['3', 'A_17'], - ['', ''], [' ', ''], ['99', ''], @@ -360,14 +347,11 @@ describe('KeylayoutToKmnConverter', function () { describe('get_ActionIndex__From__ActionId ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); const read = sut_r.read(inputFilename); [ ['none', 0], - // Italian: ['a16', 8], - // Italian: ['a18', 10], - // Italian: ['a19', 11], ['A_16', 8], ['A_18', 10], ['A_19', 11], @@ -388,15 +372,13 @@ describe('KeylayoutToKmnConverter', function () { describe('get_Output__From__ActionId_None ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); const read = sut_r.read(inputFilename); [ - // Italian: ['a14', 'u'], ['A_14', 'u'], ['', ''], [' ', ''], - // Italian: ['a18', undefined], ['A_18', undefined], ['unknown', ''], ].forEach(function (values) { @@ -421,76 +403,8 @@ describe('KeylayoutToKmnConverter', function () { describe('get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); const read = sut_r.read(inputFilename); - /*Italian: - - const b1_keycode_arr = [ - ['49', 'K_SPACE', 'a0', '0', 'ˆ'], - ['49', 'K_SPACE', 'a0', '1', 'ˆ'], - ['49', 'K_SPACE', 'a0', '2', 'ˆ'], - ['6', 'K_Z', 'a0', '4', 'ˆ'], - ['25', 'K_9', 'a0', '4', 'ˆ'], - ['43', 'K_COMMA', 'a0', '4', 'ˆ'], - ['49', 'K_SPACE', 'a0', '7', 'ˆ'], - ['0', 'K_A', 'a1', '1', 'Â'], - ['0', 'K_A', 'a1', '2', 'Â'], - ['14', 'K_E', 'a10', '0', 'ê'], - ['34', 'K_I', 'a11', '0', 'î'], - ['31', 'K_O', 'a13', '0', 'ô'], - ['32', 'K_U', 'a14', '0', 'û'], - ['14', 'K_E', 'a2', '1', 'Ê'], - ['14', 'K_E', 'a2', '2', 'Ê'], - ['34', 'K_I', 'a3', '1', 'Î'], - ['34', 'K_I', 'a3', '2', 'Î'], - ['31', 'K_O', 'a5', '1', 'Ô'], - ['31', 'K_O', 'a5', '2', 'Ô'], - ['32', 'K_U', 'a6', '1', 'Û'], - ['32', 'K_U', 'a6', '2', 'Û'], - ['0', 'K_A', 'a9', '0', 'â'] - ]; - const b1_modifierKey_arr = [ - ['K_SPACE', 'a0', '0', 'NCAPS', 'ˆ'], - ['K_SPACE', 'a0', '1', 'NCAPS SHIFT', 'ˆ'], - ['K_SPACE', 'a0', '1', 'SHIFT CAPS', 'ˆ'], - ['K_SPACE', 'a0', '2', 'CAPS', 'ˆ'], - ['K_Z', 'a0', '4', 'NCAPS SHIFT RALT', 'ˆ'], - ['K_9', 'a0', '4', 'NCAPS SHIFT RALT', 'ˆ'], - ['K_COMMA', 'a0', '4', 'NCAPS SHIFT RALT', 'ˆ'], - ['K_SPACE', 'a0', '7', 'NCAPS CTRL', 'ˆ'], - ['K_SPACE', 'a0', '7', 'NCAPS RALT CTRL', 'ˆ'], - ['K_A', 'a1', '1', 'NCAPS SHIFT', 'Â'], - ['K_A', 'a1', '1', 'SHIFT CAPS', 'Â'], - ['K_A', 'a1', '2', 'CAPS', 'Â'], - ['K_E', 'a10', '0', 'NCAPS', 'ê'], - ['K_I', 'a11', '0', 'NCAPS', 'î'], - ['K_O', 'a13', '0', 'NCAPS', 'ô'], - ['K_U', 'a14', '0', 'NCAPS', 'û'], - ['K_E', 'a2', '1', 'NCAPS SHIFT', 'Ê'], - ['K_E', 'a2', '1', 'SHIFT CAPS', 'Ê'], - ['K_E', 'a2', '2', 'CAPS', 'Ê'], - ['K_I', 'a3', '1', 'NCAPS SHIFT', 'Î'], - ['K_I', 'a3', '1', 'SHIFT CAPS', 'Î'], - ['K_I', 'a3', '2', 'CAPS', 'Î'], - ['K_O', 'a5', '1', 'NCAPS SHIFT', 'Ô'], - ['K_O', 'a5', '1', 'SHIFT CAPS', 'Ô'], - ['K_O', 'a5', '2', 'CAPS', 'Ô'], - ['K_U', 'a6', '1', 'NCAPS SHIFT', 'Û'], - ['K_U', 'a6', '1', 'SHIFT CAPS', 'Û'], - ['K_U', 'a6', '2', 'CAPS', 'Û'], - ['K_A', 'a9', '0', 'NCAPS', 'â'] - ]; - - [[b1_keycode_arr, b1_modifierKey_arr], - [[['49', 'K_SPACE', 'a0', '0', 'ˆ']], [['K_SPACE', 'a0', '0', 'NCAPS', 'ˆ']]], - [[['49', 'K_SPACE', 'a0', '0', '']], [['K_SPACE', 'a0', '0', 'NCAPS', '']]], - [[['49', 'K_SPACE', 'a0', '', 'ˆ']], [['K_SPACE', 'a0', '', 'NCAPS', 'ˆ']]], - [[['49', 'K_SPACE', '', '0', 'ˆ']], [['K_SPACE', '', '0', 'NCAPS', 'ˆ']]], - [[['49', '', 'a0', '0', 'ˆ']], [['', 'a0', '0', 'NCAPS', 'ˆ']]], - [[['', 'K_SPACE', 'a0', '0', 'ˆ']], [['K_SPACE', 'a0', '0', 'NCAPS', 'ˆ']]], - [[['', 'K_SPACE', 'a0', '0', 'ˆ']], [['K_SPACE', 'a0', '0', 'NCAPS', 'ˆ']]], - [[['', '', '', '', '']], [['', '', '', 'NCAPS', '']]], - */ const b1_keycode_arr = [ ['49', 'K_SPACE', 'A_0', '0', 'ˆ'], @@ -570,12 +484,6 @@ describe('KeylayoutToKmnConverter', function () { }); }); - /* Italian: [[[['49', 'K_SPACE', 'a0', '0', 'ˆ']], [['K_SPACE', 'a0', '0', '', 'ˆ']]], - [[['49', 'K_SPACE', 'a0', '0', '']], [['K_SPACE', 'a0', '0', '', '']]], - [[['', 'K_SPACE', 'a0', '0', 'ˆ']], [['K_SPACE', 'a0', '0', '', 'ˆ']]], - [[['', '', '', '', '']], [['', '', '', '', '']]], - ].forEach(function (values) { */ - [[[['49', 'K_SPACE', 'A_0', '0', 'ˆ']], [['K_SPACE', 'A_0', '0', '', 'ˆ']]], [[['49', 'K_SPACE', 'A_0', '0', '']], [['K_SPACE', 'A_0', '0', '', '']]], [[['', 'K_SPACE', 'A_0', '0', 'ˆ']], [['K_SPACE', 'A_0', '0', '', 'ˆ']]], @@ -607,35 +515,9 @@ describe('KeylayoutToKmnConverter', function () { describe('get_ActionStateOutput_array__From__ActionState ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); const read = sut_r.read(inputFilename); - /* - Italian:[['1', [ - ['a0', '1', 'ˆ'], - ['a1', '1', 'Â'], - ['a10', '1', 'ê'], - ['a11', '1', 'î'], - ['a13', '1', 'ô'], - ['a14', '1', 'û'], - ['a2', '1', 'Ê'], - ['a3', '1', 'Î'], - ['a5', '1', 'Ô'], - ['a6', '1', 'Û'], - ['a9', '1', 'â']],], - ['2', [ - ['a0', '2', '`'], - ['a1', '2', 'À'], - ['a10', '2', 'è'], - ['a11', '2', 'ì'], - ['a13', '2', 'ò'], - ['a14', '2', 'ù'], - ['a2', '2', 'È'], - ['a3', '2', 'Ì'], - ['a5', '2', 'Ò'], - ['a6', '2', 'Ù'], - ['a9', '2', 'à']],], - */ [['1', [ ['A_0', '1', 'ˆ'], ['A_1', '1', 'Â'], @@ -679,29 +561,9 @@ describe('KeylayoutToKmnConverter', function () { describe('get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); const read = sut_r.read(inputFilename); const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); - /* Italian: [ - ['a1', 'A', true, [ - ['a1', 'A', 'a1', '1', 'K_A', 'NCAPS SHIFT'], - ['a1', 'A', 'a1', '1', 'K_A', 'SHIFT CAPS'], - ['a1', 'A', 'a1', '2', 'K_A', 'CAPS']] - ], - ['a1', 'A', false, [ - ['a1', 'A', 'a1', '1', 'K_A', 'SHIFT'], - ['a1', 'A', 'a1', '1', 'K_A', 'SHIFT CAPS'], - ['a1', 'A', 'a1', '2', 'K_A', 'CAPS']] - ], - ['a9', 'a', true, [['a9', 'a', 'a9', '0', 'K_A', 'NCAPS']]], - ['a9', 'a', false, [['a9', 'a', 'a9', '0', 'K_A', '']]], - ['a9', 'a', , [['a9', 'a', 'a9', '0', 'K_A', '']]], - ['a9', '', true, [['a9', '', 'a9', '0', 'K_A', 'NCAPS']]], - ['a9', '', false, [['a9', '', 'a9', '0', 'K_A', '']]], - ['', 'a', true, []], - ['', 'a', false, []], - ['', '', , []], - */ [ ['A_1', 'A', true, [ @@ -737,47 +599,9 @@ describe('KeylayoutToKmnConverter', function () { describe('get_KeyActionOutput_array__From__ActionStateOutput_array ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); const read = sut_r.read(inputFilename); - /* Italian: const b6_actionId_arr = [ - ['a0', '1', 'ˆ'], - ['a1', '1', 'Â'], - ['a10', '1', 'ê'], - ['a11', '1', 'î'], - ['a13', '1', 'ô'], - ['a14', '1', 'û'], - ['a2', '1', 'Ê'], - ['a3', '1', 'Î'], - ['a5', '1', 'Ô'], - ['a6', '1', 'Û'], - ['a9', '1', 'â'] - ]; - const b1_keycode_arr = [ - ['49', 'K_SPACE', 'a0', '0', 'ˆ'], - ['49', 'K_SPACE', 'a0', '1', 'ˆ'], - ['49', 'K_SPACE', 'a0', '2', 'ˆ'], - ['6', 'K_Z', 'a0', '4', 'ˆ'], - ['25', 'K_9', 'a0', '4', 'ˆ'], - ['43', 'K_COMMA', 'a0', '4', 'ˆ'], - ['49', 'K_SPACE', 'a0', '7', 'ˆ'], - ['0', 'K_A', 'a1', '1', 'Â'], - ['0', 'K_A', 'a1', '2', 'Â'], - ['14', 'K_E', 'a10', '0', 'ê'], - ['34', 'K_I', 'a11', '0', 'î'], - ['31', 'K_O', 'a13', '0', 'ô'], - ['32', 'K_U', 'a14', '0', 'û'], - ['14', 'K_E', 'a2', '1', 'Ê'], - ['14', 'K_E', 'a2', '2', 'Ê'], - ['34', 'K_I', 'a3', '1', 'Î'], - ['34', 'K_I', 'a3', '2', 'Î'], - ['31', 'K_O', 'a5', '1', 'Ô'], - ['31', 'K_O', 'a5', '2', 'Ô'], - ['32', 'K_U', 'a6', '1', 'Û'], - ['32', 'K_U', 'a6', '2', 'Û'], - ['0', 'K_A', 'a9', '0', 'â'] - ]; - */ const b6_actionId_arr = [ ['A_0', '1', 'ˆ'], ['A_1', '1', 'Â'], @@ -792,8 +616,6 @@ describe('KeylayoutToKmnConverter', function () { ['A_9', '1', 'â'] ]; const b1_keycode_arr = [ - - ['49', 'K_SPACE', 'A_0', '0', 'ˆ'], ['49', 'K_SPACE', 'A_0', '1', 'ˆ'], ['49', 'K_SPACE', 'A_0', '2', 'ˆ'], @@ -827,27 +649,6 @@ describe('KeylayoutToKmnConverter', function () { }); }); - //----------------- - /* Italian: const oneEntryResult = [ - ['49', 'K_SPACE', 'a0', '0', 'ˆ'], - ['49', 'K_SPACE', 'a0', '1', 'ˆ'], - ['49', 'K_SPACE', 'a0', '2', 'ˆ'], - ['6', 'K_Z', 'a0', '4', 'ˆ'], - ['25', 'K_9', 'a0', '4', 'ˆ'], - ['43', 'K_COMMA', 'a0', '4', 'ˆ'], - ['49', 'K_SPACE', 'a0', '7', 'ˆ'] - ]; - const oneEntryResultNoOutput = [ - ['49', 'K_SPACE', 'a0', '0', ''], - ['49', 'K_SPACE', 'a0', '1', ''], - ['49', 'K_SPACE', 'a0', '2', ''], - ['6', 'K_Z', 'a0', '4', ''], - ['25', 'K_9', 'a0', '4', ''], - ['43', 'K_COMMA', 'a0', '4', ''], - ['49', 'K_SPACE', 'a0', '7', ''] - ] ; - */ - const oneEntryResult = [ ['49', 'K_SPACE', 'A_0', '0', 'ˆ'], ['49', 'K_SPACE', 'A_0', '1', 'ˆ'], @@ -877,7 +678,6 @@ describe('KeylayoutToKmnConverter', function () { }); }); - //------------------------------------------------------------------------------------- [[[['', '1', 'ˆ']], []], [[['', '', '']], []], [[[' ', ' ', '']], []], @@ -888,7 +688,6 @@ describe('KeylayoutToKmnConverter', function () { }); }); - //------------------------------------------------------------------------------------- [[[], []], [undefined, []], [null, []], diff --git a/developer/src/kmc-convert/test/kmn-file-reader.tests.ts b/developer/src/kmc-convert/test/kmn-file-reader.tests.ts index c6bdcca108c..42a626ccec1 100644 --- a/developer/src/kmc-convert/test/kmn-file-reader.tests.ts +++ b/developer/src/kmc-convert/test/kmn-file-reader.tests.ts @@ -12,8 +12,6 @@ import { assert } from 'chai'; import { compilerTestCallbacks, makePathToFixture } from './helpers/index.js'; import { KeylayoutFileReader } from '../src/keylayout-to-kmn/keylayout-file-reader.js'; -//----------------------------------------------------------------------------------------------------------------------- - describe('KeylayoutFileReader', function () { before(function () { @@ -25,7 +23,7 @@ describe('KeylayoutFileReader', function () { const sut_r = new KeylayoutFileReader(compilerTestCallbacks); it('read() should return filled array on correct input', async function () { - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); const result = sut_r.read(inputFilename); assert.isNotEmpty(result); }); @@ -46,7 +44,7 @@ describe('KeylayoutFileReader', function () { }); it('read() should return empty array on unavailable file name', async function () { - const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); + const inputFilename_unavailable = makePathToFixture('../' + 'data' + '/X.keylayout'); const result = sut_r.read(inputFilename_unavailable); assert.isNull(result); }); diff --git a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts index 17c810ed1a1..ad350f967fe 100644 --- a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts +++ b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts @@ -23,15 +23,15 @@ describe('KmnFileWriter', function () { }); describe("write() ", function () { - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); const read = sut_r.read(inputFilename); - const converted = sut.convert_bound.convert(read, '/Test.keylayout'.replace(/\.keylayout$/, '.kmn')); + const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); // empty convert_object from unavailable file name - const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); + const inputFilename_unavailable = makePathToFixture('../' + 'data' + '/X.keylayout'); const read_unavailable = sut_r.read(inputFilename_unavailable); const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); @@ -49,7 +49,7 @@ describe('KmnFileWriter', function () { }); describe("writeToString() ", function () { - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); @@ -72,8 +72,7 @@ describe('KmnFileWriter', function () { + "\n"; // empty convert_object from unavailable file name - //const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); - const inputFilename_unavailable = '/X.keylayout'; + const inputFilename_unavailable = makePathToFixture('../' + 'data' + '/X.keylayout'); const read_unavailable = sut_r.read(inputFilename_unavailable); const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); @@ -89,8 +88,7 @@ describe('KmnFileWriter', function () { }); describe("writeToUint8Array() ", function () { - //const inputFilename = makePathToFixture('../data/Test.keylayout'); - const inputFilename = '/Test.keylayout'; + const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); @@ -115,7 +113,7 @@ describe('KmnFileWriter', function () { // empty convert_object from unavailable file name - const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); + const inputFilename_unavailable = makePathToFixture('../' + 'data' + '/X.keylayout'); const read_unavailable = sut_r.read(inputFilename_unavailable); const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); it('writeToUint8Array() should return header in case of missing inputfile', async function () { @@ -130,7 +128,7 @@ describe('KmnFileWriter', function () { }); describe("writeData_Rules() ", function () { - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); @@ -138,7 +136,7 @@ describe('KmnFileWriter', function () { const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); // empty convert_object from unavailable file name - const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); + const inputFilename_unavailable = makePathToFixture('../' + 'data' + '/X.keylayout'); const read_unavailable = sut_r.read(inputFilename_unavailable); const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); @@ -158,19 +156,19 @@ describe('KmnFileWriter', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); const read = sut_r.read(inputFilename); const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); // empty convert_object from unavailable file name - const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); + const inputFilename_unavailable = makePathToFixture('../' + 'data' + '/X.keylayout'); const read_unavailable = sut_r.read(inputFilename_unavailable); const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); // empty convert_object from empty filename const inputFilename_empty = makePathToFixture(''); const read_empty = sut_r.read(inputFilename_empty); - const converted_empty = sut.convert_bound.convert(read_empty, inputFilename_empty.replace(/\.keylayout$/, '.kmn')); + const converted_empty = sut.convert_bound.convert(read_empty, inputFilename_empty); const out_expected_first: string = "c ..................................................................................................................\n" From 2dfa57c142011cb77be0597a57c2352e7cb50b29 Mon Sep 17 00:00:00 2001 From: Sabine Date: Wed, 9 Jul 2025 14:14:58 +0200 Subject: [PATCH 140/251] feat(developer): changes in build.sh, fixup-schema --- developer/src/kmc-convert/build.sh | 10 +--------- .../keylayout/create_keylayout_schema.sh | 5 +---- 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/developer/src/kmc-convert/build.sh b/developer/src/kmc-convert/build.sh index 7bdba0bbb80..a6c0f98a59f 100755 --- a/developer/src/kmc-convert/build.sh +++ b/developer/src/kmc-convert/build.sh @@ -32,18 +32,10 @@ builder_parse "$@" do_kmc_convert_test() { builder_echo heading "Creating keylayout.schema.JSON" - cd $KEYMAN_ROOT/resources/standards-data/keylayout - #./create_keylayout_schema.sh "$KEYMAN_ROOT/resources/standards-data/keylayout/create_keylayout_schema.sh" builder_echo heading "Creating keylayout.schema.validator" - cd $KEYMAN_ROOT/common/web/types - #./build.sh configure - # _S2 how would I start configure??? - "$KEYMAN_ROOT/common/web/types/build.sh" - - builder_echo heading "Starting kmc-convert test" - cd $THIS_SCRIPT_PATH + "$KEYMAN_ROOT/common/web/types/build.sh" "configure" } builder_run_action clean rm -rf ./build/ ./tsconfig.tsbuildinfo diff --git a/resources/standards-data/keylayout/create_keylayout_schema.sh b/resources/standards-data/keylayout/create_keylayout_schema.sh index 123a5f47a0e..bab40e7c817 100644 --- a/resources/standards-data/keylayout/create_keylayout_schema.sh +++ b/resources/standards-data/keylayout/create_keylayout_schema.sh @@ -5,6 +5,7 @@ # Create Date: 20 May 2025 # Authors: S. Schmitt +set -eu ## START STANDARD BUILD SCRIPT INCLUDE # adjust relative paths as necessary @@ -34,10 +35,6 @@ do builder_echo debug "${xsd} -> ${json}" (cd .. ; npx -p jgexml xsd2json ${THIS_SCRIPT_PATH}/"${xsd}" ${THIS_SCRIPT_PATH}/"${json}") || exit - #builder_echo debug 'fixup-schema.js' "${json}" - # old ldml: node ../fixup-schema.js "${json}" || builder_die "failed to fixup schema ${json}" - #node fixup-keylayout-schema.js "${json}" || builder_die "failed to fixup schema ${json}" - mv "${json}" tmp.json # reformat with prettier(JQ) ${JQ} . -S < tmp.json > "${json}" || (rm tmp.json ; builder_die "failed to transform final schema ${json}") From 1a522bf8a4d1c65ad044f1a02a78237c5bc341a5 Mon Sep 17 00:00:00 2001 From: Sabine Date: Wed, 9 Jul 2025 15:03:13 +0200 Subject: [PATCH 141/251] feat(developer): add header comment for keylayot-xml.ts --- .../web/utils/src/types/keylayout/keylayout-xml.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/developer/src/common/web/utils/src/types/keylayout/keylayout-xml.ts b/developer/src/common/web/utils/src/types/keylayout/keylayout-xml.ts index 69c4a849dd8..e5919c073f0 100644 --- a/developer/src/common/web/utils/src/types/keylayout/keylayout-xml.ts +++ b/developer/src/common/web/utils/src/types/keylayout/keylayout-xml.ts @@ -1,4 +1,12 @@ - +/* + * Keyman is 2025 copyright (C) SIL International. MIT License. + * + * Created by S. Schmitt on 2025-06-12 + * + * The interfaces in this file are designed with reference to the mapped + * structures produced by xml2js when passed keylayout .xml file. + * The prefix KL is stands for 'Keylayout' + */ export interface KeylayoutXMLSourceFile { /** From 558676c3ed3e6e24d4a3f0df187a01168c71474b Mon Sep 17 00:00:00 2001 From: Sabine Date: Wed, 9 Jul 2025 15:13:44 +0200 Subject: [PATCH 142/251] feat(developer): concatenating path for makePathToFixture --- developer/src/kmc-convert/package.json | 3 +- .../test/keylayout-to-kmn-converter.tests.ts | 40 +++++++++---------- .../kmc-convert/test/kmn-file-reader.tests.ts | 6 +-- .../kmc-convert/test/kmn-file-writer.tests.ts | 20 +++++----- package-lock.json | 10 ++--- 5 files changed, 38 insertions(+), 41 deletions(-) diff --git a/developer/src/kmc-convert/package.json b/developer/src/kmc-convert/package.json index 4798331e00a..615f81b18a3 100644 --- a/developer/src/kmc-convert/package.json +++ b/developer/src/kmc-convert/package.json @@ -29,7 +29,8 @@ "url": "https://github.com/keymanapp/keyman/issues" }, "dependencies": { - "@keymanapp/developer-utils": "*" + "@keymanapp/developer-utils": "*", + "ajv": "^8.17.1" }, "devDependencies": { "@keymanapp/developer-test-helpers": "*", diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index c37a9e8e8cf..a673c4c9e72 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -53,7 +53,7 @@ describe('KeylayoutToKmnConverter', function () { }); it('run() should throw on unavailable input file name and null output file name', async function () { - const inputFilename = makePathToFixture('../' + 'data' + '/Unavailable.keylayout'); + const inputFilename = makePathToFixture('../data/Unavailable.keylayout'); const result = sut.run(inputFilename, null); assert.isNotNull(result); assert.equal(compilerTestCallbacks.messages.length, 2); @@ -61,24 +61,24 @@ describe('KeylayoutToKmnConverter', function () { }); it('run() should return on correct input file name and empty output file name ', async function () { - const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); await NodeAssert.doesNotReject(async () => sut.run(inputFilename, '')); }); it('run() should return on correct input file name and null output file name', async function () { - const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); await NodeAssert.doesNotReject(async () => sut.run(inputFilename, null)); }); it('run() should return on correct input file name and given output file name ', async function () { - const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); - const outputFilename = makePathToFixture('../' + 'data' + '/OutputName.kmn'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); + const outputFilename = makePathToFixture('../data/OutputName.kmn'); await NodeAssert.doesNotReject(async () => sut.run(inputFilename, outputFilename)); }); it('run() should throw on incorrect input file extention and output file extention', async function () { - const inputFilename = makePathToFixture('../' + 'data' + '/Test_command.A'); - const outputFilename = makePathToFixture('../' + 'data' + '/data/OutputXName.B'); + const inputFilename = makePathToFixture('../data/Test_command.A'); + const outputFilename = makePathToFixture('../data/data/OutputXName.B'); const result = sut.run(inputFilename, outputFilename); assert.isNotNull(result); assert.equal(compilerTestCallbacks.messages.length, 2); @@ -86,8 +86,8 @@ describe('KeylayoutToKmnConverter', function () { }); it('run() return on correct input file extention and unsupperted output file extention', async function () { - const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); - const outputFilename = makePathToFixture('../' + 'data' + '/OutputXName.B'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); + const outputFilename = makePathToFixture('../data/OutputXName.B'); await NodeAssert.doesNotReject(async () => sut.run(inputFilename, outputFilename)); }); }); @@ -95,12 +95,12 @@ describe('KeylayoutToKmnConverter', function () { describe('convert() ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const read = sut_r.read(inputFilename); const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); // convert_object from unavailable file name - const inputFilename_unavailable = makePathToFixture('../' + 'data' + '/X.keylayout'); + const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); const read_unavailable = sut_r.read(inputFilename_unavailable); const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); @@ -256,7 +256,7 @@ describe('KeylayoutToKmnConverter', function () { describe('get_Modifier_array__From__KeyModifier_array ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const read = sut_r.read(inputFilename); const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); @@ -291,7 +291,7 @@ describe('KeylayoutToKmnConverter', function () { describe('get_KeyModifier_array__From__ActionID ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const read = sut_r.read(inputFilename); [ @@ -320,7 +320,7 @@ describe('KeylayoutToKmnConverter', function () { describe('get_ActionID__From__ActionNext ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const read = sut_r.read(inputFilename); [ @@ -347,7 +347,7 @@ describe('KeylayoutToKmnConverter', function () { describe('get_ActionIndex__From__ActionId ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const read = sut_r.read(inputFilename); [ @@ -372,7 +372,7 @@ describe('KeylayoutToKmnConverter', function () { describe('get_Output__From__ActionId_None ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const read = sut_r.read(inputFilename); [ @@ -403,7 +403,7 @@ describe('KeylayoutToKmnConverter', function () { describe('get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const read = sut_r.read(inputFilename); const b1_keycode_arr = [ @@ -515,7 +515,7 @@ describe('KeylayoutToKmnConverter', function () { describe('get_ActionStateOutput_array__From__ActionState ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const read = sut_r.read(inputFilename); [['1', [ @@ -561,7 +561,7 @@ describe('KeylayoutToKmnConverter', function () { describe('get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const read = sut_r.read(inputFilename); const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); @@ -599,7 +599,7 @@ describe('KeylayoutToKmnConverter', function () { describe('get_KeyActionOutput_array__From__ActionStateOutput_array ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const read = sut_r.read(inputFilename); const b6_actionId_arr = [ diff --git a/developer/src/kmc-convert/test/kmn-file-reader.tests.ts b/developer/src/kmc-convert/test/kmn-file-reader.tests.ts index 60fe42c2f5d..61be6c667af 100644 --- a/developer/src/kmc-convert/test/kmn-file-reader.tests.ts +++ b/developer/src/kmc-convert/test/kmn-file-reader.tests.ts @@ -23,7 +23,7 @@ describe('KeylayoutFileReader', function () { const sut_r = new KeylayoutFileReader(compilerTestCallbacks); it('read() should return filled array on correct input', async function () { - const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const result = sut_r.read(inputFilename); assert.isNotEmpty(result); }); @@ -44,13 +44,13 @@ describe('KeylayoutFileReader', function () { }); it('read() should return empty array on unavailable file name', async function () { - const inputFilename_unavailable = makePathToFixture('../' + 'data' + '/X.keylayout'); + const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); const result = sut_r.read(inputFilename_unavailable); assert.isNull(result); }); it('read() should return empty array on typo in path', async function () { - const result = sut_r.read(makePathToFixture('../' + 'data' + '|Test.keylayout')); + const result = sut_r.read(makePathToFixture('../data|Test.keylayout')); assert.isNull(result); }); }); diff --git a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts index ad350f967fe..9afaae5b7b8 100644 --- a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts +++ b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts @@ -23,7 +23,7 @@ describe('KmnFileWriter', function () { }); describe("write() ", function () { - const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); @@ -31,7 +31,7 @@ describe('KmnFileWriter', function () { const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); // empty convert_object from unavailable file name - const inputFilename_unavailable = makePathToFixture('../' + 'data' + '/X.keylayout'); + const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); const read_unavailable = sut_r.read(inputFilename_unavailable); const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); @@ -49,7 +49,7 @@ describe('KmnFileWriter', function () { }); describe("writeToString() ", function () { - const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); @@ -72,7 +72,7 @@ describe('KmnFileWriter', function () { + "\n"; // empty convert_object from unavailable file name - const inputFilename_unavailable = makePathToFixture('../' + 'data' + '/X.keylayout'); + const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); const read_unavailable = sut_r.read(inputFilename_unavailable); const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); @@ -88,7 +88,7 @@ describe('KmnFileWriter', function () { }); describe("writeToUint8Array() ", function () { - const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); @@ -113,7 +113,7 @@ describe('KmnFileWriter', function () { // empty convert_object from unavailable file name - const inputFilename_unavailable = makePathToFixture('../' + 'data' + '/X.keylayout'); + const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); const read_unavailable = sut_r.read(inputFilename_unavailable); const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); it('writeToUint8Array() should return header in case of missing inputfile', async function () { @@ -128,7 +128,7 @@ describe('KmnFileWriter', function () { }); describe("writeData_Rules() ", function () { - const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); @@ -136,7 +136,7 @@ describe('KmnFileWriter', function () { const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); // empty convert_object from unavailable file name - const inputFilename_unavailable = makePathToFixture('../' + 'data' + '/X.keylayout'); + const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); const read_unavailable = sut_r.read(inputFilename_unavailable); const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); @@ -156,12 +156,12 @@ describe('KmnFileWriter', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); - const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const read = sut_r.read(inputFilename); const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); // empty convert_object from unavailable file name - const inputFilename_unavailable = makePathToFixture('../' + 'data' + '/X.keylayout'); + const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); const read_unavailable = sut_r.read(inputFilename_unavailable); const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); diff --git a/package-lock.json b/package-lock.json index 74f8eeaef80..b347b9b8202 100644 --- a/package-lock.json +++ b/package-lock.json @@ -387,7 +387,8 @@ "name": "@keymanapp/kmc-convert", "license": "MIT", "dependencies": { - "@keymanapp/developer-utils": "*" + "@keymanapp/developer-utils": "*", + "ajv": "^8.17.1" }, "devDependencies": { "@keymanapp/developer-test-helpers": "*", @@ -4702,7 +4703,6 @@ "version": "8.17.1", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3", @@ -7779,7 +7779,6 @@ }, "node_modules/fast-deep-equal": { "version": "3.1.3", - "dev": true, "license": "MIT" }, "node_modules/fast-fifo": { @@ -7828,7 +7827,6 @@ "version": "3.0.6", "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz", "integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==", - "dev": true, "funding": [ { "type": "github", @@ -9511,8 +9509,7 @@ "node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", @@ -11870,7 +11867,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, "engines": { "node": ">=0.10.0" } From 4ddc7268a095ecbe162358fdbe968c9c3d8fe6fc Mon Sep 17 00:00:00 2001 From: Sabine Date: Wed, 9 Jul 2025 15:16:50 +0200 Subject: [PATCH 143/251] feat(developer): change path in makePathToFixture --- .../test/keylayout-to-kmn-converter.tests.ts | 40 +++++++++---------- .../kmc-convert/test/kmn-file-reader.tests.ts | 4 +- .../kmc-convert/test/kmn-file-writer.tests.ts | 20 +++++----- 3 files changed, 32 insertions(+), 32 deletions(-) diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index c37a9e8e8cf..a673c4c9e72 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -53,7 +53,7 @@ describe('KeylayoutToKmnConverter', function () { }); it('run() should throw on unavailable input file name and null output file name', async function () { - const inputFilename = makePathToFixture('../' + 'data' + '/Unavailable.keylayout'); + const inputFilename = makePathToFixture('../data/Unavailable.keylayout'); const result = sut.run(inputFilename, null); assert.isNotNull(result); assert.equal(compilerTestCallbacks.messages.length, 2); @@ -61,24 +61,24 @@ describe('KeylayoutToKmnConverter', function () { }); it('run() should return on correct input file name and empty output file name ', async function () { - const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); await NodeAssert.doesNotReject(async () => sut.run(inputFilename, '')); }); it('run() should return on correct input file name and null output file name', async function () { - const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); await NodeAssert.doesNotReject(async () => sut.run(inputFilename, null)); }); it('run() should return on correct input file name and given output file name ', async function () { - const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); - const outputFilename = makePathToFixture('../' + 'data' + '/OutputName.kmn'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); + const outputFilename = makePathToFixture('../data/OutputName.kmn'); await NodeAssert.doesNotReject(async () => sut.run(inputFilename, outputFilename)); }); it('run() should throw on incorrect input file extention and output file extention', async function () { - const inputFilename = makePathToFixture('../' + 'data' + '/Test_command.A'); - const outputFilename = makePathToFixture('../' + 'data' + '/data/OutputXName.B'); + const inputFilename = makePathToFixture('../data/Test_command.A'); + const outputFilename = makePathToFixture('../data/data/OutputXName.B'); const result = sut.run(inputFilename, outputFilename); assert.isNotNull(result); assert.equal(compilerTestCallbacks.messages.length, 2); @@ -86,8 +86,8 @@ describe('KeylayoutToKmnConverter', function () { }); it('run() return on correct input file extention and unsupperted output file extention', async function () { - const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); - const outputFilename = makePathToFixture('../' + 'data' + '/OutputXName.B'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); + const outputFilename = makePathToFixture('../data/OutputXName.B'); await NodeAssert.doesNotReject(async () => sut.run(inputFilename, outputFilename)); }); }); @@ -95,12 +95,12 @@ describe('KeylayoutToKmnConverter', function () { describe('convert() ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const read = sut_r.read(inputFilename); const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); // convert_object from unavailable file name - const inputFilename_unavailable = makePathToFixture('../' + 'data' + '/X.keylayout'); + const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); const read_unavailable = sut_r.read(inputFilename_unavailable); const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); @@ -256,7 +256,7 @@ describe('KeylayoutToKmnConverter', function () { describe('get_Modifier_array__From__KeyModifier_array ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const read = sut_r.read(inputFilename); const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); @@ -291,7 +291,7 @@ describe('KeylayoutToKmnConverter', function () { describe('get_KeyModifier_array__From__ActionID ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const read = sut_r.read(inputFilename); [ @@ -320,7 +320,7 @@ describe('KeylayoutToKmnConverter', function () { describe('get_ActionID__From__ActionNext ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const read = sut_r.read(inputFilename); [ @@ -347,7 +347,7 @@ describe('KeylayoutToKmnConverter', function () { describe('get_ActionIndex__From__ActionId ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const read = sut_r.read(inputFilename); [ @@ -372,7 +372,7 @@ describe('KeylayoutToKmnConverter', function () { describe('get_Output__From__ActionId_None ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const read = sut_r.read(inputFilename); [ @@ -403,7 +403,7 @@ describe('KeylayoutToKmnConverter', function () { describe('get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const read = sut_r.read(inputFilename); const b1_keycode_arr = [ @@ -515,7 +515,7 @@ describe('KeylayoutToKmnConverter', function () { describe('get_ActionStateOutput_array__From__ActionState ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const read = sut_r.read(inputFilename); [['1', [ @@ -561,7 +561,7 @@ describe('KeylayoutToKmnConverter', function () { describe('get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const read = sut_r.read(inputFilename); const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); @@ -599,7 +599,7 @@ describe('KeylayoutToKmnConverter', function () { describe('get_KeyActionOutput_array__From__ActionStateOutput_array ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const read = sut_r.read(inputFilename); const b6_actionId_arr = [ diff --git a/developer/src/kmc-convert/test/kmn-file-reader.tests.ts b/developer/src/kmc-convert/test/kmn-file-reader.tests.ts index 42a626ccec1..61be6c667af 100644 --- a/developer/src/kmc-convert/test/kmn-file-reader.tests.ts +++ b/developer/src/kmc-convert/test/kmn-file-reader.tests.ts @@ -23,7 +23,7 @@ describe('KeylayoutFileReader', function () { const sut_r = new KeylayoutFileReader(compilerTestCallbacks); it('read() should return filled array on correct input', async function () { - const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const result = sut_r.read(inputFilename); assert.isNotEmpty(result); }); @@ -44,7 +44,7 @@ describe('KeylayoutFileReader', function () { }); it('read() should return empty array on unavailable file name', async function () { - const inputFilename_unavailable = makePathToFixture('../' + 'data' + '/X.keylayout'); + const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); const result = sut_r.read(inputFilename_unavailable); assert.isNull(result); }); diff --git a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts index ad350f967fe..9afaae5b7b8 100644 --- a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts +++ b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts @@ -23,7 +23,7 @@ describe('KmnFileWriter', function () { }); describe("write() ", function () { - const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); @@ -31,7 +31,7 @@ describe('KmnFileWriter', function () { const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); // empty convert_object from unavailable file name - const inputFilename_unavailable = makePathToFixture('../' + 'data' + '/X.keylayout'); + const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); const read_unavailable = sut_r.read(inputFilename_unavailable); const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); @@ -49,7 +49,7 @@ describe('KmnFileWriter', function () { }); describe("writeToString() ", function () { - const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); @@ -72,7 +72,7 @@ describe('KmnFileWriter', function () { + "\n"; // empty convert_object from unavailable file name - const inputFilename_unavailable = makePathToFixture('../' + 'data' + '/X.keylayout'); + const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); const read_unavailable = sut_r.read(inputFilename_unavailable); const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); @@ -88,7 +88,7 @@ describe('KmnFileWriter', function () { }); describe("writeToUint8Array() ", function () { - const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); @@ -113,7 +113,7 @@ describe('KmnFileWriter', function () { // empty convert_object from unavailable file name - const inputFilename_unavailable = makePathToFixture('../' + 'data' + '/X.keylayout'); + const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); const read_unavailable = sut_r.read(inputFilename_unavailable); const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); it('writeToUint8Array() should return header in case of missing inputfile', async function () { @@ -128,7 +128,7 @@ describe('KmnFileWriter', function () { }); describe("writeData_Rules() ", function () { - const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); @@ -136,7 +136,7 @@ describe('KmnFileWriter', function () { const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); // empty convert_object from unavailable file name - const inputFilename_unavailable = makePathToFixture('../' + 'data' + '/X.keylayout'); + const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); const read_unavailable = sut_r.read(inputFilename_unavailable); const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); @@ -156,12 +156,12 @@ describe('KmnFileWriter', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); - const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const read = sut_r.read(inputFilename); const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); // empty convert_object from unavailable file name - const inputFilename_unavailable = makePathToFixture('../' + 'data' + '/X.keylayout'); + const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); const read_unavailable = sut_r.read(inputFilename_unavailable); const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); From 5801a56be6897074f82dccddfcaca3a6c1d302d7 Mon Sep 17 00:00:00 2001 From: Sabine Date: Wed, 9 Jul 2025 15:18:21 +0200 Subject: [PATCH 144/251] feat(developer): change path in makePathToFixture --- .../test/keylayout-to-kmn-converter.tests.ts | 40 +++++++++---------- .../kmc-convert/test/kmn-file-reader.tests.ts | 4 +- .../kmc-convert/test/kmn-file-writer.tests.ts | 20 +++++----- 3 files changed, 32 insertions(+), 32 deletions(-) diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index cfb42889c8e..146d6388834 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -53,7 +53,7 @@ describe('KeylayoutToKmnConverter', function () { }); it('run() should throw on unavailable input file name and null output file name', async function () { - const inputFilename = makePathToFixture('../' + 'data' + '/Unavailable.keylayout'); + const inputFilename = makePathToFixture('../data/Unavailable.keylayout'); const result = sut.run(inputFilename, null); assert.isNotNull(result); assert.equal(compilerTestCallbacks.messages.length, 2); @@ -62,24 +62,24 @@ describe('KeylayoutToKmnConverter', function () { }); it('run() should return on correct input file name and empty output file name ', async function () { - const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); await NodeAssert.doesNotReject(async () => sut.run(inputFilename, '')); }); it('run() should return on correct input file name and null output file name', async function () { - const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); await NodeAssert.doesNotReject(async () => sut.run(inputFilename, null)); }); it('run() should return on correct input file name and given output file name ', async function () { - const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); - const outputFilename = makePathToFixture('../' + 'data' + '/OutputName.kmn'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); + const outputFilename = makePathToFixture('../data/OutputName.kmn'); await NodeAssert.doesNotReject(async () => sut.run(inputFilename, outputFilename)); }); it('run() should throw on incorrect input file extention and output file extention', async function () { - const inputFilename = makePathToFixture('../' + 'data' + '/Test_command.A'); - const outputFilename = makePathToFixture('../' + 'data' + '/data/OutputXName.B'); + const inputFilename = makePathToFixture('../data/Test_command.A'); + const outputFilename = makePathToFixture('../data/data/OutputXName.B'); const result = sut.run(inputFilename, outputFilename); assert.isNotNull(result); assert.equal(compilerTestCallbacks.messages.length, 2); @@ -88,8 +88,8 @@ describe('KeylayoutToKmnConverter', function () { }); it('run() return on correct input file extention and unsupperted output file extention', async function () { - const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); - const outputFilename = makePathToFixture('../' + 'data' + '/OutputXName.B'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); + const outputFilename = makePathToFixture('../data/OutputXName.B'); await NodeAssert.doesNotReject(async () => sut.run(inputFilename, outputFilename)); }); }); @@ -97,12 +97,12 @@ describe('KeylayoutToKmnConverter', function () { describe('convert() ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const read = sut_r.read(inputFilename); const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); // convert_object from unavailable file name - const inputFilename_unavailable = makePathToFixture('../' + 'data' + '/X.keylayout'); + const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); const read_unavailable = sut_r.read(inputFilename_unavailable); const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); @@ -258,7 +258,7 @@ describe('KeylayoutToKmnConverter', function () { describe('get_Modifier_array__From__KeyModifier_array ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const read = sut_r.read(inputFilename); const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); @@ -293,7 +293,7 @@ describe('KeylayoutToKmnConverter', function () { describe('get_KeyModifier_array__From__ActionID ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const read = sut_r.read(inputFilename); [ @@ -322,7 +322,7 @@ describe('KeylayoutToKmnConverter', function () { describe('get_ActionID__From__ActionNext ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const read = sut_r.read(inputFilename); [ @@ -349,7 +349,7 @@ describe('KeylayoutToKmnConverter', function () { describe('get_ActionIndex__From__ActionId ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const read = sut_r.read(inputFilename); [ @@ -374,7 +374,7 @@ describe('KeylayoutToKmnConverter', function () { describe('get_Output__From__ActionId_None ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const read = sut_r.read(inputFilename); [ @@ -405,7 +405,7 @@ describe('KeylayoutToKmnConverter', function () { describe('get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const read = sut_r.read(inputFilename); const b1_keycode_arr = [ @@ -517,7 +517,7 @@ describe('KeylayoutToKmnConverter', function () { describe('get_ActionStateOutput_array__From__ActionState ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const read = sut_r.read(inputFilename); [['1', [ @@ -563,7 +563,7 @@ describe('KeylayoutToKmnConverter', function () { describe('get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const read = sut_r.read(inputFilename); const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); @@ -601,7 +601,7 @@ describe('KeylayoutToKmnConverter', function () { describe('get_KeyActionOutput_array__From__ActionStateOutput_array ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const read = sut_r.read(inputFilename); const b6_actionId_arr = [ diff --git a/developer/src/kmc-convert/test/kmn-file-reader.tests.ts b/developer/src/kmc-convert/test/kmn-file-reader.tests.ts index 60fe42c2f5d..a6c28cf818e 100644 --- a/developer/src/kmc-convert/test/kmn-file-reader.tests.ts +++ b/developer/src/kmc-convert/test/kmn-file-reader.tests.ts @@ -23,7 +23,7 @@ describe('KeylayoutFileReader', function () { const sut_r = new KeylayoutFileReader(compilerTestCallbacks); it('read() should return filled array on correct input', async function () { - const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const result = sut_r.read(inputFilename); assert.isNotEmpty(result); }); @@ -44,7 +44,7 @@ describe('KeylayoutFileReader', function () { }); it('read() should return empty array on unavailable file name', async function () { - const inputFilename_unavailable = makePathToFixture('../' + 'data' + '/X.keylayout'); + const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); const result = sut_r.read(inputFilename_unavailable); assert.isNull(result); }); diff --git a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts index 6f005771b0b..0d8ee9b6033 100644 --- a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts +++ b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts @@ -23,7 +23,7 @@ describe('KmnFileWriter', function () { }); describe("write() ", function () { - const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); @@ -32,7 +32,7 @@ describe('KmnFileWriter', function () { // empty convert_object from unavailable file name - const inputFilename_unavailable = makePathToFixture('../' + 'data' + '/X.keylayout'); + const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); const read_unavailable = sut_r.read(inputFilename_unavailable); const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); @@ -50,7 +50,7 @@ describe('KmnFileWriter', function () { }); describe("writeToString() ", function () { - const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); @@ -73,7 +73,7 @@ describe('KmnFileWriter', function () { + "\n"; // empty convert_object from unavailable file name - const inputFilename_unavailable = makePathToFixture('../' + 'data' + '/X.keylayout'); + const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); const read_unavailable = sut_r.read(inputFilename_unavailable); const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); @@ -89,7 +89,7 @@ describe('KmnFileWriter', function () { }); describe("writeToUint8Array() ", function () { - const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); @@ -114,7 +114,7 @@ describe('KmnFileWriter', function () { // empty convert_object from unavailable file name - const inputFilename_unavailable = makePathToFixture('../' + 'data' + '/X.keylayout'); + const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); const read_unavailable = sut_r.read(inputFilename_unavailable); const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); it('writeToUint8Array() should return header in case of missing inputfile', async function () { @@ -129,7 +129,7 @@ describe('KmnFileWriter', function () { }); describe("writeData_Rules() ", function () { - const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); @@ -137,7 +137,7 @@ describe('KmnFileWriter', function () { const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); // empty convert_object from unavailable file name - const inputFilename_unavailable = makePathToFixture('../' + 'data' + '/X.keylayout'); + const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); const read_unavailable = sut_r.read(inputFilename_unavailable); const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); @@ -157,12 +157,12 @@ describe('KmnFileWriter', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); - const inputFilename = makePathToFixture('../' + 'data' + '/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const read = sut_r.read(inputFilename); const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); // empty convert_object from unavailable file name - const inputFilename_unavailable = makePathToFixture('../' + 'data' + '/X.keylayout'); + const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); const read_unavailable = sut_r.read(inputFilename_unavailable); const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); From d2b21931803dc8b3d6310a4a54c98b8188356ef9 Mon Sep 17 00:00:00 2001 From: Sabine Date: Thu, 10 Jul 2025 08:18:05 +0200 Subject: [PATCH 145/251] feat(developer): remove call of validate --- .../src/keylayout-to-kmn/keylayout-to-kmn-converter.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index d08725ca214..5b778f9ec0c 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -56,14 +56,14 @@ export class KeylayoutToKmnConverter { const KeylayoutReader = new KeylayoutFileReader(this.callbacks/*, this.options*/); const jsonO: KeylayoutXMLSourceFile = KeylayoutReader.read(inputFilename); - try { + /* try { if (!KeylayoutReader.validate(jsonO)) { return null; } } catch (e) { this.callbacks.reportMessage(ConverterMessages.Error_InvalidFile({ errorText: e.toString() })); return null; - } + }*/ if (!jsonO) { this.callbacks.reportMessage(ConverterMessages.Error_UnableToRead({ inputFilename })); From ca41381659056121b32e361a9f810dabc82b0e30 Mon Sep 17 00:00:00 2001 From: Sabine Date: Thu, 10 Jul 2025 09:08:41 +0200 Subject: [PATCH 146/251] feat(developer): add call of validate --- .../src/keylayout-to-kmn/keylayout-to-kmn-converter.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 5b778f9ec0c..d08725ca214 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -56,14 +56,14 @@ export class KeylayoutToKmnConverter { const KeylayoutReader = new KeylayoutFileReader(this.callbacks/*, this.options*/); const jsonO: KeylayoutXMLSourceFile = KeylayoutReader.read(inputFilename); - /* try { + try { if (!KeylayoutReader.validate(jsonO)) { return null; } } catch (e) { this.callbacks.reportMessage(ConverterMessages.Error_InvalidFile({ errorText: e.toString() })); return null; - }*/ + } if (!jsonO) { this.callbacks.reportMessage(ConverterMessages.Error_UnableToRead({ inputFilename })); From 1f7134fd5275ef35da504502aefb005de76187df Mon Sep 17 00:00:00 2001 From: Sabine Date: Fri, 11 Jul 2025 08:39:39 +0200 Subject: [PATCH 147/251] feat(developer): permissions for create_keylayout_schema.sh --- resources/standards-data/keylayout/create_keylayout_schema.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/standards-data/keylayout/create_keylayout_schema.sh b/resources/standards-data/keylayout/create_keylayout_schema.sh index bab40e7c817..a782fba4a65 100644 --- a/resources/standards-data/keylayout/create_keylayout_schema.sh +++ b/resources/standards-data/keylayout/create_keylayout_schema.sh @@ -5,6 +5,7 @@ # Create Date: 20 May 2025 # Authors: S. Schmitt + set -eu ## START STANDARD BUILD SCRIPT INCLUDE From b5952df3a9a8c4f63e3729f1c8f3c3ffab68d53e Mon Sep 17 00:00:00 2001 From: Sabine Date: Fri, 11 Jul 2025 09:50:33 +0200 Subject: [PATCH 148/251] feat(developer): permissions for create_keylayout_schema.sh --- resources/standards-data/keylayout/create_keylayout_schema.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 resources/standards-data/keylayout/create_keylayout_schema.sh diff --git a/resources/standards-data/keylayout/create_keylayout_schema.sh b/resources/standards-data/keylayout/create_keylayout_schema.sh old mode 100644 new mode 100755 From 3d1972bd4f4a0d05e00ec0d1bb3e710c8c580721 Mon Sep 17 00:00:00 2001 From: Sabine Date: Fri, 11 Jul 2025 10:40:07 +0200 Subject: [PATCH 149/251] feat(developer): add tests for validate() --- .../test/data/Test_additionalTags.keylayout | 601 ++++++++++++++++++ .../test/data/Test_missingTags.keylayout | 595 +++++++++++++++++ .../test/data/Test_noActionWhen.keylayout | 598 +++++++++++++++++ .../test/data/Test_unknownTags.keylayout | 598 +++++++++++++++++ .../kmc-convert/test/kmn-file-reader.tests.ts | 42 ++ 5 files changed, 2434 insertions(+) create mode 100644 developer/src/kmc-convert/test/data/Test_additionalTags.keylayout create mode 100644 developer/src/kmc-convert/test/data/Test_missingTags.keylayout create mode 100644 developer/src/kmc-convert/test/data/Test_noActionWhen.keylayout create mode 100644 developer/src/kmc-convert/test/data/Test_unknownTags.keylayout diff --git a/developer/src/kmc-convert/test/data/Test_additionalTags.keylayout b/developer/src/kmc-convert/test/data/Test_additionalTags.keylayout new file mode 100644 index 00000000000..990b60a23a0 --- /dev/null +++ b/developer/src/kmc-convert/test/data/Test_additionalTags.keylayout @@ -0,0 +1,601 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/Test_missingTags.keylayout b/developer/src/kmc-convert/test/data/Test_missingTags.keylayout new file mode 100644 index 00000000000..271eeda562e --- /dev/null +++ b/developer/src/kmc-convert/test/data/Test_missingTags.keylayout @@ -0,0 +1,595 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/Test_noActionWhen.keylayout b/developer/src/kmc-convert/test/data/Test_noActionWhen.keylayout new file mode 100644 index 00000000000..61d87537ad6 --- /dev/null +++ b/developer/src/kmc-convert/test/data/Test_noActionWhen.keylayout @@ -0,0 +1,598 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/Test_unknownTags.keylayout b/developer/src/kmc-convert/test/data/Test_unknownTags.keylayout new file mode 100644 index 00000000000..e34ee307946 --- /dev/null +++ b/developer/src/kmc-convert/test/data/Test_unknownTags.keylayout @@ -0,0 +1,598 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/kmn-file-reader.tests.ts b/developer/src/kmc-convert/test/kmn-file-reader.tests.ts index 61be6c667af..5624d656852 100644 --- a/developer/src/kmc-convert/test/kmn-file-reader.tests.ts +++ b/developer/src/kmc-convert/test/kmn-file-reader.tests.ts @@ -11,6 +11,7 @@ import 'mocha'; import { assert } from 'chai'; import { compilerTestCallbacks, makePathToFixture } from './helpers/index.js'; import { KeylayoutFileReader } from '../src/keylayout-to-kmn/keylayout-file-reader.js'; +import { KeylayoutXMLSourceFile } from '../../common/web/utils/src/types/keylayout/keylayout-xml.js'; describe('KeylayoutFileReader', function () { @@ -18,6 +19,47 @@ describe('KeylayoutFileReader', function () { compilerTestCallbacks.clear(); }); + describe("validate() ", function () { + + it('validate() should return true on correct inputfile', async function () { + const sut_r = new KeylayoutFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/Test.keylayout'); + const result: KeylayoutXMLSourceFile = sut_r.read(inputFilename); + const validated = sut_r.validate(result); + assert.isTrue(validated); + }); + + it('validate() should return false on inputfile with unknown tags', async function () { + const sut_r = new KeylayoutFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/Test_unknownTags.keylayout'); + const result: KeylayoutXMLSourceFile = sut_r.read(inputFilename); + const validated = sut_r.validate(result); + assert.isFalse(validated); + }); + + it('validate() should return false on inputfile with additional tags', async function () { + const sut_r = new KeylayoutFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/Test_additionalTags.keylayout'); + const result: KeylayoutXMLSourceFile = sut_r.read(inputFilename); + const validated = sut_r.validate(result); + assert.isFalse(validated); + }); + it('validate() should return false on inputfile with missing tags', async function () { + const sut_r = new KeylayoutFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/Test_missingTags.keylayout'); + const result: KeylayoutXMLSourceFile = sut_r.read(inputFilename); + const validated = sut_r.validate(result); + assert.isFalse(validated); + }); + it('validate() should return false on no entries in action-when', async function () { + const sut_r = new KeylayoutFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/Test_noActionWhen.keylayout'); + const result: KeylayoutXMLSourceFile = sut_r.read(inputFilename); + const validated = sut_r.validate(result); + assert.isFalse(validated); + }); + }); + describe("read() ", function () { const sut_r = new KeylayoutFileReader(compilerTestCallbacks); From 77ec5728371df74d16a981b2bac83910c1a03e5c Mon Sep 17 00:00:00 2001 From: Sabine Date: Fri, 11 Jul 2025 12:27:36 +0200 Subject: [PATCH 150/251] feat(developer): remove comments --- .../src/kmc-convert/src/converter-class-factory.ts | 3 --- developer/src/kmc-convert/src/converter.ts | 10 ---------- .../src/keylayout-to-kmn/keylayout-to-kmn-converter.ts | 3 --- 3 files changed, 16 deletions(-) diff --git a/developer/src/kmc-convert/src/converter-class-factory.ts b/developer/src/kmc-convert/src/converter-class-factory.ts index a947626df70..2176b3df008 100644 --- a/developer/src/kmc-convert/src/converter-class-factory.ts +++ b/developer/src/kmc-convert/src/converter-class-factory.ts @@ -3,9 +3,6 @@ * * Lists all the available converters and finds matching converter */ -// _S2 const converters later holds several converters - each specified in diff module folder e.g. /keylayout-to-kmn,... -// _S2 this class will be used in each converter module -// _S2 class method returns/finds the right converter import { KeylayoutToKmnConverter } from './keylayout-to-kmn/keylayout-to-kmn-converter.js'; const converters = [ diff --git a/developer/src/kmc-convert/src/converter.ts b/developer/src/kmc-convert/src/converter.ts index 0d886aab8fe..2e9911073a0 100644 --- a/developer/src/kmc-convert/src/converter.ts +++ b/developer/src/kmc-convert/src/converter.ts @@ -29,9 +29,6 @@ export interface ConverterResult extends KeymanCompilerResult { * relies on callbacks for all external IO. */ -// _S2 this is Base class of all converters -// _S2 method init: uses Interface CompilerCallbacks( loadfile,...) -// _S2 method run: uses Interface CompilerCallbacks( loadfile,...) export class Converter implements KeymanCompiler { private callbacks: CompilerCallbacks; private options: CompilerOptions; @@ -43,7 +40,6 @@ export class Converter implements KeymanCompiler { * @param options - Compiler options * @returns false if initialization fails */ - // _S2 fills interface this.callbacks with array (holding our data), filesize ect async init(callbacks: CompilerCallbacks, options: CompilerOptions): Promise { this.options = { ...options }; this.callbacks = callbacks; @@ -61,12 +57,6 @@ export class Converter implements KeymanCompiler { * {@link Converter.write}. * @returns Source artifacts on success, null on failure. */ - // _S2 check for ( file available,...) then - // _S2 finds converter e.g.keylayout->kmn ( uses converter-class-factory) - // _S2 factory uses/instanciates child class ( ~ in C++ virtual function in base class <-> use fun of derived class) - // _S2 loads file - // _S2 creates a new converter (-object) - // _S2 runs conversion for this object ( run-method of this converter of keylayout-to-kmn-tonverter.ts ) async run(inputFilename: string, outputFilename?: string): Promise { const converterOptions: CompilerOptions = { ...defaultCompilerOptions, diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index d08725ca214..fdd36265484 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -114,9 +114,6 @@ export class KeylayoutToKmnConverter { data_object.arrayOf_Modifiers = modifierBehavior; // ukelele uses behaviours e.g. 18 modifiersCombinations in 8 KeyMapSelect(behaviors) data_object.arrayOf_Rules = rules; - // _S2 ToDo remove this console.log - console.log("RUN kmc convert - input file: ",data_object.keylayout_filename, " --> output file: ", data_object.kmn_filename); - // create an array of modifier combinations and store in data_object for (let j = 0; j < jsonObj.keyboard.modifierMap.keyMapSelect.length; j++) { const singleModifierSet: string[] = []; From e429923df6b90373449f100842f2110844a03434 Mon Sep 17 00:00:00 2001 From: Sabine Date: Fri, 11 Jul 2025 13:01:17 +0200 Subject: [PATCH 151/251] feat(developer): remove comments, rename write()->writeToFile(), writeToUint8Array()->write() --- .../src/converter-class-factory.ts | 3 - developer/src/kmc-convert/src/converter.ts | 10 --- .../keylayout-to-kmn-converter.ts | 10 +-- .../src/keylayout-to-kmn/kmn-file-writer.ts | 21 +------ .../kmc-convert/test/kmn-file-writer.tests.ts | 61 ++++--------------- 5 files changed, 16 insertions(+), 89 deletions(-) diff --git a/developer/src/kmc-convert/src/converter-class-factory.ts b/developer/src/kmc-convert/src/converter-class-factory.ts index a947626df70..2176b3df008 100644 --- a/developer/src/kmc-convert/src/converter-class-factory.ts +++ b/developer/src/kmc-convert/src/converter-class-factory.ts @@ -3,9 +3,6 @@ * * Lists all the available converters and finds matching converter */ -// _S2 const converters later holds several converters - each specified in diff module folder e.g. /keylayout-to-kmn,... -// _S2 this class will be used in each converter module -// _S2 class method returns/finds the right converter import { KeylayoutToKmnConverter } from './keylayout-to-kmn/keylayout-to-kmn-converter.js'; const converters = [ diff --git a/developer/src/kmc-convert/src/converter.ts b/developer/src/kmc-convert/src/converter.ts index f36530fcf8c..8335c052dbe 100644 --- a/developer/src/kmc-convert/src/converter.ts +++ b/developer/src/kmc-convert/src/converter.ts @@ -29,9 +29,6 @@ export interface ConverterResult extends KeymanCompilerResult { * relies on callbacks for all external IO. */ -// _S2 this is Base class of all converters -// _S2 method init: uses Interface CompilerCallbacks( loadfile,...) -// _S2 method run: uses Interface CompilerCallbacks( loadfile,...) export class Converter implements KeymanCompiler { private callbacks: CompilerCallbacks; private options: CompilerOptions; @@ -43,7 +40,6 @@ export class Converter implements KeymanCompiler { * @param options - Compiler options * @returns false if initialization fails */ - // _S2 fills interface this.callbacks with array (holding our data), filesize ect async init(callbacks: CompilerCallbacks, options: CompilerOptions): Promise { this.options = { ...options }; this.callbacks = callbacks; @@ -61,12 +57,6 @@ export class Converter implements KeymanCompiler { * {@link Converter.write}. * @returns Source artifacts on success, null on failure. */ - // _S2 check for ( file available,...) then - // _S2 finds converter e.g.keylayout->kmn ( uses converter-class-factory) - // _S2 factory uses/instanciates child class ( ~ in C++ virtual function in base class <-> use fun of derived class) - // _S2 loads file - // _S2 creates a new (derived) converter (-object) - // _S2 runs conversion for this object ( run-method of this converter of keylayout-to-kmn-tonverter.ts ) async run(inputFilename: string, outputFilename?: string): Promise { const converterOptions: CompilerOptions = { ...defaultCompilerOptions, diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index fdd14406d88..6ce29118843 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -85,22 +85,21 @@ export class KeylayoutToKmnConverter { const kmnFileWriter = new KmnFileWriter(this.callbacks, this.options); - // _S2 still write to file - may be removed later - const out_text_ok: boolean = kmnFileWriter.write(outArray); + // _S2 still write to file - will be removed later + const out_text_ok: boolean = kmnFileWriter.writeToFile(outArray); if (!out_text_ok) { this.callbacks.reportMessage(ConverterMessages.Error_UnableToWrite({ outputFilename })); return null; } // write to object/ConverterToKmnResult - const out_Uint8: Uint8Array = kmnFileWriter.writeToUint8Array(outArray); + const out_Uint8: Uint8Array = kmnFileWriter.write(outArray); const Result_toBeReturned: ConverterToKmnResult = { artifacts: { kmn: { data: out_Uint8, filename: outputFilename } } }; - // _S2 does this still work? if (!out_Uint8) { this.callbacks.reportMessage(ConverterMessages.Error_UnableToWrite({ outputFilename })); return null; @@ -131,9 +130,6 @@ export class KeylayoutToKmnConverter { data_object.arrayOf_Modifiers = modifierBehavior; // ukelele uses behaviours e.g. 18 modifiersCombinations in 8 KeyMapSelect(behaviors) data_object.arrayOf_Rules = rules; - // _S2 ToDo remove this console.log - console.log("RUN kmc convert - input file: ", data_object.keylayout_filename, " --> output file: ", data_object.kmn_filename); - // create an array of modifier combinations and store in data_object for (let j = 0; j < jsonObj.keyboard.modifierMap.keyMapSelect.length; j++) { const singleModifierSet: string[] = []; diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts index 5aeb4ecfd22..2c0daeab3ae 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts @@ -23,7 +23,7 @@ export class KmnFileWriter { * @param outputfilename the file that will be written; if no outputfilename is given an outputfilename will be created from data_ukelele.keylayout_filename * @return true if data has been written; false if not */ - public write(data_ukelele: convert_object): boolean { + public writeToFile(data_ukelele: convert_object): boolean { let data: string = "\n"; @@ -42,24 +42,7 @@ export class KmnFileWriter { } } - public writeToString(data_ukelele: convert_object): string { - let data: string = "\n"; - - // add top part of kmn file: STORES - data += this.writeData_Stores(data_ukelele); - - // add bottom part of kmn file: RULES - data += this.writeData_Rules(data_ukelele); - - try { - return data; - } catch (err) { - this.callbacks.reportMessage(ConverterMessages.Error_UnableToWrite({outputFilename: data_ukelele.kmn_filename})); - return null; - } - } - - public writeToUint8Array(data_ukelele: convert_object): Uint8Array { + public write(data_ukelele: convert_object): Uint8Array { let data: string = "\n"; // add top part of kmn file: STORES diff --git a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts index 9afaae5b7b8..72113a17ae2 100644 --- a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts +++ b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts @@ -22,7 +22,7 @@ describe('KmnFileWriter', function () { compilerTestCallbacks.clear(); }); - describe("write() ", function () { + describe("writeToFile()() ", function () { const inputFilename = makePathToFixture('../data/Test.keylayout'); const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); @@ -35,59 +35,19 @@ describe('KmnFileWriter', function () { const read_unavailable = sut_r.read(inputFilename_unavailable); const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); - it('write() should return true (no error) if written', async function () { - - const result = sut_w.write(converted); + it('writeToFile()() should return true (no error) if written', async function () { + const result = sut_w.writeToFile(converted); assert.isTrue(result); }); - it('write() should return false if no inputfile', async function () { - const result = sut_w.write(converted_unavailable); + it('writeToFile()() should return false if no inputfile', async function () { + const result = sut_w.writeToFile(converted_unavailable); assert.isFalse(result); }); }); - describe("writeToString() ", function () { - const inputFilename = makePathToFixture('../data/Test.keylayout'); - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); - const read = sut_r.read(inputFilename); - const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); - - const out_expected_first: string = "c ..................................................................................................................\n" - + "c ..................................................................................................................\n" - + "c Keyman keyboard generated by kmn-convert version: " + KEYMAN_VERSION.VERSION + "\n" - + "c from Ukelele file: "; - - const out_expected_last: string = "\n" - + "c ..................................................................................................................\n" - + "c ..................................................................................................................\n" - + "\n" - + "store(&TARGETS) 'desktop'\n" - + "\n" - + "begin Unicode > use(main)\n\n" - + "group(main) using keys\n\n" - + "\n"; - - // empty convert_object from unavailable file name - const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); - const read_unavailable = sut_r.read(inputFilename_unavailable); - const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); - - it('writeToString() should return result', async function () { - const result = sut_w.writeToString(converted); - assert.isNotNull(result); - }); - - it('writeToString() should return header in case of missing inputfile', async function () { - const result = sut_w.writeToString(converted_unavailable); - assert.equal(result, ("\n" + out_expected_first + out_expected_last)); - }); - }); - - describe("writeToUint8Array() ", function () { + describe("write()() ", function () { const inputFilename = makePathToFixture('../data/Test.keylayout'); const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); @@ -116,13 +76,14 @@ describe('KmnFileWriter', function () { const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); const read_unavailable = sut_r.read(inputFilename_unavailable); const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); - it('writeToUint8Array() should return header in case of missing inputfile', async function () { - const result = sut_w.writeToUint8Array(converted_unavailable); + + it('write()() should return header in case of missing inputfile', async function () { + const result = sut_w.write(converted_unavailable); assert.equal(new TextDecoder().decode(result), ("\n" + out_expected_first + out_expected_last)); }); - it('writeToUint8Array() should return result', async function () { - const result = sut_w.writeToUint8Array(converted); + it('write()() should return result', async function () { + const result = sut_w.write(converted); assert.isNotNull(result); }); }); From 7e1aa09475772aa5e6f1aacdc2d4b081a80b2f29 Mon Sep 17 00:00:00 2001 From: Sabine Date: Mon, 14 Jul 2025 15:32:38 +0200 Subject: [PATCH 152/251] feat(developer): changed copyright, imports, duplicate validationError, comments --- developer/src/common/web/utils/src/index.ts | 3 +++ .../src/common/web/utils/src/xml-utils.ts | 3 --- .../src/kmc-convert/src/converter-messages.ts | 4 ---- .../keylayout-to-kmn/keylayout-file-reader.ts | 6 +++-- .../keylayout-to-kmn-converter.ts | 2 +- .../src/kmc-convert/test/data/keylayout.dtd | 23 ++++++++++--------- .../kmc-convert/test/kmn-file-reader.tests.ts | 2 +- .../keylayout/dtd/keylayout.dtd | 23 ++++++++++--------- 8 files changed, 33 insertions(+), 33 deletions(-) diff --git a/developer/src/common/web/utils/src/index.ts b/developer/src/common/web/utils/src/index.ts index c39afa8bff7..00dc6d128d9 100644 --- a/developer/src/common/web/utils/src/index.ts +++ b/developer/src/common/web/utils/src/index.ts @@ -30,6 +30,9 @@ export * as LDMLKeyboard from './types/ldml-keyboard/ldml-keyboard-xml.js'; export { LDMLKeyboardTestDataXMLSourceFile } from './types/ldml-keyboard/ldml-keyboard-testdata-xml.js'; export { LDMLKeyboardXMLSourceFileReader, LDMLKeyboardXMLSourceFileReaderOptions } from './types/ldml-keyboard/ldml-keyboard-xml-reader.js'; +export * as Keylayout from './types/keylayout/keylayout-xml.js'; +export { KeylayoutXMLSourceFile } from './types/keylayout/keylayout-xml.js'; + export { CompilerAsyncCallbacks, CompilerCallbacks, diff --git a/developer/src/common/web/utils/src/xml-utils.ts b/developer/src/common/web/utils/src/xml-utils.ts index 2134b9cf78d..1fa186072f3 100644 --- a/developer/src/common/web/utils/src/xml-utils.ts +++ b/developer/src/common/web/utils/src/xml-utils.ts @@ -71,9 +71,6 @@ const PARSER_OPTIONS: KeymanXMLParserOptionsBag = { ignoreAttributes: false, // We'd like attributes, please tagValueProcessor: (_tagName: string, tagValue: string /*, jPath, hasAttributes, isLeafNode*/) => { // since trimValues: false, we need to zap any element values that would be trimmed. - // currently, the LDML spec doesn't have any element values, but this - // future-proofs us a little in that element values are allowed, just trimmed. - // if we do need elements in the future, we'd check the preserve-space attribute here. return tagValue?.trim(); }, trimValues: false, // preserve spaces, but see tagValueProcessor diff --git a/developer/src/kmc-convert/src/converter-messages.ts b/developer/src/kmc-convert/src/converter-messages.ts index d26f7e20707..6356c8e0a50 100644 --- a/developer/src/kmc-convert/src/converter-messages.ts +++ b/developer/src/kmc-convert/src/converter-messages.ts @@ -48,8 +48,4 @@ export class ConverterMessages { static Error_InvalidFile = (o: { errorText: string; }) => m( this.ERROR_InvalidFile, `The source file has an invalid structure: ${def(o.errorText)}`); - static ERROR_SchemaValidationError = SevError | 0x009; - static Error_SchemaValidationError = (o: { instancePath: string, keyword: string, message: string, params: string; }) => m( - this.ERROR_SchemaValidationError, `Error validating Keylayout XML file: ${def(o.instancePath === "" ? "keyboard" : o.instancePath)} : ${def(o.keyword)}: ${def(o.message)} ${def(o.params)}`); - } diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts index 667520a2473..eb3fbd0e3ca 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts @@ -12,7 +12,9 @@ import { XMLParser } from 'fast-xml-parser'; import { util } from '@keymanapp/common-types'; import { ConverterMessages } from '../converter-messages.js'; import { SchemaValidators } from '@keymanapp/common-types'; -import { KeylayoutXMLSourceFile } from '../../../common/web/utils/src/types/keylayout/keylayout-xml.js'; +import { DeveloperUtilsMessages } from '@keymanapp/developer-utils'; +import { KeylayoutXMLSourceFile } from "@keymanapp/developer-utils" + import boxXmlArray = util.boxXmlArray; export class KeylayoutFileReader { @@ -27,7 +29,7 @@ export class KeylayoutFileReader { if (!SchemaValidators.default.keylayout(source)) { for (const err of (SchemaValidators.default.keylayout).errors) { - this.callbacks.reportMessage(ConverterMessages.Error_SchemaValidationError({ + this.callbacks.reportMessage(DeveloperUtilsMessages.Error_SchemaValidationError({ instancePath: err.instancePath, keyword: err.keyword, message: err.message || 'Unknown AJV Error', // docs say 'message' is optional if 'messages:false' in options diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index fdd36265484..64dbac146c2 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -12,7 +12,7 @@ import { ConverterToKmnArtifacts } from "../converter-artifacts.js"; import { KmnFileWriter } from './kmn-file-writer.js'; import { KeylayoutFileReader } from './keylayout-file-reader.js'; import { ConverterMessages } from '../converter-messages.js'; -import { KeylayoutXMLSourceFile } from '../../../common/web/utils/src/types/keylayout/keylayout-xml.js'; +import { KeylayoutXMLSourceFile } from "@keymanapp/developer-utils" export interface convert_object { keylayout_filename: string, diff --git a/developer/src/kmc-convert/test/data/keylayout.dtd b/developer/src/kmc-convert/test/data/keylayout.dtd index 7bd1746e673..a670078a447 100644 --- a/developer/src/kmc-convert/test/data/keylayout.dtd +++ b/developer/src/kmc-convert/test/data/keylayout.dtd @@ -1,14 +1,13 @@ - - - + * Keyman is 2025 copyright (C) SIL International. MIT License. + * + * Created by S. Schmitt on 2025-07-14 + * + * This DTD describes a technical preview of Keylayout Data + --> + + + @@ -19,6 +18,7 @@ This DTD describes a technical preview of Keyboard Test Data --> + @@ -26,6 +26,7 @@ This DTD describes a technical preview of Keyboard Test Data --> - + + diff --git a/developer/src/kmc-convert/test/kmn-file-reader.tests.ts b/developer/src/kmc-convert/test/kmn-file-reader.tests.ts index 5624d656852..0229b487eb6 100644 --- a/developer/src/kmc-convert/test/kmn-file-reader.tests.ts +++ b/developer/src/kmc-convert/test/kmn-file-reader.tests.ts @@ -11,7 +11,7 @@ import 'mocha'; import { assert } from 'chai'; import { compilerTestCallbacks, makePathToFixture } from './helpers/index.js'; import { KeylayoutFileReader } from '../src/keylayout-to-kmn/keylayout-file-reader.js'; -import { KeylayoutXMLSourceFile } from '../../common/web/utils/src/types/keylayout/keylayout-xml.js'; +import { KeylayoutXMLSourceFile } from "@keymanapp/developer-utils" describe('KeylayoutFileReader', function () { diff --git a/resources/standards-data/keylayout/dtd/keylayout.dtd b/resources/standards-data/keylayout/dtd/keylayout.dtd index 55b41719718..a670078a447 100644 --- a/resources/standards-data/keylayout/dtd/keylayout.dtd +++ b/resources/standards-data/keylayout/dtd/keylayout.dtd @@ -1,14 +1,13 @@ - - - + * Keyman is 2025 copyright (C) SIL International. MIT License. + * + * Created by S. Schmitt on 2025-07-14 + * + * This DTD describes a technical preview of Keylayout Data + --> + + + @@ -19,6 +18,7 @@ This DTD describes a technical preview of Keyboard Test Data --> + @@ -26,6 +26,7 @@ This DTD describes a technical preview of Keyboard Test Data --> - + + From 274550da720d9dca4d7c4a1ea83794d654e0cc4d Mon Sep 17 00:00:00 2001 From: Sabine Date: Mon, 21 Jul 2025 11:47:14 +0200 Subject: [PATCH 153/251] feat(developer): comments and formatting of Error_ in converterMessages --- common/web/types/src/util/util.ts | 8 +++++-- .../src/kmc-convert/src/converter-messages.ts | 24 ++++++++++++------- .../keylayout-to-kmn-converter.ts | 8 +++++-- 3 files changed, 27 insertions(+), 13 deletions(-) diff --git a/common/web/types/src/util/util.ts b/common/web/types/src/util/util.ts index 30016414312..26055d6a30b 100644 --- a/common/web/types/src/util/util.ts +++ b/common/web/types/src/util/util.ts @@ -248,7 +248,7 @@ export function decodeUniHexValue(Uni_Val: string): any { /** * @brief function to convert a numeric character reference or a unicode value to a unicode character e.g. c -> c; U+1F60E -> 😎 * @param in_str the value that will converted - * @return a unicode character or undefined if in_str is not recognized + * @return a unicode character like 'c', 'ሴ', '😎' or undefined if in_str is not recognized */ export function convertToUnicodeCharacter(in_str: string): string { @@ -279,7 +279,11 @@ export function convertToUnicodeCharacter(in_str: string): string { return undefined; } } - +/** + * @brief function to convert a numeric character reference to a unicode Code Point e.g. ሴ -> U+1234; 􏘁 -> U+1F60E + * @param instr the value that will converted + * @return returns a unicode Code Point like U+0063, U+1234, U+1F60E; returns the input character if a non-numeric reference is used or returns 'undefined' if instr is not recognized + */ export function convertToUnicodeCodePoint(instr: string): string { if ((instr === null) || (instr === undefined)) { diff --git a/developer/src/kmc-convert/src/converter-messages.ts b/developer/src/kmc-convert/src/converter-messages.ts index 8e2e60aee1e..20f095d23fa 100644 --- a/developer/src/kmc-convert/src/converter-messages.ts +++ b/developer/src/kmc-convert/src/converter-messages.ts @@ -19,35 +19,41 @@ export class ConverterMessages { static ERROR_OutputFilenameIsRequired = SevError | 0x0001; static Error_OutputFilenameIsRequired = () => m( this.ERROR_OutputFilenameIsRequired, - `An output filename is required for keyboard conversion.`); + `An output filename is required for keyboard conversion.` + ); static ERROR_NoConverterFound = SevError | 0x0002; static Error_NoConverterFound = (o: { inputFilename: string, outputFilename: string; }) => m( this.ERROR_NoConverterFound, - `No converter is available that can convert from '${def(o.inputFilename)}' to '${def(o.outputFilename)}'.`); + `No converter is available that can convert from '${def(o.inputFilename)}' to '${def(o.outputFilename)}'.` + ); static ERROR_FileNotFound = SevError | 0x0003; static Error_FileNotFound = (o: { inputFilename: string; }) => m( this.ERROR_FileNotFound, `Input filename '${def(o.inputFilename)} - ' does not exist or could not be loaded.`); + ' does not exist or could not be loaded.` + ); static ERROR_UnableToRead = SevError | 0x0004; static Error_UnableToRead = (o: { inputFilename: string; }) => m( this.ERROR_UnableToRead, `Input file '${def(o.inputFilename)} - ' could not be read.`); + ' could not be read.` + ); static ERROR_UnableToConvert = SevError | 0x0005; static Error_UnableToConvert = (o: { inputFilename: string; }) => m( this.ERROR_UnableToConvert, `Input file '${def(o.inputFilename)} - ' could not be converted.`); + ' could not be converted.` + ); static ERROR_UnableToWrite = SevError | 0x0006; static Error_UnableToWrite = (o: { outputFilename: string; }) => m( this.ERROR_UnableToWrite, `Output file for '${def(o.outputFilename)} - ' could not be written.`); + ' could not be written.` + ); static ERROR_UnsupportedCharactersDetected = SevError | 0x0007; static Error_UnsupportedCharactersDetected = (o: { inputFilename: string, keymap_index: string, key: string, output: string; }) => m( - this.ERROR_UnsupportedCharactersDetected, `Input file ${def(o.inputFilename)} contains unsupported character ('${def(o.output)}') on key (${def(o.key)}) at keyMap index ${def(o.keymap_index)}`); - - } + this.ERROR_UnsupportedCharactersDetected, `Input file ${def(o.inputFilename)} contains unsupported character ('${def(o.output)}') on key (${def(o.key)}) at keyMap index ${def(o.keymap_index)}` + ); +} diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 2cf4cd2731c..ca7791c4fee 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -13,7 +13,12 @@ import { KmnFileWriter } from './kmn-file-writer.js'; import { KeylayoutFileReader } from './keylayout-file-reader.js'; import { ConverterMessages } from '../converter-messages.js'; - +/** + * Object holding all important data for the conversion between + * input (*.keylayout) format and output (*.kmn) format. + * It contains input and output filenames, an array of all used modifiers + * and all preprocessed key rules for up to 3 key/modifier combinations. + */ export interface convert_object { keylayout_filename: string, kmn_filename: string, @@ -108,7 +113,6 @@ export class KeylayoutToKmnConverter { arrayOf_Rules: [] }; - // ToDo in a new PR: check tags ( issue # 13599) if ((jsonObj !== null) && (jsonObj.hasOwnProperty("keyboard"))) { data_object.keylayout_filename = outputfilename.replace(/\.kmn$/, '.keylayout'); From d48cd56f354985a6d32f1aae8d3b326341a45ab8 Mon Sep 17 00:00:00 2001 From: Sabine Date: Mon, 21 Jul 2025 13:02:04 +0200 Subject: [PATCH 154/251] feat(developer): add import KeylayoutXMLSourceFile, add ERROR_InvalidFile --- developer/src/kmc-convert/src/converter-messages.ts | 6 ++++++ .../src/keylayout-to-kmn/keylayout-to-kmn-converter.ts | 1 + 2 files changed, 7 insertions(+) diff --git a/developer/src/kmc-convert/src/converter-messages.ts b/developer/src/kmc-convert/src/converter-messages.ts index 20f095d23fa..1d8aa5e70ba 100644 --- a/developer/src/kmc-convert/src/converter-messages.ts +++ b/developer/src/kmc-convert/src/converter-messages.ts @@ -56,4 +56,10 @@ export class ConverterMessages { static Error_UnsupportedCharactersDetected = (o: { inputFilename: string, keymap_index: string, key: string, output: string; }) => m( this.ERROR_UnsupportedCharactersDetected, `Input file ${def(o.inputFilename)} contains unsupported character ('${def(o.output)}') on key (${def(o.key)}) at keyMap index ${def(o.keymap_index)}` ); + + static ERROR_InvalidFile = SevError | 0x0008; + static Error_InvalidFile = (o: { errorText: string; }) => m( + this.ERROR_InvalidFile, `The source file has an invalid structure: ${def(o.errorText)}` + ); + } diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index e8e417aac9a..0c4e9e0e0d1 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -12,6 +12,7 @@ import { ConverterToKmnArtifacts } from "../converter-artifacts.js"; import { KmnFileWriter } from './kmn-file-writer.js'; import { KeylayoutFileReader } from './keylayout-file-reader.js'; import { ConverterMessages } from '../converter-messages.js'; +import { KeylayoutXMLSourceFile } from '../../../common/web/utils/src/types/keylayout/keylayout-xml.js'; /** * Object holding all important data for the conversion between From 5c8ac8c6500d042485bf3bca26c7be69773e483a Mon Sep 17 00:00:00 2001 From: Sabine Date: Wed, 23 Jul 2025 21:08:52 +0200 Subject: [PATCH 155/251] feat(developer): use Arrays of objects instead of 2D arrays (runs OK-draft version) --- .../keylayout-to-kmn-converter.ts | 566 +++++++++++++++--- .../test/keylayout-to-kmn-converter.tests.ts | 547 +++++++++++++++-- 2 files changed, 969 insertions(+), 144 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 0c4e9e0e0d1..b951a324091 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -26,6 +26,41 @@ export interface convert_object { arrayOf_Modifiers: string[][], arrayOf_Rules: Rule[], }; +//_S2 do I need search??? +export interface ActionIdOutputBehaviourKeyModi_object { + search: string, + actionId: string, + outchar: string, + behaviour: string, + key: string, + modifier: string, +}; + + + +export interface ActionIdKeyModiOutput_object { + actionId: string, + keyCode: string, + key: string, + modifier: string, + outchar: string; +}; +export interface modifierKey_object { + key: string; // _S2 todo change everywhere!!! + modifier: number, +}; +export interface modifier_object { + modifier: string, +}; +export interface behaviourKey_object { + behaviour: string, + key: string, +}; +export interface idStateOutput_object { + id: string, + state: string, + output: string, +}; export class KeylayoutToKmnConverter { @@ -206,15 +241,15 @@ export class KeylayoutToKmnConverter { for (let l = 0; l < data_ukelele.arrayOf_Modifiers[i].length; l++) { - if ((this.get_Output__From__ActionId_None(jsonObj, action_id) !== undefined) - && (this.get_Output__From__ActionId_None(jsonObj, action_id) !== "")) { + if ((this.get_4_Output__From__ActionId_None(jsonObj, action_id) !== undefined) + && (this.get_4_Output__From__ActionId_None(jsonObj, action_id) !== "")) { - const outputchar: string = this.get_Output__From__ActionId_None(jsonObj, action_id); - const b1_modifierKey_arr: string[][] = - this.get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput(jsonObj, data_ukelele.arrayOf_Modifiers, action_id, outputchar, isCapsused); + const outputchar: string = this.get_4_Output__From__ActionId_None(jsonObj, action_id); - for (let m = 0; m < b1_modifierKey_arr.length; m++) { + const b1_modifierKey_obj: ActionIdOutputBehaviourKeyModi_object[] = + this.get_8_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput(jsonObj, data_ukelele.arrayOf_Modifiers, action_id, outputchar, isCapsused); + for (let m = 0; m < b1_modifierKey_obj.length; m++) { rule_obj = new Rule( /* rule_type */ "C1", @@ -228,8 +263,8 @@ export class KeylayoutToKmnConverter { /* dk for C2*/ 0, /* unique B */ 0, - /* modifier_key*/ b1_modifierKey_arr[m][5], - /* key */ b1_modifierKey_arr[m][4], + /* modifier_key*/ b1_modifierKey_obj[m].modifier, + /* key */ b1_modifierKey_obj[m].key, /* output */ new TextEncoder().encode(outputchar) ); if ((outputchar !== undefined) && (outputchar !== "undefined") && (outputchar !== "")) { @@ -247,7 +282,7 @@ export class KeylayoutToKmnConverter { // https://docs.google.com/document/d/12J3NGO6RxIthCpZDTR8FYSRjiMgXJDLwPY2z9xqKzJ0/edit?tab=t.0#heading=h.g7jwx3lx0ydd ......... // ............................................................................................................................... - const b1_actionIndex: number = this.get_ActionIndex__From__ActionId(jsonObj, action_id); + const b1_actionIndex: number = this.get_1_ActionIndex__From__ActionId(jsonObj, action_id); // with action_id from above loop all 'action' and search for a state(none)-next-pair ............................................................................................................ // e.g. in Block 5: find for action id a18 ...................................................................................................................... @@ -264,27 +299,38 @@ export class KeylayoutToKmnConverter { // Data of Block Nr 4 ..................................................................................................................................................................... // with present action_id (a18) find all keycode-behaviour-pairs that use this action (a18) => (keymapIndex 0/keycode 24 and keymapIndex 3/keycode 24) .................................... // from these create an array of modifier combinations e.g. [['','caps?'], ['Caps']] ..................................................................................................... - /* eg: [['24', 0], ['24', 3]] */ const b4_deadkey_arr: number[][] = this.get_KeyModifier_array__From__ActionID(jsonObj, action_id); - /* e.g. [['','caps?'], ['Caps']]*/ const b4_deadkeyModifier_arr: string[] = this.get_Modifier_array__From__KeyModifier_array(data_ukelele.arrayOf_Modifiers, b4_deadkey_arr); + /* eg: [['24', 0], ['24', 3]] */ // const b4_deadkey_arr: number[][] = this.get_9o_KeyModifier_array__From__ActionID_oldArrayType(jsonObj, action_id); //_S2 remove&replace + /* eg: [['24', 0], ['24', 3]] */ const b4_deadkey_obj: modifierKey_object[] = this.get_9_KeyModifier_array__From__ActionID(jsonObj, action_id); + /* e.g. [['','caps?'], ['Caps']]*/ //const b4_deadkeyModifier_arr: string[] = this.get_3o_Modifier_array__From__KeyModifier_array_oldArrayType(data_ukelele.arrayOf_Modifiers, b4_deadkey_arr);//_S2 remove&replace + /* e.g. [['','caps?'], ['Caps']]*/ const b4_deadkeyModifier_obj: string[] = this.get_3_Modifier_array__From__KeyModifier_array(data_ukelele.arrayOf_Modifiers, b4_deadkey_obj); // ........................................................................................................................................................................................ // Data of Block Nr 6 ..................................................................................................................................................................... // create an array[action id,state,output] from all state-output-pairs that use state = b5_value_next (e.g. use 1 in ) ...................................... - /* eg: [ 'a9','1','â'] */ const b6_actionId_arr: string[][] = this.get_ActionStateOutput_array__From__ActionState(jsonObj, b5_value_next); + /* eg: [ 'a9','1','â'] */ //const b6_actionId_arr: string[][] = this.get_6o_ActionStateOutput_array__From__ActionState_oldArrayType(jsonObj, b5_value_next);//_S2 remove&replace + /* eg: [ 'a9','1','â'] */ const b6_actionId_obj: idStateOutput_object[] = this.get_6_ActionStateOutput_array__From__ActionState(jsonObj, b5_value_next); // ........................................................................................................................................................................................ // Data of Block Nr 1 .................................................................................................................................................................... // create array[Keycode,Keyname,action id,actionIndex,output] and array[Keyname,action id,behaviour,modifier,output] ...................................................................... - /* eg: ['0','K_A','a9','0','â'] */ const b1_keycode_arr: string[][] = this.get_KeyActionOutput_array__From__ActionStateOutput_array(jsonObj, b6_actionId_arr); - /* eg: ['K_A','a9','0','NCAPS','â']*/ const b1_modifierKey_arr: string[][] = this.get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(jsonObj, b1_keycode_arr, isCapsused); + /* eg: ['0','K_A','a9','0','â'] */ //const b1_keycode_arr: string[][] = this.get_5o_KeyActionOutput_array__From__ActionStateOutput_array_oldArrayType(jsonObj, b6_actionId_arr);//_S2 remove&replace + /* eg: ['0','K_A','a9','0','â'] */ const b1_keycode_obj: ActionIdKeyModiOutput_object[] = this.get_5_KeyActionOutput_array__From__ActionStateOutput_array(jsonObj, b6_actionId_obj); + + /* eg: ['K_A','a9','0','NCAPS','â']*/ // const b1_modifierKey_arr: string[][] = this.get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array_arr(jsonObj, b1_keycode_arr, isCapsused);//_S2 remove&replace + /* eg: ['K_A','a9','0','NCAPS','â']*/ //const b1_modifierKey_obj: ActionIdOutputBehaviourKeyModi_object[] = this.get_7o_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(jsonObj, b1_keycode_arr, isCapsused);//_S2 remove&replace + /* eg: ['K_A','a9','0','NCAPS','â']*/ const b1_modifierKey_obj: ActionIdOutputBehaviourKeyModi_object[] = this.get_7_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(jsonObj, b1_keycode_obj, isCapsused);//_S2 remove&replace // ....................................................................................................................................................................................... - for (let n1 = 0; n1 < b4_deadkeyModifier_arr.length; n1++) { - for (let n2 = 0; n2 < b4_deadkeyModifier_arr[n1].length; n2++) { - for (let n3 = 0; n3 < b4_deadkey_arr.length; n3++) { - for (let n4 = 0; n4 < b1_modifierKey_arr.length; n4++) { + //for (let n1 = 0; n1 < b4_deadkeyModifier_arr.length; n1++) { + for (let n1 = 0; n1 < b4_deadkeyModifier_obj.length; n1++) { + //for (let n2 = 0; n2 < b4_deadkeyModifier_arr[n1].length; n2++) { + for (let n2 = 0; n2 < b4_deadkeyModifier_obj[n1].length; n2++) { + // for (let n3 = 0; n3 < b4_deadkey_arr.length; n3++) { + for (let n3 = 0; n3 < b4_deadkey_obj.length; n3++) { + //for (let n4 = 0; n4 < b1_modifierKey_arr.length; n4++) {//_S2 remove&replace + for (let n4 = 0; n4 < b1_modifierKey_obj.length; n4++) { rule_obj = new Rule( /* rule_type */ "C2", @@ -294,18 +340,30 @@ export class KeylayoutToKmnConverter { /* id_prev_deadkey */ 0, /* unique A */ 0, - /* modifier_deadkey */ this.create_kmn_modifier(b4_deadkeyModifier_arr[n1][n2], isCapsused), - /* deadkey */ this.map_UkeleleKC_To_VK(Number(b4_deadkey_arr[n3][0])), + /* modifier_deadkey */ //this.create_kmn_modifier(b4_deadkeyModifier_arr[n1][n2], isCapsused), + /* modifier_deadkey */ this.create_kmn_modifier(b4_deadkeyModifier_obj[n1][n2], isCapsused), + /* deadkey */ //this.map_UkeleleKC_To_VK(Number(b4_deadkey_arr[n3][0])), + /* deadkey */ this.map_UkeleleKC_To_VK(Number(b4_deadkey_obj[n3].key)), /* dk for C2*/ dk_counter_C2++, /* unique B */ 0, - /* modifier_key*/ b1_modifierKey_arr[n4][3], - /* key */ b1_modifierKey_arr[n4][0], - /* output */ new TextEncoder().encode(b1_modifierKey_arr[n4][4]), + /* modifier_key*/ // b1_modifierKey_arr[n4][3],//_S2 remove&replace + /* key */ //b1_modifierKey_arr[n4][0], + /* output */ // new TextEncoder().encode(b1_modifierKey_arr[n4][4]), + + /* modifier_key*/ b1_modifierKey_obj[n4].modifier, + /* key */ b1_modifierKey_obj[n4].key, + /* output */ new TextEncoder().encode(b1_modifierKey_obj[n4].outchar), ); - if ((b1_modifierKey_arr[n4][4] !== undefined) - && (b1_modifierKey_arr[n4][4] !== "undefined") - && (b1_modifierKey_arr[n4][4] !== "")) { + /* if ((b1_modifierKey_arr[n4][4] !== undefined)//_S2 remove&replace + && (b1_modifierKey_arr[n4][4] !== "undefined") + && (b1_modifierKey_arr[n4][4] !== "")) { + object_array.push(rule_obj); + }*/ + + if ((b1_modifierKey_obj[n4].outchar !== undefined) + && (b1_modifierKey_obj[n4].outchar !== "undefined") + && (b1_modifierKey_obj[n4].outchar !== "")) { object_array.push(rule_obj); } } @@ -341,60 +399,94 @@ export class KeylayoutToKmnConverter { // Data of Block Nr 4 ........................................................................................................................................................................ // with present action_id (a16) find all keycode-behaviour-pairs that use this action (a16) => (keymapIndex 3/keycode 32) .................................................................... // from these create an array of modifier combinations e.g. [ [ 'anyOption', 'Caps' ] ] ..................................................................................................... - /* e.g. [['32', 3]] */ const b4_deadkey_arr: number[][] = this.get_KeyModifier_array__From__ActionID(jsonObj, action_id); - /* e.g. [ [ 'anyOption', 'Caps' ] ]*/ const b4_deadkeyModifier_arr: string[] = this.get_Modifier_array__From__KeyModifier_array(data_ukelele.arrayOf_Modifiers, b4_deadkey_arr); + /* e.g. [['32', 3]] */ // const b4_deadkey_arr: number[][] = this.get_9o_KeyModifier_array__From__ActionID_oldArrayType(jsonObj, action_id);//_S2 remove&replace + /* e.g. [['32', 3]] */ const b4_deadkey_obj: modifierKey_object[] = this.get_9_KeyModifier_array__From__ActionID(jsonObj, action_id); + /* e.g. [ [ 'anyOption', 'Caps' ] ]*/ // const b4_deadkeyModifier_arr: string[] = this.get_3o_Modifier_array__From__KeyModifier_array_oldArrayType(data_ukelele.arrayOf_Modifiers, b4_deadkey_arr); + /* e.g. [ [ 'anyOption', 'Caps' ] ]*/ const b4_deadkeyModifier_obj: string[] = this.get_3_Modifier_array__From__KeyModifier_array(data_ukelele.arrayOf_Modifiers, b4_deadkey_obj); // ........................................................................................................................................................................................... // Data of Block Nr 3 ........................................................................................................................................................................ // get an action id from a state-output-pair that use state = b5_value_state (e.g. use 3 in ) ................................................................. - /* e.g. actioniD = a17 */ const b3_actionId: string = this.get_ActionID__From__ActionNext(jsonObj, b5_value_state); + /* e.g. actioniD = a17 */ const b3_actionId: string = this.get_2_ActionID__From__ActionNext(jsonObj, b5_value_state); // ........................................................................................................................................................................................... // Data of Block Nr 2 ....................................................................................................................................................................... // with present action_id (a17) find all key names and behaviours that use this action (a17) => (keymapIndex 3/keycode 28) .................................................................... // from these create an array of modifier combinations e.g. [ [ 'anyOption', 'Caps' ] ] ..................................................................................................... - /* eg: index=3 */ const b2_prev_deadkey_arr: number[][] = this.get_KeyModifier_array__From__ActionID(jsonObj, String(b3_actionId)); // conversion not necessary - /* e.g. [ [ 'anyOption', 'Caps' ] ] */ const b2_prev_deadkeyModifier_arr: string[] = this.get_Modifier_array__From__KeyModifier_array(data_ukelele.arrayOf_Modifiers, b2_prev_deadkey_arr); + + + + /* eg: index=3 */ //const b2_prev_deadkey_arr: number[][] = this.get_9o_KeyModifier_array__From__ActionID_oldArrayType(jsonObj, b3_actionId); // conversion not necessary //_S2 remove&replace + /* eg: index=3 */ const b2_prev_deadkey_obj: modifierKey_object[] = this.get_9_KeyModifier_array__From__ActionID(jsonObj, b3_actionId); // conversion not necessary //_S2 remove&replace + /* e.g. [ [ 'anyOption', 'Caps' ] ] */ // const b2_prev_deadkeyModifier_arr: string[] = this.get_3o_Modifier_array__From__KeyModifier_array_oldArrayType(data_ukelele.arrayOf_Modifiers, b2_prev_deadkey_arr); + /* e.g. [ [ 'anyOption', 'Caps' ] ] */ const b2_prev_deadkeyModifier_obj: string[] = this.get_3_Modifier_array__From__KeyModifier_array(data_ukelele.arrayOf_Modifiers, b2_prev_deadkey_obj); // ........................................................................................................................................................................................... // Data of Block Nr 6 ........................................................................................................................................................................ // create an array[action id,state,output] from all state-output-pairs that use state = b5_value_next (e.g. use 1 in ) ......................................... - /* eg:[ [ 'a9','1','â'] ]*/ const b6_actionId_arr: string[][] = this.get_ActionStateOutput_array__From__ActionState(jsonObj, b5_value_next); + /* eg:[ [ 'a9','1','â'] ]*/ // const b6_actionId_arr: string[][] = this.get_6o_ActionStateOutput_array__From__ActionState_oldArrayType(jsonObj, b5_value_next); + /* eg:[ [ 'a9','1','â'] ]*/ const b6_actionId_obj: idStateOutput_object[] = this.get_6_ActionStateOutput_array__From__ActionState(jsonObj, b5_value_next); /* eg:[ [ 'a9','1','â'] ]*/ // ........................................................................................................................................................................................... // Data of Block Nr 1 ....................................................................................................................................................................... // create array[Keycode,Keyname,action id,actionIndex,output] and array[Keyname,action id,behaviour,modifier,output] ......................................................................... - /* eg: ['49','K_SPACE','a0','0','Â'] */ const b1_keycode_arr: string[][] = this.get_KeyActionOutput_array__From__ActionStateOutput_array(jsonObj, b6_actionId_arr); - /* eg: ['K_SPACE','a0','0','NCAPS','Â'] */ const b1_modifierKey_arr: string[][] = this.get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(jsonObj, b1_keycode_arr, isCapsused); + /* eg: ['49','K_SPACE','a0','0','Â'] */ //const b1_keycode_arr: string[][] = this.get_5o_KeyActionOutput_array__From__ActionStateOutput_array_oldArrayType(jsonObj, b6_actionId_arr); + /* eg: ['0','K_A','a9','0','â'] */ const b1_keycode_obj: ActionIdKeyModiOutput_object[] = this.get_5_KeyActionOutput_array__From__ActionStateOutput_array(jsonObj, b6_actionId_obj); + // console.log("b1_keycode_obj ", b1_keycode_obj); + //this.compareBoth(b1_keycode_arr, b1_keycode_obj); + + /* eg: ['K_SPACE','a0','0','NCAPS','Â'] */ //const b1_modifierKey_arr: string[][] = this.get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array_arr(jsonObj, b1_keycode_arr, isCapsused);//_S2 remove&replace + /* eg: ['K_SPACE','a0','0','NCAPS','Â'] */ //const b1_modifierKey_obj: ActionIdOutputBehaviourKeyModi_object[] = this.get_7o_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(jsonObj, b1_keycode_arr, isCapsused); + const b1_modifierKey_obj: ActionIdOutputBehaviourKeyModi_object[] = this.get_7_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(jsonObj, b1_keycode_obj, isCapsused);//_S2 remove&replace // ........................................................................................................................................................................................... - for (let n1 = 0; n1 < b2_prev_deadkeyModifier_arr.length; n1++) { - for (let n2 = 0; n2 < b2_prev_deadkeyModifier_arr[n1].length; n2++) { - for (let n3 = 0; n3 < b2_prev_deadkey_arr.length; n3++) { - for (let n4 = 0; n4 < b4_deadkeyModifier_arr.length; n4++) { - for (let n5 = 0; n5 < b4_deadkeyModifier_arr[n4].length; n5++) { - for (let n6 = 0; n6 < b4_deadkey_arr.length; n6++) { - for (let n7 = 0; n7 < b1_modifierKey_arr.length; n7++) { + //for (let n1 = 0; n1 < b2_prev_deadkeyModifier_arr.length; n1++) { + for (let n1 = 0; n1 < b2_prev_deadkeyModifier_obj.length; n1++) { + //for (let n2 = 0; n2 < b2_prev_deadkeyModifier_arr[n1].length; n2++) { + for (let n2 = 0; n2 < b2_prev_deadkeyModifier_obj[n1].length; n2++) { + //for (let n3 = 0; n3 < b2_prev_deadkey_arr.length; n3++) { + for (let n3 = 0; n3 < b2_prev_deadkey_obj.length; n3++) { + //for (let n4 = 0; n4 < b4_deadkeyModifier_arr.length; n4++) { + for (let n4 = 0; n4 < b4_deadkeyModifier_obj.length; n4++) { + // for (let n5 = 0; n5 < b4_deadkeyModifier_arr[n4].length; n5++) { + for (let n5 = 0; n5 < b4_deadkeyModifier_obj[n4].length; n5++) { + //for (let n6 = 0; n6 < b4_deadkey_arr.length; n6++) { + for (let n6 = 0; n6 < b4_deadkey_obj.length; n6++) { + // for (let n7 = 0; n7 < b1_modifierKey_arr.length; n7++) {//_S2 remove&replace + for (let n7 = 0; n7 < b1_modifierKey_obj.length; n7++) { rule_obj = new Rule( /* rule_type */ "C3", - /* modifier_prev_deadkey*/ this.create_kmn_modifier(b2_prev_deadkeyModifier_arr[n1][n2], isCapsused), - /* prev_deadkey */ this.map_UkeleleKC_To_VK(Number(b2_prev_deadkey_arr[n3][0])), + /* modifier_prev_deadkey*/ //this.create_kmn_modifier(b2_prev_deadkeyModifier_arr[n1][n2], isCapsused), + /* modifier_prev_deadkey*/ this.create_kmn_modifier(b2_prev_deadkeyModifier_obj[n1][n2], isCapsused), + /* prev_deadkey */ //this.map_UkeleleKC_To_VK(Number(b2_prev_deadkey_arr[n3][0])), + /* prev_deadkey */ this.map_UkeleleKC_To_VK(Number(b2_prev_deadkey_obj[n3].key)), /* id_prev_deadkey */ dk_counter_C3++, /* unique A */ 0, - /* modifier_deadkey */ this.create_kmn_modifier(b4_deadkeyModifier_arr[n4][n5], isCapsused), - /* deadkey */ this.map_UkeleleKC_To_VK(Number(b4_deadkey_arr[n6][0])), + /* modifier_deadkey */ // this.create_kmn_modifier(b4_deadkeyModifier_arr[n4][n5], isCapsused), + /* modifier_deadkey */ this.create_kmn_modifier(b4_deadkeyModifier_obj[n4][n5], isCapsused), + /* deadkey */ // this.map_UkeleleKC_To_VK(Number(b4_deadkey_arr[n6][0])), + /* deadkey */ this.map_UkeleleKC_To_VK(Number(b4_deadkey_obj[n6].key)), /* dk for C2*/ 0, /* unique B */ 0, - /* modifier_key*/ b1_modifierKey_arr[n7][3], - /* key */ b1_modifierKey_arr[n7][0], - /* output */ new TextEncoder().encode(b1_modifierKey_arr[n7][4]), + /* modifier_key*/ //b1_modifierKey_arr[n7][3],//_S2 remove&replace + /* key */ //b1_modifierKey_arr[n7][0], + /* output */ //new TextEncoder().encode(b1_modifierKey_arr[n7][4]), + + /* modifier_key*/ b1_modifierKey_obj[n7].modifier, + /* key */ b1_modifierKey_obj[n7].key, + /* output */ new TextEncoder().encode(b1_modifierKey_obj[n7].outchar), ); - if ((b1_modifierKey_arr[n7][4] !== undefined) - && (b1_modifierKey_arr[n7][4] !== "undefined") - && (b1_modifierKey_arr[n7][4] !== "")) { + /* if ((b1_modifierKey_arr[n7][4] !== undefined)//_S2 remove&replace + && (b1_modifierKey_arr[n7][4] !== "undefined") + && (b1_modifierKey_arr[n7][4] !== "")) { + object_array.push(rule_obj); + }*/ + if ((b1_modifierKey_obj[n7].outchar !== undefined) + && (b1_modifierKey_obj[n7].outchar !== "undefined") + && (b1_modifierKey_obj[n7].outchar !== "")) { object_array.push(rule_obj); } } @@ -735,7 +827,8 @@ export class KeylayoutToKmnConverter { * @param search :string - value 'id' to be found * @return a number specifying the index of an actionId */ - public get_ActionIndex__From__ActionId(data: any, search: string): number { + // _S2 get 1 OK + public get_1_ActionIndex__From__ActionId(data: any, search: string): number { for (let i = 0; i < data.keyboard.actions.action.length; i++) { if (data.keyboard.actions.action[i]['@_id'] === search) { return i; @@ -743,14 +836,14 @@ export class KeylayoutToKmnConverter { } return 0; } - /** * @brief member function to find the actionID of a certain state-next pair * @param data :any an object containing all data read from a .keylayout file * @param search :string value 'next' to be found * @return a string containing the actionId of a certain state-next pair */ - public get_ActionID__From__ActionNext(data: any, search: string): string { + // _S2 get 2 OK + public get_2_ActionID__From__ActionNext(data: any, search: string): string { if (search !== "none") { for (let i = 0; i < data.keyboard.actions.action.length; i++) { for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { @@ -769,21 +862,49 @@ export class KeylayoutToKmnConverter { * @param search : (string | number)[][] - an array[keycode,modifier] to be found * @return an array: string[] containing modifiers */ - public get_Modifier_array__From__KeyModifier_array(data: any, search: (string | number)[][]): string[] { + // _S2 get 3 OK + public get_3o_Modifier_array__From__KeyModifier_array_oldArrayType(data: any, search: (string | number)[][]): string[] { const mapIndexArray_2D: string[] = []; + + //console.log("Xsearch old ",search); for (let i = 0; i < search.length; i++) { mapIndexArray_2D.push(data[search[i][1]]); } return mapIndexArray_2D; } + public get_3_Modifier_array__From__KeyModifier_array_retObj(data: any, search: modifierKey_object[]): modifier_object[] { + const returnObjarray1D = []; + // console.log("Xsearch 3",search); + + let returnObject: modifier_object; + for (let i = 0; i < search.length; i++) { + returnObject = { + modifier: (data[search[i].modifier]) + }; + returnObjarray1D.push(returnObject); + } + return returnObjarray1D; + } + + + public get_3_Modifier_array__From__KeyModifier_array(data: any, search: modifierKey_object[]): string[] { + const returnString1D: string[] = []; + for (let i = 0; i < search.length; i++) { + returnString1D.push(data[search[i].modifier]); + } + return returnString1D; + } + + /** * @brief member function to find the output for a certain actionID for state 'none' * @param data :any an object containing all data read from a .keylayout file * @param search :string an actionId to be found * @return a string containing the output character */ - public get_Output__From__ActionId_None(data: any, search: string): string { + // _S2 get 4 OK + public get_4_Output__From__ActionId_None(data: any, search: string): string { let OutputValue: string = ""; for (let i = 0; i < data.keyboard.actions.action.length; i++) { @@ -804,11 +925,13 @@ export class KeylayoutToKmnConverter { * @param search :string[][] - array of [ actionID,state,output] * @return a string[][] containing [Keycode,Keyname,actionId,actionIDIndex, output] */ - public get_KeyActionOutput_array__From__ActionStateOutput_array(data: any, search: string[][]): string[][] { + // _S2 get 5 OK + public get_5o_KeyActionOutput_array__From__ActionStateOutput_array_oldArrayType(data: any, search: string[][]): string[][] { if ((search === undefined) || (search === null)) return []; + const returnarray2D: string[][] = []; for (let k = 0; k < search.length; k++) { for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { @@ -828,6 +951,35 @@ export class KeylayoutToKmnConverter { } return returnarray2D; } + // _S2 get 5 OK + public get_5_KeyActionOutput_array__From__ActionStateOutput_array(data: any, search: idStateOutput_object[]): ActionIdKeyModiOutput_object[] { + + if ((search === undefined) || (search === null)) + return []; + + const returnObjarray1D = []; + let returnObject: ActionIdKeyModiOutput_object; + + for (let k = 0; k < search.length; k++) { + for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { + for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { + if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search[k].id && + data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'] <= KeylayoutToKmnConverter.USED_KEYS_COUNT) { + + returnObject = { + keyCode: data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], + key: this.map_UkeleleKC_To_VK(Number(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), + actionId: data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'], + modifier: data.keyboard.keyMapSet[0].keyMap[i]['@_index'], + outchar: search[k].output + }; + returnObjarray1D.push(returnObject); + } + } + } + } + return returnObjarray1D; + } /** * @brief member function to get an array of all actionId-output pairs for a certain state @@ -835,7 +987,8 @@ export class KeylayoutToKmnConverter { * @param search : string a 'state' to be found * @return an array: string[][] containing all [actionId, state, output] for a certain state */ - public get_ActionStateOutput_array__From__ActionState(data: any, search: string): string[][] { + // _S2 get 6 OK + public get_6o_ActionStateOutput_array__From__ActionState_oldArrayType(data: any, search: string): string[][] { const returnarray2D: string[][] = []; for (let i = 0; i < data.keyboard.actions.action.length; i++) { @@ -851,6 +1004,26 @@ export class KeylayoutToKmnConverter { } return returnarray2D; } + // _S2 get 6 OK + public get_6_ActionStateOutput_array__From__ActionState(data: any, search: string): idStateOutput_object[] { + const returnObjarray1D: idStateOutput_object[] = []; + let returnObject: idStateOutput_object; + + for (let i = 0; i < data.keyboard.actions.action.length; i++) { + for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { + if ((data.keyboard.actions.action[i].when[j]['@_state'] === search)) { + + returnObject = { + id: data.keyboard.actions.action[i]['@_id'], + state: data.keyboard.actions.action[i].when[j]['@_state'], + output: data.keyboard.actions.action[i].when[j]['@_output'] + }; + returnObjarray1D.push(returnObject); + } + } + } + return returnObjarray1D; + } /** * @brief member function to create an 2D array of [KeyName,actionId,behaviour,modifier,output] @@ -859,7 +1032,8 @@ export class KeylayoutToKmnConverter { * @param isCAPSused : boolean flag to indicate if CAPS is used in a keylayout file or not * @return an array: string[][] containing [KeyName,actionId,behaviour,modifier,output] */ - public get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(data: any, search: (boolean | string)[][], isCAPSused: boolean): string[][] { + // _S2 get 7 OK --> tests not OK + public get_7o_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array_oldArrayType(data: any, search: (boolean | string)[][], isCAPSused: boolean): string[][] { const returnarray: string[][] = []; if (!((search === undefined) || (search === null) || (search.length === 0))) { @@ -894,6 +1068,97 @@ export class KeylayoutToKmnConverter { ); return unique_returnarray; } + public get_7o_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(data: any, search: ((boolean | string)[])[], isCAPSused: boolean): ActionIdOutputBehaviourKeyModi_object[] { + const returnarray: string[][] = []; + const returnObjarray1D = []; + let returnObject: ActionIdOutputBehaviourKeyModi_object; + + + if (!((search === undefined) || (search === null) || (search.length === 0))) { + for (let i = 0; i < search.length; i++) { + const behaviour: number = Number(search[i][3]); + for (let j = 0; j < data.keyboard.modifierMap.keyMapSelect[behaviour].modifier.length; j++) { + + returnarray.push([ + // KeyName + String(search[i][1]), + // actionId + String(search[i][2]), + // behaviour + String(search[i][3]), + // modifier + String(this.create_kmn_modifier(data.keyboard.modifierMap.keyMapSelect[behaviour].modifier[j]['@_keys'], isCAPSused)), + // output + String(search[i][4]) + ]); + + returnObject = { + search: "", + actionId: String(search[i][2]), + behaviour: String(search[i][3]), + modifier: String(this.create_kmn_modifier(data.keyboard.modifierMap.keyMapSelect[behaviour].modifier[j]['@_keys'], isCAPSused)), + key: String(search[i][1]), + outchar: String(search[i][4]), + }; + returnObjarray1D.push(returnObject); + } + } + } + // remove duplicates + const unique_Objarray = returnObjarray1D.reduce((unique, o) => { + if (!unique.some(obj => + obj.actionId === o.actionId && + obj.behaviour === o.behaviour && + obj.modifier === o.modifier && + obj.key === o.key && + obj.outchar === o.outchar + )) { + unique.push(o); + } + return unique; + }, []); + + return unique_Objarray; + } + public get_7_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(data: any, search: ActionIdKeyModiOutput_object[], isCAPSused: boolean): ActionIdOutputBehaviourKeyModi_object[] { + + const returnObjarray1D = []; + let returnObject: ActionIdOutputBehaviourKeyModi_object; + + + if (!((search === undefined) || (search === null) || (search.length === 0))) { + for (let i = 0; i < search.length; i++) { + const behaviour: number = Number(search[i].modifier); + for (let j = 0; j < data.keyboard.modifierMap.keyMapSelect[behaviour].modifier.length; j++) { + + returnObject = { + search: "", + actionId: String(search[i].actionId), + behaviour: String(search[i].modifier), + modifier: String(this.create_kmn_modifier(data.keyboard.modifierMap.keyMapSelect[behaviour].modifier[j]['@_keys'], isCAPSused)), + key: String(search[i].key), + outchar: String(search[i].outchar), + }; + returnObjarray1D.push(returnObject); + } + } + } + // remove duplicates + const unique_Objarray = returnObjarray1D.reduce((unique, o) => { + if (!unique.some(obj => + obj.actionId === o.actionId && + obj.behaviour === o.behaviour && + obj.modifier === o.modifier && + obj.key === o.key && + obj.outchar === o.outchar + )) { + unique.push(o); + } + return unique; + }, []); + + return unique_Objarray; + } /** * @brief member function to create an array of [actionID, output, behaviour,keyname,modifier] for a given actionId @@ -904,45 +1169,53 @@ export class KeylayoutToKmnConverter { * @param isCAPSused : boolean - flag to indicate if CAPS is used in a keylayout file or not * @return an array: string[][] containing [actionID,output,actionID, behaviour,keyname,modifier] */ - public get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput(data: any, modi: any, search: string, outchar: string, isCapsused: boolean): string[][] { - const returnarray2D: string[][] = []; + // _S2 get 8 OK + public get_8_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput(data: any, modi: any, search: string, outchar: string, isCapsused: boolean): ActionIdOutputBehaviourKeyModi_object[] { + const returnObjarray1D = []; + let returnObject: ActionIdOutputBehaviourKeyModi_object; if ((search === "") || (search === undefined) || !((isCapsused === true) || (isCapsused === false))) { return []; } - - // loop behaviors (in ukelele it is possible to define multiple modifier combinations that behave in the same) + // loop behaviors (in ukelele it is possible to define multiple modifier combinations that behave in the same way) for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { for (let j = 0; j <= KeylayoutToKmnConverter.USED_KEYS_COUNT; j++) { if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { for (let k = 0; k < modi[data.keyboard.keyMapSet[0].keyMap[i]['@_index']].length; k++) { const behaviour: string = data.keyboard.keyMapSet[0].keyMap[i]['@_index']; - const modifierkmn: string = this.create_kmn_modifier(modi[behaviour][k], isCapsused); - const keyName: string = this.map_UkeleleKC_To_VK(Number(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])); - returnarray2D.push([ - search, - outchar, - data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'], - behaviour, - keyName, - modifierkmn]); + + returnObject = { + search: search, + outchar: outchar, + actionId: data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'], + behaviour: data.keyboard.keyMapSet[0].keyMap[i]['@_index'], + key: this.map_UkeleleKC_To_VK(Number(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), + modifier: this.create_kmn_modifier(modi[behaviour][k], isCapsused), + }; + returnObjarray1D.push(returnObject); } } } } + + //............................................................................. + // remove duplicates - const [unique_returnarray] = returnarray2D.reduce((acc, curr) => { - const [uniq, set] = acc; - if (!set.has(curr.join(','))) { - set.add(curr.join(',')); - uniq.push(curr); + const unique_Objarray = returnObjarray1D.reduce((unique, o) => { + if (!unique.some(obj => + obj.actionId === o.actionId && + obj.outchar === o.outchar && + obj.search === o.search && + obj.behaviour === o.behaviour && + obj.key === o.key && + obj.modifier === o.modifier + )) { + unique.push(o); } - return acc; - }, - [[], new Set()], - ); + return unique; + }, []); - return unique_returnarray; + return unique_Objarray; } /** @@ -951,22 +1224,149 @@ export class KeylayoutToKmnConverter { * @param search : string - an actionId to be found * @return an array: number[][] containing [keycode,behaviour] */ - public get_KeyModifier_array__From__ActionID(data: any, search: string): number[][] { + // _S2 get 9 OK //_S2 remove&replace + public get_9o_KeyModifier_array__From__ActionID_oldArrayType(data: any, search: string): number[][] { const mapIndexArray_2D: number[][] = []; + let returnObject: modifierKey_object; + const mapIndexObject1D: modifierKey_object[] = []; + for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { for (let j = 0; j <= KeylayoutToKmnConverter.USED_KEYS_COUNT; j++) { if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { + mapIndexArray_2D.push([data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], i]); + + returnObject = { + key: data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], + modifier: i + }; + mapIndexObject1D.push(returnObject); } } } return mapIndexArray_2D; } + public get_9_KeyModifier_array__From__ActionID(data: any, search: string): modifierKey_object[] { + const mapIndexArray_2D: number[][] = []; + let returnObject: modifierKey_object; + const mapIndexObject1D: modifierKey_object[] = []; + + for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { + for (let j = 0; j <= KeylayoutToKmnConverter.USED_KEYS_COUNT; j++) { + if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { + + mapIndexArray_2D.push([data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], i]); + + returnObject = { + key: data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], + modifier: i + }; + mapIndexObject1D.push(returnObject); + } + } + } + return mapIndexObject1D; + } /** @internal */ public convert_bound = { convert: this.convert.bind(this), }; + + + + public dummy(into: any) { + } + public compareBoth(arr: any, obj: any,) { + + // compare:----------------------------------- + for (let k = 0; k < obj.length; k++) { + /*console.log("k ", k); + + console.log(" arr", typeof (arr), arr, "----", typeof (arr[k]), arr[k]); + console.log("-------------------- ",); + console.log(" obj", typeof (obj), obj, "----", typeof (obj[k]), obj[k]); + + console.log("arr[k ", arr[k]); + console.log("obj[k].modifier ", obj[k].modifier);*/ + if ( + (arr.length === obj.length) && + + + (arr[k] === obj[k].modifier) + // (arr[k][1] === obj[k].key) + + /*(arr[k][0] === obj[k].key) && + (arr[k][1] === obj[k].actionId) && + (arr[k][2] === obj[k].behaviour) && + (arr[k][3] === obj[k].modifier) && + (arr[k][4] === obj[k].outchar)*/ + + ) { + console.log("IS_EQUAL ",); + } + else console.log("NONONO not_EQUAL \n", + (arr.length === obj.length), obj.length, "<->", arr.length, "\n", + + (arr[k] === obj[k].modifier), obj[k].modifier, "<->", arr[k], "\n", + // (arr[k][1] === obj[k].key), obj[k].key, "<->", arr[k][1], "\n", + + + /* (arr[k][0] === obj[k].key), obj[k].key, "<->", arr[k][0], "\n", + (arr[k][1] === obj[k].actionId), obj[k].actionId, "<->", arr[k][1], "\n", + (arr[k][2] === obj[k].behaviour), obj[k].behaviour, "<->", arr[k][2], "\n", + (arr[k][3] === obj[k].modifier), obj[k].modifier, "<->", arr[k][3], "\n", + (arr[k][4] === obj[k].outchar), obj[k].outchar, "<->", arr[k][4]*/ + ); + } + } + public compareSameType(arr1: any, arr2: any,) { + + + // compare:----------------------------------- + for (let k = 0; k < arr1.length; k++) { + /*console.log("k ", k); + + console.log(" arr1", typeof (arr1), arr1, "----", typeof (arr1[k]), arr1[k]); + console.log("-------------------- ",); + console.log(" arr2", typeof (arr2), arr2, "----", typeof (arr2[k]), arr2[k]); + + console.log("arr1[k ", arr1[k]); + console.log("arr2[k].modifier ", arr2[k].modifier);*/ + if ( + (arr1.length === arr2.length) && + + (arr1[k].search === arr2[k].search) && + (arr1[k].actionId === arr2[k].actionId) && + (arr1[k].behaviour === arr2[k].behaviour) && + (arr1[k].modifier === arr2[k].modifier) && + (arr1[k].key === arr2[k].key) && + (arr1[k].outchar === arr2[k].outchar) + + ) { + console.log("compareSameType: IS_EQUAL ",); + } + else console.log("compareSameType: NONONO not_EQUAL \n", + (arr1.length === arr2.length), arr2.length, "<->", arr1.length, "\n", + + (arr1[k] === arr2[k].modifier), arr2[k].modifier, "<->", arr1[k], "\n", + // (arr1[k][1] === arr2[k].key), arr2[k].key, "<->", arr1[k][1], "\n", + + + /* (arr1[k][0] === arr2[k].key), arr2[k].key, "<->", arr1[k][0], "\n", + (arr1[k][1] === arr2[k].actionId), arr2[k].actionId, "<->", arr1[k][1], "\n", + (arr1[k][2] === arr2[k].behaviour), arr2[k].behaviour, "<->", arr1[k][2], "\n", + (arr1[k][3] === arr2[k].modifier), arr2[k].modifier, "<->", arr1[k][3], "\n", + (arr1[k][4] === arr2[k].outchar), arr2[k].outchar, "<->", arr1[k][4]*/ + ); + } + } + + + + + + } /** diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index a673c4c9e72..f3ac272cec0 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -10,7 +10,7 @@ import 'mocha'; import { assert } from 'chai'; import { compilerTestCallbacks, compilerTestOptions, makePathToFixture } from './helpers/index.js'; -import { KeylayoutToKmnConverter } from '../src/keylayout-to-kmn/keylayout-to-kmn-converter.js'; +import { /*ActionIdOutputBehaviourKeyModi_object,*/ KeylayoutToKmnConverter } from '../src/keylayout-to-kmn/keylayout-to-kmn-converter.js'; import { KeylayoutFileReader } from '../src/keylayout-to-kmn/keylayout-file-reader.js'; import { ConverterMessages } from '../src/converter-messages.js'; import * as NodeAssert from 'node:assert'; @@ -21,6 +21,43 @@ describe('KeylayoutToKmnConverter', function () { compilerTestCallbacks.clear(); }); + // todo remove + describe('RunOneFile', function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const inputFilename = makePathToFixture('../data/Test.keylayout'); + sut.run(inputFilename); + assert.isTrue(true); + }); + + // todo remove + describe('RunOneFile', function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const inputFilename = makePathToFixture('../data/Italian.keylayout'); + sut.run(inputFilename); + assert.isTrue(true); + }); + + // todo remove + describe('RunAllFiles', function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + [ + [makePathToFixture('../data/Italian.keylayout')], + [makePathToFixture('../data/Italian_command.keylayout')], + [makePathToFixture('../data/Swiss_French.keylayout')], + [makePathToFixture('../data/Spanish.keylayout')], + [makePathToFixture('../data/Swiss_German.keylayout')], + [makePathToFixture('../data/US.keylayout')], + [makePathToFixture('../data/Polish.keylayout')], + [makePathToFixture('../data/French.keylayout')], + [makePathToFixture('../data/Latin_American.keylayout')], + // [makePathToFixture('../data/German_complete.keylayout')], + [makePathToFixture('../data/German_complete_reduced.keylayout')], + //[makePathToFixture('../data/German_Standard.keylayout')], + ].forEach(function (files_) { + sut.run(files_[0]); + assert.isTrue(true); + }); + }); describe('run() ', function () { // _S2 can I do this??? - some tests of the run() function might take longer than 2000 ms @@ -253,7 +290,7 @@ describe('KeylayoutToKmnConverter', function () { }); }); - describe('get_Modifier_array__From__KeyModifier_array ', function () { + describe('get_3o_Modifier_array__From__KeyModifier_array_oldArrayType ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Test.keylayout'); @@ -270,9 +307,9 @@ describe('KeylayoutToKmnConverter', function () { ].forEach(function (values) { it((values[1][0] !== null) ? - ("get_Modifier_array__From__KeyModifier_array(['" + values[0][0][0] + "', '" + values[0][0][1] + "'])").padEnd(68, " ") + " should return ['" + values[1][0][0] + "', '" + values[1][0][1] + "']" : - ("get_Modifier_array__From__KeyModifier_array(['" + values[0][0][0] + "', '" + values[0][0][1] + "'])").padEnd(68, " ") + " should return ['" + values[1][0] + "']", async function () { - const result = sut.get_Modifier_array__From__KeyModifier_array(converted.arrayOf_Modifiers, values[0]); + ("get_3o_Modifier_array__From__KeyModifier_array_oldArrayType(['" + values[0][0][0] + "', '" + values[0][0][1] + "'])").padEnd(68, " ") + " should return ['" + values[1][0][0] + "', '" + values[1][0][1] + "']" : + ("get_3o_Modifier_array__From__KeyModifier_array_oldArrayType(['" + values[0][0][0] + "', '" + values[0][0][1] + "'])").padEnd(68, " ") + " should return ['" + values[1][0] + "']", async function () { + const result = sut.get_3o_Modifier_array__From__KeyModifier_array_oldArrayType(converted.arrayOf_Modifiers, values[0]); assert.deepStrictEqual(JSON.stringify(result), JSON.stringify(values[1])); }); }); @@ -281,14 +318,113 @@ describe('KeylayoutToKmnConverter', function () { [[[undefined]], [null]], [[[]], [null]], ].forEach(function (values) { - it(("get_Modifier_array__From__KeyModifier_array([" + values[0][0] + "])").padEnd(68, " ") + " should return ['" + values[1][0] + "']", async function () { - const result = sut.get_Modifier_array__From__KeyModifier_array(converted.arrayOf_Modifiers, values[0]); + it(("get_3o_Modifier_array__From__KeyModifier_array_oldArrayType([" + values[0][0] + "])").padEnd(68, " ") + " should return ['" + values[1][0] + "']", async function () { + const result = sut.get_3o_Modifier_array__From__KeyModifier_array_oldArrayType(converted.arrayOf_Modifiers, values[0]); assert.deepStrictEqual(JSON.stringify(result), JSON.stringify(values[1])); }); }); }); + describe('get_3_Modifier_array__From__KeyModifier_array ', function () { + /*const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sut_r = new KeylayoutFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/Test.keylayout'); + const read = sut_r.read(inputFilename); + const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); + + + //search old [ [ '45', 5 ] ] + //search [ { key: '45', modifier: 5 } ] + + + [ + + //search + [[{ key: '0', modifier: 0 }, ['', 'shift? caps? ']]], + [[{ key: '3', modifier: 0 },['', 'shixft? caps? ']]], + [[{ key: '7', modifier: 0 },['', 'shift? caxps? ']]], + [[{ key: '0', modifier: 2 },['', 'shift? caps? ']]], + [[{ key: '0', modifier: 999 },['', 'shift? caps? ']]], + [[{ key: '999', modifier: null },['', 'shift? caps? ']]], + [[{ key: '0', modifier: -999 },['', 'shift? caps? ']]], + [[{ key: '0', modifier: null },['', 'shift? caps? ']]], + + + + //[['0', 0], [['', 'shift? caps? ']]], + // [[['0', 2]], [['shift? leftShift caps? ', 'anyShift caps?', 'shift leftShift caps ', 'shift? rightShift caps? ']]], + // [[['0', 999]], [null]], + // [[['999',]], [null]], + // [[['0', -999]], [null]], + // [[['0']], [null]], + + + + + ].forEach(function (values) { + + + + console.log("values ", values); + console.log("values[0] ", values[0]); + console.log("values[1] ", values[1]); + //console.log("values[1][0] ", values[1][0]); + // console.log("values[0][0][0] ", values[0][0][0]); + // console.log(" values[0][0][1]", values[0][0][1]); + // console.log("values[1][0][0] ", values[1][0][0]); + // console.log("values [1][0][1]", values[1][0][1]); + + +console.log("XXX get_3_Modifier_array__From__KeyModifier_array(['" , values[0] , "'])", " should return ['" , values[1] , "']"); + + + + it((values[1] !== null) ? + ("get_3_Modifier_array__From__KeyModifier_array(['" + values[0] + "'])").padEnd(68, " ") + " should return ['" + values[1] + "']" : + ("get_3_Modifier_array__From__KeyModifier_array(['" + values[0] + "'])").padEnd(68, " ") + " should return ['" + values[1] + "']", async function () { + //const result = sut.get_3_Modifier_array__From__KeyModifier_array(converted.arrayOf_Modifiers, values[0]); + // assert.deepStrictEqual(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); + + /* [[[[null]], [null]], + [[[undefined]], [null]], + [[[]], [null]], + ].forEach(function (values) { + it(("get_3_Modifier_array__From__KeyModifier_array([" + values[0][0] + "])").padEnd(68, " ") + " should return ['" + values[1][0] + "']", async function () { + const result = sut.get_3_Modifier_array__From__KeyModifier_array(converted.arrayOf_Modifiers, values[0]); + assert.deepStrictEqual(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); + */ + }); - describe('get_KeyModifier_array__From__ActionID ', function () { + describe('get_9_KeyModifier_array__From__ActionID ', function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sut_r = new KeylayoutFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/Test.keylayout'); + const read = sut_r.read(inputFilename); + [ + ['A_16', [{ "key": "32", "modifier": 5 }]], + ['A_19', [{ "key": "45", "modifier": 5 }]], + ['A_18', [{ "key": "24", "modifier": 0 }, { "key": "24", "modifier": 5 }]], + ['unknown', []], + [undefined, []], + [null, []], + [' ', []], + ['', []], + ].forEach(function (values) { + let outstring = '[ '; + for (let i = 0; i < values[1].length; i++) { + outstring = outstring + "[ " + JSON.stringify(values[1][i]) + "], "; + } + it(("get_9_KeyModifier_array__From__ActionID('" + values[0] + "')").padEnd(57, " ") + ' should return ' + outstring.substring(0, outstring.lastIndexOf(']') + 2) + " ]", async function () { + //const result = sut.get_9_KeyModifier_array__From__ActionID_arr(read, String(values[0])); //_S2 remove&replace + const result = sut.get_9_KeyModifier_array__From__ActionID(read, String(values[0])); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); + }); + describe('get_9o_KeyModifier_array__From__ActionID_oldArrayType ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Test.keylayout'); @@ -298,6 +434,8 @@ describe('KeylayoutToKmnConverter', function () { ['A_16', [['32', 5]]], ['A_19', [['45', 5]]], ['A_18', [['24', 0], ['24', 5]]], + + ['unknown', []], [undefined, []], [null, []], @@ -309,15 +447,14 @@ describe('KeylayoutToKmnConverter', function () { for (let i = 0; i < values[1].length; i++) { outstring = outstring + "[ '" + values[1][i][0] + "', " + values[1][i][1].toString() + "], "; } - - it(("get_KeyModifier_array__From__ActionID('" + values[0] + "')").padEnd(57, " ") + ' should return ' + outstring.substring(0, outstring.lastIndexOf(']') + 2) + " ]", async function () { - const result = sut.get_KeyModifier_array__From__ActionID(read, String(values[0])); + it(("get_9o_KeyModifier_array__From__ActionID_oldArrayType('" + values[0] + "')").padEnd(57, " ") + ' should return ' + outstring.substring(0, outstring.lastIndexOf(']') + 2) + " ]", async function () { + const result = sut.get_9o_KeyModifier_array__From__ActionID_oldArrayType(read, String(values[0])); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); }); - describe('get_ActionID__From__ActionNext ', function () { + describe('get_2_ActionID__From__ActionNext ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Test.keylayout'); @@ -337,14 +474,13 @@ describe('KeylayoutToKmnConverter', function () { [undefined, ''], ['unknown', ''], ].forEach(function (values) { - it(("get_ActionID__From__ActionNext('" + values[0] + "')").padEnd(49, " ") + ' should return ' + "'" + values[1] + "'", async function () { - const result = sut.get_ActionID__From__ActionNext(read, String(values[0])); + it(("get_2_ActionID__From__ActionNext('" + values[0] + "')").padEnd(49, " ") + ' should return ' + "'" + values[1] + "'", async function () { + const result = sut.get_2_ActionID__From__ActionNext(read, String(values[0])); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); }); - - describe('get_ActionIndex__From__ActionId ', function () { + describe('get_1_ActionIndex__From__ActionId ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Test.keylayout'); @@ -362,14 +498,14 @@ describe('KeylayoutToKmnConverter', function () { [undefined, 0], ['unknown', 0], ].forEach(function (values) { - it(("get_ActionIndex__From__ActionId('" + values[0] + "')").padEnd(50, " ") + ' should return ' + values[1], async function () { - const result = sut.get_ActionIndex__From__ActionId(read, String(values[0])); + it(("get_1_ActionIndex__From__ActionId('" + values[0] + "')").padEnd(50, " ") + ' should return ' + values[1], async function () { + const result = sut.get_1_ActionIndex__From__ActionId(read, String(values[0])); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); }); - describe('get_Output__From__ActionId_None ', function () { + describe('get_4_Output__From__ActionId_None ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Test.keylayout'); @@ -383,8 +519,8 @@ describe('KeylayoutToKmnConverter', function () { ['unknown', ''], ].forEach(function (values) { it( - ("get_Output__From__ActionId_None('" + values[0] + "')").padEnd(56, " ") + ' should return ' + "'" + values[1] + "'", async function () { - const result = sut.get_Output__From__ActionId_None(read, String(values[0])); + ("get_4_Output__From__ActionId_None('" + values[0] + "')").padEnd(56, " ") + ' should return ' + "'" + values[1] + "'", async function () { + const result = sut.get_4_Output__From__ActionId_None(read, String(values[0])); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); @@ -393,14 +529,14 @@ describe('KeylayoutToKmnConverter', function () { [undefined, ''], [99, ''], ].forEach(function (values) { - it(("get_Output__From__ActionId_None('" + values[0] + "')").padEnd(56, " ") + ' should return ' + values[1], async function () { - const result = sut.get_Output__From__ActionId_None(read, String(values[0])); + it(("get_4_Output__From__ActionId_None('" + values[0] + "')").padEnd(56, " ") + ' should return ' + values[1], async function () { + const result = sut.get_4_Output__From__ActionId_None(read, String(values[0])); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); }); - describe('get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array ', function () { + describe('get_7o_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array_oldArrayType ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Test.keylayout'); @@ -474,12 +610,16 @@ describe('KeylayoutToKmnConverter', function () { ].forEach(function (values) { const isCaps_used = true; - const string_in = "get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(['" + "', '" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "', '" + values[0][0][3] + "', '" + values[0][0][4] + "'])"; + const string_in = "get_7o_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array_oldArrayType(['" + "', '" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "', '" + values[0][0][3] + "', '" + values[0][0][4] + "'])"; const string_out = "['" + "', '" + values[1][0][0] + "', '" + values[1][0][1] + "', '" + values[1][0][2] + "', '" + values[1][0][3] + "', '" + values[1][0][4] + "']"; + + //console.log("FUNCTION NEEDS ", values[0]); + + it((JSON.stringify(values[1]).length > 60) ? 'an array of objects should return an array of objects' : string_in.padEnd(74, " ") + ' should return ' + string_out, async function () { - const result = sut.get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(read, values[0], isCaps_used); + const result = sut.get_7o_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array_oldArrayType(read, values[0], isCaps_used); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); @@ -491,11 +631,11 @@ describe('KeylayoutToKmnConverter', function () { ].forEach(function (values) { const isCaps_used = false; - const string_in = "get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(['" + "', '" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "', '" + values[0][0][3] + "', '" + values[0][0][4] + "'])"; + const string_in = "get_7o_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array_oldArrayType(['" + "', '" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "', '" + values[0][0][3] + "', '" + values[0][0][4] + "'])"; const string_out = "['" + "', '" + values[1][0][0] + "', '" + values[1][0][1] + "', '" + values[1][0][2] + "', '" + values[1][0][3] + "', '" + values[1][0][4] + "']"; it(string_in.padEnd(74, " ") + ' should return ' + string_out, async function () { - const result = sut.get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(read, values[0], isCaps_used); + const result = sut.get_7o_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array_oldArrayType(read, values[0], isCaps_used); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); @@ -505,14 +645,132 @@ describe('KeylayoutToKmnConverter', function () { [null, []], ].forEach(function (values) { const isCaps = true; - it(("get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array([" + values[0] + "])").padEnd(74, " ") + ' should return ' + "[" + values[1] + "]", async function () { - const result = sut.get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(read, values[0], isCaps); + it(("get_7o_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array_oldArrayType([" + values[0] + "])").padEnd(74, " ") + ' should return ' + "[" + values[1] + "]", async function () { + const result = sut.get_7o_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array_oldArrayType(read, values[0], isCaps); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); }); + //_S2 Todo finish !! + describe('get_7_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array ', function () { + /*const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sut_r = new KeylayoutFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/Test.keylayout'); + const read = sut_r.read(inputFilename);*/ - describe('get_ActionStateOutput_array__From__ActionState ', function () { + const b1_keycode_arr = [ + // _S2 Todo write in object-fornm + + ['49', 'K_SPACE', 'A_0', '0', 'ˆ'], + ['49', 'K_SPACE', 'A_0', '1', 'ˆ'], + ['49', 'K_SPACE', 'A_0', '2', 'ˆ'], + ['6', 'K_Z', 'A_0', '4', 'ˆ'], + ['25', 'K_9', 'A_0', '4', 'ˆ'], + ['43', 'K_COMMA', 'A_0', '4', 'ˆ'], + ['49', 'K_SPACE', 'A_0', '3', 'ˆ'], + ['0', 'K_A', 'A_1', '2', 'Â'], + ['0', 'K_A', 'A_1', '1', 'Â'], + ['14', 'K_E', 'A_10', '0', 'ê'], + ['34', 'K_I', 'A_11', '0', 'î'], + ['31', 'K_O', 'A_13', '0', 'ô'], + ['32', 'K_U', 'A_14', '0', 'û'], + ['14', 'K_E', 'A_2', '2', 'Ê'], + ['14', 'K_E', 'A_2', '1', 'Ê'], + ['34', 'K_I', 'A_3', '2', 'Î'], + ['34', 'K_I', 'A_3', '1', 'Î'], + ['31', 'K_O', 'A_5', '2', 'Ô'], + ['31', 'K_O', 'A_5', '1', 'Ô'], + ['32', 'K_U', 'A_6', '2', 'Û'], + ['32', 'K_U', 'A_6', '1', 'Û'], + ['0', 'K_A', 'A_9', '0', 'â']/**/ + ]; + const b1_modifierKey_arr = [ + /* ['K_SPACE', 'A_0', '0', 'NCAPS', 'ˆ'], + ... + ['K_A', 'A_9', '0', 'NCAPS', 'â'],*/ + { "search": "", "actionId": "A_0", "behaviour": "0", "modifier": "NCAPS", "key": "K_SPACE", "outchar": "ˆ" }, + { "search": "", "actionId": "A_0", "behaviour": "1", "modifier": "CAPS", "key": "K_SPACE", "outchar": "ˆ" }, + { "search": "", "actionId": "A_0", "behaviour": "2", "modifier": "NCAPS SHIFT", "key": "K_SPACE", "outchar": "ˆ" }, + { "search": "", "actionId": "A_0", "behaviour": "2", "modifier": "SHIFT CAPS", "key": "K_SPACE", "outchar": "ˆ" }, + { "search": "", "actionId": "A_0", "behaviour": "4", "modifier": "NCAPS SHIFT RALT", "key": "K_Z", "outchar": "ˆ" }, + { "search": "", "actionId": "A_0", "behaviour": "4", "modifier": "NCAPS SHIFT RALT", "key": "K_9", "outchar": "ˆ" }, + { "search": "", "actionId": "A_0", "behaviour": "4", "modifier": "NCAPS SHIFT RALT", "key": "K_COMMA", "outchar": "ˆ" }, + { "search": "", "actionId": "A_0", "behaviour": "3", "modifier": "NCAPS RALT CTRL", "key": "K_SPACE", "outchar": "ˆ" }, + { "search": "", "actionId": "A_0", "behaviour": "3", "modifier": "NCAPS CTRL", "key": "K_SPACE", "outchar": "ˆ" }, + { "search": "", "actionId": "A_1", "behaviour": "2", "modifier": "NCAPS SHIFT", "key": "K_A", "outchar": "Â" }, + { "search": "", "actionId": "A_1", "behaviour": "2", "modifier": "SHIFT CAPS", "key": "K_A", "outchar": "Â" }, + { "search": "", "actionId": "A_1", "behaviour": "1", "modifier": "CAPS", "key": "K_A", "outchar": "Â" }, + { "search": "", "actionId": "A_10", "behaviour": "0", "modifier": "NCAPS", "key": "K_E", "outchar": "ê" }, + { "search": "", "actionId": "A_11", "behaviour": "0", "modifier": "NCAPS", "key": "K_I", "outchar": "î" }, + { "search": "", "actionId": "A_13", "behaviour": "0", "modifier": "NCAPS", "key": "K_O", "outchar": "ô" }, + { "search": "", "actionId": "A_14", "behaviour": "0", "modifier": "NCAPS", "key": "K_U", "outchar": "û" }, + { "search": "", "actionId": "A_2", "behaviour": "2", "modifier": "NCAPS SHIFT", "key": "K_E", "outchar": "Ê" }, + { "search": "", "actionId": "A_2", "behaviour": "2", "modifier": "SHIFT CAPS", "key": "K_E", "outchar": "Ê" }, + { "search": "", "actionId": "A_2", "behaviour": "1", "modifier": "CAPS", "key": "K_E", "outchar": "Ê" }, + { "search": "", "actionId": "A_3", "behaviour": "2", "modifier": "NCAPS SHIFT", "key": "K_I", "outchar": "Î" }, + { "search": "", "actionId": "A_3", "behaviour": "2", "modifier": "SHIFT CAPS", "key": "K_I", "outchar": "Î" }, + { "search": "", "actionId": "A_3", "behaviour": "1", "modifier": "CAPS", "key": "K_I", "outchar": "Î" }, + { "search": "", "actionId": "A_5", "behaviour": "2", "modifier": "NCAPS SHIFT", "key": "K_O", "outchar": "Ô" }, + { "search": "", "actionId": "A_5", "behaviour": "2", "modifier": "SHIFT CAPS", "key": "K_O", "outchar": "Ô" }, + { "search": "", "actionId": "A_5", "behaviour": "1", "modifier": "CAPS", "key": "K_O", "outchar": "Ô" }, + { "search": "", "actionId": "A_6", "behaviour": "2", "modifier": "NCAPS SHIFT", "key": "K_U", "outchar": "Û" }, + { "search": "", "actionId": "A_6", "behaviour": "2", "modifier": "SHIFT CAPS", "key": "K_U", "outchar": "Û" }, + { "search": "", "actionId": "A_6", "behaviour": "1", "modifier": "CAPS", "key": "K_U", "outchar": "Û" }, + { "search": "", "actionId": "A_9", "behaviour": "0", "modifier": "NCAPS", "key": "K_A", "outchar": "â" } + ]; + + [[b1_keycode_arr, b1_modifierKey_arr], + [[['49', 'K_SPACE', 'A_0', '0', 'ˆ']], [['K_SPACE', 'A_0', '0', 'NCAPS', 'ˆ']]], + [[['49', 'K_SPACE', 'A_0', '0', '']], [['K_SPACE', 'A_0', '0', 'NCAPS', '']]], + [[['49', 'K_SPACE', 'A_0', '', 'ˆ']], [['K_SPACE', 'A_0', '', 'NCAPS', 'ˆ']]], + [[['49', 'K_SPACE', '', '0', 'ˆ']], [['K_SPACE', '', '0', 'NCAPS', 'ˆ']]], + [[['49', '', 'A_0', '0', 'ˆ']], [['', 'A_0', '0', 'NCAPS', 'ˆ']]], + [[['', 'K_SPACE', 'A_0', '0', 'ˆ']], [['K_SPACE', 'A_0', '0', 'NCAPS', 'ˆ']]], + [[['', 'K_SPACE', 'A_0', '0', 'ˆ']], [['K_SPACE', 'A_0', '0', 'NCAPS', 'ˆ']]], + [[['', '', '', '', '']], [['', '', '', 'NCAPS', '']]], + ].forEach(function (values) { + + /* // _S2 const isCaps_used = true; + const string_in = "get_7_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(['" + "', '" + values[0][0] + "', '" + values[0][1] + "', '" + values[0][2] + "', '" + values[0][3] + "', '" + values[0][4] + "'])"; + const string_out = "['" + "', '" + values[1][0] + "', '" + values[1][1] + "', '" + values[1][2] + "', '" + values[1][3] + "', '" + values[1][4] + "']"; + + it((JSON.stringify(values[1]).length > 60) ? 'an array of objects should return an array of objects' : + string_in.padEnd(74, " ") + ' should return ' + string_out, async function () { + const result = sut.get_7_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(read, values[0], isCaps_used); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + });*/ + }); + + [[[['49', 'K_SPACE', 'A_0', '0', 'ˆ']], [['K_SPACE', 'A_0', '0', '', 'ˆ']]], + [[['49', 'K_SPACE', 'A_0', '0', '']], [['K_SPACE', 'A_0', '0', '', '']]], + [[['', 'K_SPACE', 'A_0', '0', 'ˆ']], [['K_SPACE', 'A_0', '0', '', 'ˆ']]], + [[['', '', '', '', '']], [['', '', '', '', '']]], + ].forEach(function (values) { + + /* const isCaps_used = false; // _S2 add again + const string_in = "get_7_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(['" + "', '" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "', '" + values[0][0][3] + "', '" + values[0][0][4] + "'])"; + const string_out = "['" + "', '" + values[1][0][0] + "', '" + values[1][0][1] + "', '" + values[1][0][2] + "', '" + values[1][0][3] + "', '" + values[1][0][4] + "']"; + + it(string_in.padEnd(74, " ") + ' should return ' + string_out, async function () { + const result = sut.get_7_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(read, values[0], isCaps_used); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + });*/ + }); + + [[[], []], + [undefined, []], + [null, []], + ].forEach(function (values) { + /* const isCaps = true; + it(("get_7_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array([" + values[0] + "])").padEnd(74, " ") + ' should return ' + "[" + values[1] + "]", async function () { + const result = sut.get_7_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(read, values[0], isCaps); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + });*/ + }); + }); + + + describe('get_6o_ActionStateOutput_array__From__ActionState_oldArrayType ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Test.keylayout'); @@ -550,15 +808,64 @@ describe('KeylayoutToKmnConverter', function () { [undefined, [],], ].forEach(function (values) { it((JSON.stringify(values[1]).length > 30) ? - ("get_ActionStateOutput_array__From__ActionState('" + values[0] + "')").padEnd(60, " ") + ' should return an array of objects' : - ("get_ActionStateOutput_array__From__ActionState('" + values[0] + "')").padEnd(60, " ") + ' should return ' + "'" + JSON.stringify(values[1]) + "'", async function () { - const result = sut.get_ActionStateOutput_array__From__ActionState(read, String(values[0])); + ("get_6o_ActionStateOutput_array__From__ActionState_oldArrayType('" + values[0] + "')").padEnd(60, " ") + ' should return an array of objects' : + ("get_6o_ActionStateOutput_array__From__ActionState_oldArrayType('" + values[0] + "')").padEnd(60, " ") + ' should return ' + "'" + JSON.stringify(values[1]) + "'", async function () { + const result = sut.get_6o_ActionStateOutput_array__From__ActionState_oldArrayType(read, String(values[0])); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); + }); + + describe('get_6_ActionStateOutput_array__From__ActionState ', function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sut_r = new KeylayoutFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/Test.keylayout'); + const read = sut_r.read(inputFilename); + + [['1', [ + { "id": "A_0", "state": "1", "output": "ˆ" }, + { "id": "A_1", "state": "1", "output": "Â" }, + { "id": "A_10", "state": "1", "output": "ê" }, + { "id": "A_11", "state": "1", "output": "î" }, + { "id": "A_13", "state": "1", "output": "ô" }, + { "id": "A_14", "state": "1", "output": "û" }, + { "id": "A_2", "state": "1", "output": "Ê" }, + { "id": "A_3", "state": "1", "output": "Î" }, + { "id": "A_5", "state": "1", "output": "Ô" }, + { "id": "A_6", "state": "1", "output": "Û" }, + { "id": "A_9", "state": "1", "output": "â" } + ],], + ['2', [ + { "id": "A_0", "state": "2", "output": "`" }, + { "id": "A_1", "state": "2", "output": "À" }, + { "id": "A_10", "state": "2", "output": "è" }, + { "id": "A_11", "state": "2", "output": "ì" }, + { "id": "A_13", "state": "2", "output": "ò" }, + { "id": "A_14", "state": "2", "output": "ù" }, + { "id": "A_2", "state": "2", "output": "È" }, + { "id": "A_3", "state": "2", "output": "Ì" }, + { "id": "A_5", "state": "2", "output": "Ò" }, + { "id": "A_6", "state": "2", "output": "Ù" }, + { "id": "A_9", "state": "2", "output": "à" } + ],], + ['789', [],], + ['', [],], + [' ', [],], + [123, [],], + [null, [],], + [undefined, [],], + ].forEach(function (values) { + it((JSON.stringify(values[1]).length > 30) ? + ("get_6_ActionStateOutput_array__From__ActionState('" + values[0] + "')").padEnd(60, " ") + ' should return an array of objects' : + ("get_6_ActionStateOutput_array__From__ActionState('" + values[0] + "')").padEnd(60, " ") + ' should return ' + "'" + JSON.stringify(values[1]) + "'", async function () { + const result = sut.get_6_ActionStateOutput_array__From__ActionState(read, String(values[0])); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); }); - describe('get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput ', function () { + + describe('get_8_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Test.keylayout'); @@ -566,37 +873,38 @@ describe('KeylayoutToKmnConverter', function () { const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); [ - ['A_1', 'A', true, [ - ['A_1', 'A', 'A_1', '1', 'K_A', 'CAPS'], - ['A_1', 'A', 'A_1', '2', 'K_A', 'NCAPS SHIFT'], - ['A_1', 'A', 'A_1', '2', 'K_A', 'SHIFT CAPS'], - ] + ['A_1', 'A', true, + [{ "search": "A_1", "outchar": "A", "actionId": "A_1", "behaviour": "1", "key": "K_A", "modifier": "CAPS" }, + { "search": "A_1", "outchar": "A", "actionId": "A_1", "behaviour": "2", "key": "K_A", "modifier": "NCAPS SHIFT" }, + { "search": "A_1", "outchar": "A", "actionId": "A_1", "behaviour": "2", "key": "K_A", "modifier": "SHIFT CAPS" }] ], - ['A_1', 'A', false, [ - ['A_1', 'A', 'A_1', '1', 'K_A', 'CAPS'], - ['A_1', 'A', 'A_1', '2', 'K_A', 'SHIFT'], - ['A_1', 'A', 'A_1', '2', 'K_A', 'SHIFT CAPS']] + ['A_1', 'A', false, + [{ "search": "A_1", "outchar": "A", "actionId": "A_1", "behaviour": "1", "key": "K_A", "modifier": "CAPS" }, + { "search": "A_1", "outchar": "A", "actionId": "A_1", "behaviour": "2", "key": "K_A", "modifier": "SHIFT" }, + { "search": "A_1", "outchar": "A", "actionId": "A_1", "behaviour": "2", "key": "K_A", "modifier": "SHIFT CAPS" }] ], - ['A_9', 'a', true, [['A_9', 'a', 'A_9', '0', 'K_A', 'NCAPS']]], - ['A_9', 'a', false, [['A_9', 'a', 'A_9', '0', 'K_A', '']]], - ['A_9', 'a', , [['A_9', 'a', 'A_9', '0', 'K_A', '']]], - ['A_9', '', true, [['A_9', '', 'A_9', '0', 'K_A', 'NCAPS']]], - ['A_9', '', false, [['A_9', '', 'A_9', '0', 'K_A', '']]], + ['A_9', 'a', true, [{ "search": "A_9", "outchar": "a", "actionId": "A_9", "behaviour": "0", "key": "K_A", "modifier": "NCAPS" }]], + ['A_9', 'a', false, [{ "search": "A_9", "outchar": "a", "actionId": "A_9", "behaviour": "0", "key": "K_A", "modifier": "" }]], + ['A_9', 'a', , [{ "search": "A_9", "outchar": "a", "actionId": "A_9", "behaviour": "0", "key": "K_A", "modifier": "" }]], + ['A_9', '', true, [{ "search": "A_9", "outchar": "", "actionId": "A_9", "behaviour": "0", "key": "K_A", "modifier": "NCAPS" }]], + ['A_9', '', false, [{ "search": "A_9", "outchar": "", "actionId": "A_9", "behaviour": "0", "key": "K_A", "modifier": "" }]], ['', 'a', true, []], ['', 'a', false, []], ['', '', , []], ].forEach(function (values) { it((JSON.stringify(values[3]).length > 35) ? - ("get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput('" + values[0] + "', '" + values[1] + "', " + values[2] + ")").padEnd(67, " ") + ' should return an array of objects' : - ("get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput('" + values[0] + "', '" + values[1] + "', " + values[2] + ")").padEnd(67, " ") + ' should return ' + "'" + JSON.stringify(values[3]) + "'", async function () { - const result = sut.get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput(read, converted.arrayOf_Modifiers, String(values[0]), String(values[1]), Boolean(values[2])); + ("get_8_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput('" + values[0] + "', '" + values[1] + "', " + values[2] + ")").padEnd(67, " ") + ' should return an array of objects' : + ("get_8_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput('" + values[0] + "', '" + values[1] + "', " + values[2] + ")").padEnd(67, " ") + ' should return ' + "'" + JSON.stringify(values[3]) + "'", async function () { + const result = sut.get_8_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput(read, converted.arrayOf_Modifiers, String(values[0]), String(values[1]), Boolean(values[2])); + console.log("result ", result); + assert.equal(JSON.stringify(result), JSON.stringify(values[3])); }); }); }); - describe('get_KeyActionOutput_array__From__ActionStateOutput_array ', function () { + describe('get_5o_KeyActionOutput_array__From__ActionStateOutput_array_oldArrayType ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Test.keylayout'); @@ -643,8 +951,8 @@ describe('KeylayoutToKmnConverter', function () { [[b6_actionId_arr, b1_keycode_arr], ].forEach(function (values) { - it(("get_KeyActionOutput_array__From__ActionStateOutput_array([['" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "'],..])").padEnd(73, " ") + '1 should return an array of objects', async function () { - const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0]); + it(("get_5o_KeyActionOutput_array__From__ActionStateOutput_array_oldArrayType([['" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "'],..])").padEnd(73, " ") + '1 should return an array of objects', async function () { + const result = sut.get_5o_KeyActionOutput_array__From__ActionStateOutput_array_oldArrayType(read, values[0]); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); @@ -672,8 +980,8 @@ describe('KeylayoutToKmnConverter', function () { [[['A_0', '1', '']], oneEntryResultNoOutput], [[['A_0', '', 'ˆ']], oneEntryResult], ].forEach(function (values) { - it(("get_KeyActionOutput_array__From__ActionStateOutput_array(['" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "'])").padEnd(73, " ") + '2 should return an array of objects', async function () { - const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0]); + it(("get_5o_KeyActionOutput_array__From__ActionStateOutput_array_oldArrayType(['" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "'])").padEnd(73, " ") + '2 should return an array of objects', async function () { + const result = sut.get_5o_KeyActionOutput_array__From__ActionStateOutput_array_oldArrayType(read, values[0]); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); @@ -682,8 +990,8 @@ describe('KeylayoutToKmnConverter', function () { [[['', '', '']], []], [[[' ', ' ', '']], []], ].forEach(function (values) { - it(("get_KeyActionOutput_array__From__ActionStateOutput_array(['" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "'])").padEnd(73, " ") + ' should return ' + "'[" + values[1] + "]'", async function () { - const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0]); + it(("get_5o_KeyActionOutput_array__From__ActionStateOutput_array_oldArrayType(['" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "'])").padEnd(73, " ") + ' should return ' + "'[" + values[1] + "]'", async function () { + const result = sut.get_5o_KeyActionOutput_array__From__ActionStateOutput_array_oldArrayType(read, values[0]); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); @@ -692,11 +1000,128 @@ describe('KeylayoutToKmnConverter', function () { [undefined, []], [null, []], ].forEach(function (values) { - it(("get_KeyActionOutput_array__From__ActionStateOutput_array(" + values[0] + ")").padEnd(73, " ") + ' should return ' + "'[" + values[1] + "]'", async function () { - const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0]); + it(("get_5o_KeyActionOutput_array__From__ActionStateOutput_array_oldArrayType(" + values[0] + ")").padEnd(73, " ") + ' should return ' + "'[" + values[1] + "]'", async function () { + const result = sut.get_5o_KeyActionOutput_array__From__ActionStateOutput_array_oldArrayType(read, values[0]); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); + }); + + describe('get_5_KeyActionOutput_array__From__ActionStateOutput_array ', function () { + /* const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sut_r = new KeylayoutFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/Test.keylayout'); + const read = sut_r.read(inputFilename); + + const b6_actionId_arr = [ +*/ + + // [{ "id": "A_0", "state": "1", "output": "ˆ" }], + // [{ "id": "A_1", "state": "1", "output": "Â" }], + // [{ "id": "A_10", "state": "1", "output": "ê" }], + // [{ "id": "A_11", "state": "1", "output": "î" }], + // [{ "id": "A_13", "state": "1", "output": "ô" }], + // [{ "id": "A_14", "state": "1", "output": "û" }], + // // [{ "id": "A_2", "state": "1", "output": "Ê" }], + // [{ "id": "A_3", "state": "1", "output": "Î" }], + // [{ "id": "A_5", "state": "1", "output": "Ô" }], + // [{ "id": "A_6", "state": "1", "output": "Û" }], + // [{ "id": "A_9", "state": "1", "output": "â" }] + + /* ['A_0', '1', 'ˆ'], + ['A_1', '1', 'Â'], + ['A_10', '1', 'ê'], + ['A_11', '1', 'î'], + ['A_13', '1', 'ô'], + ['A_14', '1', 'û'], + ['A_2', '1', 'Ê'], + ['A_3', '1', 'Î'], + ['A_5', '1', 'Ô'], + ['A_6', '1', 'Û'], + ['A_9', '1', 'â'] + ]; + const b1_keycode_arr = [ + ['49', 'K_SPACE', 'A_0', '0', 'ˆ'], + ['49', 'K_SPACE', 'A_0', '1', 'ˆ'], + ['49', 'K_SPACE', 'A_0', '2', 'ˆ'], + ['49', 'K_SPACE', 'A_0', '3', 'ˆ'], + ['6', 'K_Z', 'A_0', '4', 'ˆ'], + ['25', 'K_9', 'A_0', '4', 'ˆ'], + ['43', 'K_COMMA', 'A_0', '4', 'ˆ'], + + ['0', 'K_A', 'A_1', '1', 'Â'], + ['0', 'K_A', 'A_1', '2', 'Â'], + ['14', 'K_E', 'A_10', '0', 'ê'], + ['34', 'K_I', 'A_11', '0', 'î'], + ['31', 'K_O', 'A_13', '0', 'ô'], + ['32', 'K_U', 'A_14', '0', 'û'], + ['14', 'K_E', 'A_2', '1', 'Ê'], + ['14', 'K_E', 'A_2', '2', 'Ê'], + ['34', 'K_I', 'A_3', '1', 'Î'], + ['34', 'K_I', 'A_3', '2', 'Î'], + ['31', 'K_O', 'A_5', '1', 'Ô'], + ['31', 'K_O', 'A_5', '2', 'Ô'], + ['32', 'K_U', 'A_6', '1', 'Û'], + ['32', 'K_U', 'A_6', '2', 'Û'], + ['0', 'K_A', 'A_9', '0', 'â'] + ]; + + [[b6_actionId_arr, b1_keycode_arr], + ].forEach(function (values) { + it(("get_5_KeyActionOutput_array__From__ActionStateOutput_array([['" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "'],..])").padEnd(73, " ") + '1 should return an array of objects', async function () { + const result = sut.get_5_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0]); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); + + const oneEntryResult = [ + ['49', 'K_SPACE', 'A_0', '0', 'ˆ'], + ['49', 'K_SPACE', 'A_0', '1', 'ˆ'], + ['49', 'K_SPACE', 'A_0', '2', 'ˆ'], + ['49', 'K_SPACE', 'A_0', '3', 'ˆ'], + ['6', 'K_Z', 'A_0', '4', 'ˆ'], + ['25', 'K_9', 'A_0', '4', 'ˆ'], + ['43', 'K_COMMA', 'A_0', '4', 'ˆ'] + ]; + const oneEntryResultNoOutput = [ + ['49', 'K_SPACE', 'A_0', '0', ''], + ['49', 'K_SPACE', 'A_0', '1', ''], + ['49', 'K_SPACE', 'A_0', '2', ''], + ['49', 'K_SPACE', 'A_0', '3', ''], + ['6', 'K_Z', 'A_0', '4', ''], + ['25', 'K_9', 'A_0', '4', ''], + ['43', 'K_COMMA', 'A_0', '4', ''] + ]; + + [[[['A_0', '1', 'ˆ']], oneEntryResult], + [[['A_0', '1', '']], oneEntryResultNoOutput], + [[['A_0', '', 'ˆ']], oneEntryResult], + ].forEach(function (values) { + it(("get_5_KeyActionOutput_array__From__ActionStateOutput_array(['" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "'])").padEnd(73, " ") + '2 should return an array of objects', async function () { + const result = sut.get_5_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0]); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); + + [[[['', '1', 'ˆ']], []], + [[['', '', '']], []], + [[[' ', ' ', '']], []], + ].forEach(function (values) { + it(("get_5_KeyActionOutput_array__From__ActionStateOutput_array(['" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "'])").padEnd(73, " ") + ' should return ' + "'[" + values[1] + "]'", async function () { + const result = sut.get_5_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0]); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); + + [[[], []], + [undefined, []], + [null, []], + ].forEach(function (values) { + it(("get_5_KeyActionOutput_array__From__ActionStateOutput_array(" + values[0] + ")").padEnd(73, " ") + ' should return ' + "'[" + values[1] + "]'", async function () { + const result = sut.get_5_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0]); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + });*/ }); }); From 9cc6eccceea2aedeb73c1ea3198e55bc2d57ad54 Mon Sep 17 00:00:00 2001 From: Sabine Date: Fri, 25 Jul 2025 19:12:22 +0200 Subject: [PATCH 156/251] feat(developer): use Arrays of objects instead of 2D arrays finished, tests changed accordingly --- .../keylayout-to-kmn-converter.ts | 556 +++--------- .../src/keylayout-to-kmn/kmn-file-writer.ts | 2 +- .../test/keylayout-to-kmn-converter.tests.ts | 840 +++++------------- .../kmc-convert/test/kmn-file-writer.tests.ts | 1 - 4 files changed, 310 insertions(+), 1089 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index b951a324091..a90aeff27a6 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -26,49 +26,46 @@ export interface convert_object { arrayOf_Modifiers: string[][], arrayOf_Rules: Rule[], }; -//_S2 do I need search??? -export interface ActionIdOutputBehaviourKeyModi_object { - search: string, - actionId: string, - outchar: string, - behaviour: string, - key: string, - modifier: string, -}; - - -export interface ActionIdKeyModiOutput_object { - actionId: string, - keyCode: string, - key: string, - modifier: string, - outchar: string; -}; -export interface modifierKey_object { - key: string; // _S2 todo change everywhere!!! - modifier: number, -}; -export interface modifier_object { - modifier: string, -}; -export interface behaviourKey_object { - behaviour: string, - key: string, +export interface allArrayContents_object { + actionId?: string, + keyCode?: string, + key?: string, + behaviour?: string, + modifier?: string, + outchar?: string; }; + export interface idStateOutput_object { id: string, state: string, output: string, }; -export class KeylayoutToKmnConverter { +/** + * @brief member function to find the number of keys defined in a .keykayout file. + * We process 'MAX_KEY_COUNT' keys at maximum. In case a keylayout has fewer keys defined, we use that smaller number of keys (USE_KEY_COUNT) + * @param data data read from keylayout file + * @return static variable USE_KEY_COUNT holding the number of keys used in a .keykayout file. + */ +export function find_usedKeysCount(data: any): number { + let USE_KEY_COUNT = KeylayoutToKmnConverter.MAX_KEY_COUNT; + for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { + if (data.keyboard.keyMapSet[0].keyMap[i].key.length < USE_KEY_COUNT) { + // set the max to n-1 (use key 0 -> nth-1) + USE_KEY_COUNT = data.keyboard.keyMapSet[0].keyMap[i].key.length - 1; + } + } + return USE_KEY_COUNT; +} +export class KeylayoutToKmnConverter { static readonly INPUT_FILE_EXTENSION = '.keylayout'; static readonly OUTPUT_FILE_EXTENSION = '.kmn'; - static readonly USED_KEYS_COUNT = 49; // we use key Nr 0 (A) -> key Nr 49 (Space) - static readonly MAX_CTRL_CHARACTER = 32; static readonly SKIP_COMMENTED_LINES = false; + static readonly MAX_CTRL_CHARACTER = 32; + static readonly MAX_KEY_COUNT = 49; // At most we use key Nr 0 (A) -> key Nr 49 (Space) + static USE_KEY_COUNT = KeylayoutToKmnConverter.MAX_KEY_COUNT; // we use key Nr 0 (A) -> highest available key of .keylayout file private options: CompilerOptions; @@ -94,6 +91,11 @@ export class KeylayoutToKmnConverter { return null; } + if (outputFilename === null) { + this.callbacks.reportMessage(ConverterMessages.Error_OutputFilenameIsRequired()); + return null; + } + const KeylayoutReader = new KeylayoutFileReader(this.callbacks/*, this.options*/); const jsonO: KeylayoutXMLSourceFile = KeylayoutReader.read(inputFilename); @@ -162,6 +164,10 @@ export class KeylayoutToKmnConverter { } modifierBehavior.push(singleModifierSet); } + + // fix the amount of processable keys to the maximun nr of keys of a keyMap to avoid processing more keys than defined + KeylayoutToKmnConverter.USE_KEY_COUNT = find_usedKeysCount(jsonObj); + // fill rules into arrayOf_Rules of data_object return this.createRuleData(data_object, jsonObj); } @@ -181,11 +187,13 @@ export class KeylayoutToKmnConverter { let dk_counter_C2: number = 0; let action_id: string; + //find_max_used_keycount(data_ukelele) // check if we use CAPS in a modifier throughout the .keylayout file. In this case we need to add NCAPS const isCapsused: boolean = this.checkIfCapsIsUsed(data_ukelele.arrayOf_Modifiers); - // loop keys 0-50 (= all keys we use) - for (let j = 0; j <= KeylayoutToKmnConverter.USED_KEYS_COUNT; j++) { + + // loop keys 0-49 (= all keys we use) + for (let j = 0; j <= KeylayoutToKmnConverter.USE_KEY_COUNT; j++) { // loop behaviors (in ukelele it is possible to define multiple modifier combinations that behave in the same way) for (let i = 0; i < jsonObj.keyboard.keyMapSet[0].keyMap.length; i++) { @@ -241,13 +249,13 @@ export class KeylayoutToKmnConverter { for (let l = 0; l < data_ukelele.arrayOf_Modifiers[i].length; l++) { - if ((this.get_4_Output__From__ActionId_None(jsonObj, action_id) !== undefined) - && (this.get_4_Output__From__ActionId_None(jsonObj, action_id) !== "")) { + if ((this.get_Output__From__ActionId_None(jsonObj, action_id) !== undefined) + && (this.get_Output__From__ActionId_None(jsonObj, action_id) !== "")) { - const outputchar: string = this.get_4_Output__From__ActionId_None(jsonObj, action_id); + const outputchar: string = this.get_Output__From__ActionId_None(jsonObj, action_id); - const b1_modifierKey_obj: ActionIdOutputBehaviourKeyModi_object[] = - this.get_8_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput(jsonObj, data_ukelele.arrayOf_Modifiers, action_id, outputchar, isCapsused); + const b1_modifierKey_obj: allArrayContents_object[] = + this.get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput(jsonObj, data_ukelele.arrayOf_Modifiers, action_id, outputchar, isCapsused); for (let m = 0; m < b1_modifierKey_obj.length; m++) { rule_obj = new Rule( @@ -282,7 +290,7 @@ export class KeylayoutToKmnConverter { // https://docs.google.com/document/d/12J3NGO6RxIthCpZDTR8FYSRjiMgXJDLwPY2z9xqKzJ0/edit?tab=t.0#heading=h.g7jwx3lx0ydd ......... // ............................................................................................................................... - const b1_actionIndex: number = this.get_1_ActionIndex__From__ActionId(jsonObj, action_id); + const b1_actionIndex: number = this.get_ActionIndex__From__ActionId(jsonObj, action_id); // with action_id from above loop all 'action' and search for a state(none)-next-pair ............................................................................................................ // e.g. in Block 5: find for action id a18 ...................................................................................................................... @@ -299,37 +307,26 @@ export class KeylayoutToKmnConverter { // Data of Block Nr 4 ..................................................................................................................................................................... // with present action_id (a18) find all keycode-behaviour-pairs that use this action (a18) => (keymapIndex 0/keycode 24 and keymapIndex 3/keycode 24) .................................... // from these create an array of modifier combinations e.g. [['','caps?'], ['Caps']] ..................................................................................................... - /* eg: [['24', 0], ['24', 3]] */ // const b4_deadkey_arr: number[][] = this.get_9o_KeyModifier_array__From__ActionID_oldArrayType(jsonObj, action_id); //_S2 remove&replace - /* eg: [['24', 0], ['24', 3]] */ const b4_deadkey_obj: modifierKey_object[] = this.get_9_KeyModifier_array__From__ActionID(jsonObj, action_id); - /* e.g. [['','caps?'], ['Caps']]*/ //const b4_deadkeyModifier_arr: string[] = this.get_3o_Modifier_array__From__KeyModifier_array_oldArrayType(data_ukelele.arrayOf_Modifiers, b4_deadkey_arr);//_S2 remove&replace - /* e.g. [['','caps?'], ['Caps']]*/ const b4_deadkeyModifier_obj: string[] = this.get_3_Modifier_array__From__KeyModifier_array(data_ukelele.arrayOf_Modifiers, b4_deadkey_obj); + /* eg: [['24', 0], ['24', 3]] */ const b4_deadkey_obj: allArrayContents_object[] = this.get_KeyModifier_array__From__ActionID(jsonObj, action_id); + /* e.g. [['','caps?'], ['Caps']]*/ const b4_deadkeyModifier_obj: string[] = this.get_Modifier_array__From__KeyModifier_array(data_ukelele.arrayOf_Modifiers, b4_deadkey_obj); // ........................................................................................................................................................................................ // Data of Block Nr 6 ..................................................................................................................................................................... // create an array[action id,state,output] from all state-output-pairs that use state = b5_value_next (e.g. use 1 in ) ...................................... - /* eg: [ 'a9','1','â'] */ //const b6_actionId_arr: string[][] = this.get_6o_ActionStateOutput_array__From__ActionState_oldArrayType(jsonObj, b5_value_next);//_S2 remove&replace - /* eg: [ 'a9','1','â'] */ const b6_actionId_obj: idStateOutput_object[] = this.get_6_ActionStateOutput_array__From__ActionState(jsonObj, b5_value_next); + /* eg: [ 'a9','1','â'] */ const b6_actionId_obj: idStateOutput_object[] = this.get_ActionStateOutput_array__From__ActionState(jsonObj, b5_value_next); // ........................................................................................................................................................................................ // Data of Block Nr 1 .................................................................................................................................................................... // create array[Keycode,Keyname,action id,actionIndex,output] and array[Keyname,action id,behaviour,modifier,output] ...................................................................... - /* eg: ['0','K_A','a9','0','â'] */ //const b1_keycode_arr: string[][] = this.get_5o_KeyActionOutput_array__From__ActionStateOutput_array_oldArrayType(jsonObj, b6_actionId_arr);//_S2 remove&replace - /* eg: ['0','K_A','a9','0','â'] */ const b1_keycode_obj: ActionIdKeyModiOutput_object[] = this.get_5_KeyActionOutput_array__From__ActionStateOutput_array(jsonObj, b6_actionId_obj); - - /* eg: ['K_A','a9','0','NCAPS','â']*/ // const b1_modifierKey_arr: string[][] = this.get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array_arr(jsonObj, b1_keycode_arr, isCapsused);//_S2 remove&replace - /* eg: ['K_A','a9','0','NCAPS','â']*/ //const b1_modifierKey_obj: ActionIdOutputBehaviourKeyModi_object[] = this.get_7o_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(jsonObj, b1_keycode_arr, isCapsused);//_S2 remove&replace - /* eg: ['K_A','a9','0','NCAPS','â']*/ const b1_modifierKey_obj: ActionIdOutputBehaviourKeyModi_object[] = this.get_7_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(jsonObj, b1_keycode_obj, isCapsused);//_S2 remove&replace + /* eg: ['0','K_A','a9','0','â'] */ const b1_keycode_obj: allArrayContents_object[] = this.get_KeyActionOutput_array__From__ActionStateOutput_array(jsonObj, b6_actionId_obj); + /* eg: ['K_A','a9','0','NCAPS','â']*/ const b1_modifierKey_obj: allArrayContents_object[] = this.get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(jsonObj, b1_keycode_obj, isCapsused); // ....................................................................................................................................................................................... - //for (let n1 = 0; n1 < b4_deadkeyModifier_arr.length; n1++) { for (let n1 = 0; n1 < b4_deadkeyModifier_obj.length; n1++) { - //for (let n2 = 0; n2 < b4_deadkeyModifier_arr[n1].length; n2++) { for (let n2 = 0; n2 < b4_deadkeyModifier_obj[n1].length; n2++) { - // for (let n3 = 0; n3 < b4_deadkey_arr.length; n3++) { for (let n3 = 0; n3 < b4_deadkey_obj.length; n3++) { - //for (let n4 = 0; n4 < b1_modifierKey_arr.length; n4++) {//_S2 remove&replace for (let n4 = 0; n4 < b1_modifierKey_obj.length; n4++) { rule_obj = new Rule( @@ -340,27 +337,15 @@ export class KeylayoutToKmnConverter { /* id_prev_deadkey */ 0, /* unique A */ 0, - /* modifier_deadkey */ //this.create_kmn_modifier(b4_deadkeyModifier_arr[n1][n2], isCapsused), /* modifier_deadkey */ this.create_kmn_modifier(b4_deadkeyModifier_obj[n1][n2], isCapsused), - /* deadkey */ //this.map_UkeleleKC_To_VK(Number(b4_deadkey_arr[n3][0])), /* deadkey */ this.map_UkeleleKC_To_VK(Number(b4_deadkey_obj[n3].key)), /* dk for C2*/ dk_counter_C2++, /* unique B */ 0, - /* modifier_key*/ // b1_modifierKey_arr[n4][3],//_S2 remove&replace - /* key */ //b1_modifierKey_arr[n4][0], - /* output */ // new TextEncoder().encode(b1_modifierKey_arr[n4][4]), - /* modifier_key*/ b1_modifierKey_obj[n4].modifier, /* key */ b1_modifierKey_obj[n4].key, /* output */ new TextEncoder().encode(b1_modifierKey_obj[n4].outchar), ); - /* if ((b1_modifierKey_arr[n4][4] !== undefined)//_S2 remove&replace - && (b1_modifierKey_arr[n4][4] !== "undefined") - && (b1_modifierKey_arr[n4][4] !== "")) { - object_array.push(rule_obj); - }*/ - if ((b1_modifierKey_obj[n4].outchar !== undefined) && (b1_modifierKey_obj[n4].outchar !== "undefined") && (b1_modifierKey_obj[n4].outchar !== "")) { @@ -399,91 +384,56 @@ export class KeylayoutToKmnConverter { // Data of Block Nr 4 ........................................................................................................................................................................ // with present action_id (a16) find all keycode-behaviour-pairs that use this action (a16) => (keymapIndex 3/keycode 32) .................................................................... // from these create an array of modifier combinations e.g. [ [ 'anyOption', 'Caps' ] ] ..................................................................................................... - /* e.g. [['32', 3]] */ // const b4_deadkey_arr: number[][] = this.get_9o_KeyModifier_array__From__ActionID_oldArrayType(jsonObj, action_id);//_S2 remove&replace - /* e.g. [['32', 3]] */ const b4_deadkey_obj: modifierKey_object[] = this.get_9_KeyModifier_array__From__ActionID(jsonObj, action_id); - /* e.g. [ [ 'anyOption', 'Caps' ] ]*/ // const b4_deadkeyModifier_arr: string[] = this.get_3o_Modifier_array__From__KeyModifier_array_oldArrayType(data_ukelele.arrayOf_Modifiers, b4_deadkey_arr); - /* e.g. [ [ 'anyOption', 'Caps' ] ]*/ const b4_deadkeyModifier_obj: string[] = this.get_3_Modifier_array__From__KeyModifier_array(data_ukelele.arrayOf_Modifiers, b4_deadkey_obj); + /* e.g. [['32', 3]] */ const b4_deadkey_obj: allArrayContents_object[] = this.get_KeyModifier_array__From__ActionID(jsonObj, action_id); + /* e.g. [ [ 'anyOption', 'Caps' ] ]*/ const b4_deadkeyModifier_obj: string[] = this.get_Modifier_array__From__KeyModifier_array(data_ukelele.arrayOf_Modifiers, b4_deadkey_obj); // ........................................................................................................................................................................................... // Data of Block Nr 3 ........................................................................................................................................................................ // get an action id from a state-output-pair that use state = b5_value_state (e.g. use 3 in ) ................................................................. - /* e.g. actioniD = a17 */ const b3_actionId: string = this.get_2_ActionID__From__ActionNext(jsonObj, b5_value_state); + /* e.g. actioniD = a17 */ const b3_actionId: string = this.get_ActionID__From__ActionNext(jsonObj, b5_value_state); // ........................................................................................................................................................................................... // Data of Block Nr 2 ....................................................................................................................................................................... // with present action_id (a17) find all key names and behaviours that use this action (a17) => (keymapIndex 3/keycode 28) .................................................................... // from these create an array of modifier combinations e.g. [ [ 'anyOption', 'Caps' ] ] ..................................................................................................... - - - - /* eg: index=3 */ //const b2_prev_deadkey_arr: number[][] = this.get_9o_KeyModifier_array__From__ActionID_oldArrayType(jsonObj, b3_actionId); // conversion not necessary //_S2 remove&replace - /* eg: index=3 */ const b2_prev_deadkey_obj: modifierKey_object[] = this.get_9_KeyModifier_array__From__ActionID(jsonObj, b3_actionId); // conversion not necessary //_S2 remove&replace - /* e.g. [ [ 'anyOption', 'Caps' ] ] */ // const b2_prev_deadkeyModifier_arr: string[] = this.get_3o_Modifier_array__From__KeyModifier_array_oldArrayType(data_ukelele.arrayOf_Modifiers, b2_prev_deadkey_arr); - /* e.g. [ [ 'anyOption', 'Caps' ] ] */ const b2_prev_deadkeyModifier_obj: string[] = this.get_3_Modifier_array__From__KeyModifier_array(data_ukelele.arrayOf_Modifiers, b2_prev_deadkey_obj); + /* eg: index=3 */ const b2_prev_deadkey_obj: allArrayContents_object[] = this.get_KeyModifier_array__From__ActionID(jsonObj, b3_actionId); + /* e.g. [ [ 'anyOption', 'Caps' ] ] */ const b2_prev_deadkeyModifier_obj: string[] = this.get_Modifier_array__From__KeyModifier_array(data_ukelele.arrayOf_Modifiers, b2_prev_deadkey_obj); // ........................................................................................................................................................................................... // Data of Block Nr 6 ........................................................................................................................................................................ // create an array[action id,state,output] from all state-output-pairs that use state = b5_value_next (e.g. use 1 in ) ......................................... - /* eg:[ [ 'a9','1','â'] ]*/ // const b6_actionId_arr: string[][] = this.get_6o_ActionStateOutput_array__From__ActionState_oldArrayType(jsonObj, b5_value_next); - /* eg:[ [ 'a9','1','â'] ]*/ const b6_actionId_obj: idStateOutput_object[] = this.get_6_ActionStateOutput_array__From__ActionState(jsonObj, b5_value_next); /* eg:[ [ 'a9','1','â'] ]*/ + /* eg:[ [ 'a9','1','â'] ]*/ const b6_actionId_obj: idStateOutput_object[] = this.get_ActionStateOutput_array__From__ActionState(jsonObj, b5_value_next); /* eg:[ [ 'a9','1','â'] ]*/ // ........................................................................................................................................................................................... // Data of Block Nr 1 ....................................................................................................................................................................... // create array[Keycode,Keyname,action id,actionIndex,output] and array[Keyname,action id,behaviour,modifier,output] ......................................................................... - /* eg: ['49','K_SPACE','a0','0','Â'] */ //const b1_keycode_arr: string[][] = this.get_5o_KeyActionOutput_array__From__ActionStateOutput_array_oldArrayType(jsonObj, b6_actionId_arr); - /* eg: ['0','K_A','a9','0','â'] */ const b1_keycode_obj: ActionIdKeyModiOutput_object[] = this.get_5_KeyActionOutput_array__From__ActionStateOutput_array(jsonObj, b6_actionId_obj); - // console.log("b1_keycode_obj ", b1_keycode_obj); - //this.compareBoth(b1_keycode_arr, b1_keycode_obj); - - /* eg: ['K_SPACE','a0','0','NCAPS','Â'] */ //const b1_modifierKey_arr: string[][] = this.get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array_arr(jsonObj, b1_keycode_arr, isCapsused);//_S2 remove&replace - /* eg: ['K_SPACE','a0','0','NCAPS','Â'] */ //const b1_modifierKey_obj: ActionIdOutputBehaviourKeyModi_object[] = this.get_7o_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(jsonObj, b1_keycode_arr, isCapsused); - const b1_modifierKey_obj: ActionIdOutputBehaviourKeyModi_object[] = this.get_7_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(jsonObj, b1_keycode_obj, isCapsused);//_S2 remove&replace + /* eg: ['49','K_SPACE','a0','0','Â'] */ const b1_keycode_obj: allArrayContents_object[] = this.get_KeyActionOutput_array__From__ActionStateOutput_array(jsonObj, b6_actionId_obj); + /* eg: ['K_SPACE','a0','0','NCAPS','Â'] */ const b1_modifierKey_obj: allArrayContents_object[] = this.get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(jsonObj, b1_keycode_obj, isCapsused); // ........................................................................................................................................................................................... - //for (let n1 = 0; n1 < b2_prev_deadkeyModifier_arr.length; n1++) { for (let n1 = 0; n1 < b2_prev_deadkeyModifier_obj.length; n1++) { - //for (let n2 = 0; n2 < b2_prev_deadkeyModifier_arr[n1].length; n2++) { for (let n2 = 0; n2 < b2_prev_deadkeyModifier_obj[n1].length; n2++) { - //for (let n3 = 0; n3 < b2_prev_deadkey_arr.length; n3++) { for (let n3 = 0; n3 < b2_prev_deadkey_obj.length; n3++) { - //for (let n4 = 0; n4 < b4_deadkeyModifier_arr.length; n4++) { for (let n4 = 0; n4 < b4_deadkeyModifier_obj.length; n4++) { - // for (let n5 = 0; n5 < b4_deadkeyModifier_arr[n4].length; n5++) { for (let n5 = 0; n5 < b4_deadkeyModifier_obj[n4].length; n5++) { - //for (let n6 = 0; n6 < b4_deadkey_arr.length; n6++) { for (let n6 = 0; n6 < b4_deadkey_obj.length; n6++) { - // for (let n7 = 0; n7 < b1_modifierKey_arr.length; n7++) {//_S2 remove&replace for (let n7 = 0; n7 < b1_modifierKey_obj.length; n7++) { rule_obj = new Rule( /* rule_type */ "C3", - /* modifier_prev_deadkey*/ //this.create_kmn_modifier(b2_prev_deadkeyModifier_arr[n1][n2], isCapsused), /* modifier_prev_deadkey*/ this.create_kmn_modifier(b2_prev_deadkeyModifier_obj[n1][n2], isCapsused), - /* prev_deadkey */ //this.map_UkeleleKC_To_VK(Number(b2_prev_deadkey_arr[n3][0])), /* prev_deadkey */ this.map_UkeleleKC_To_VK(Number(b2_prev_deadkey_obj[n3].key)), /* id_prev_deadkey */ dk_counter_C3++, /* unique A */ 0, - /* modifier_deadkey */ // this.create_kmn_modifier(b4_deadkeyModifier_arr[n4][n5], isCapsused), /* modifier_deadkey */ this.create_kmn_modifier(b4_deadkeyModifier_obj[n4][n5], isCapsused), - /* deadkey */ // this.map_UkeleleKC_To_VK(Number(b4_deadkey_arr[n6][0])), /* deadkey */ this.map_UkeleleKC_To_VK(Number(b4_deadkey_obj[n6].key)), /* dk for C2*/ 0, /* unique B */ 0, - /* modifier_key*/ //b1_modifierKey_arr[n7][3],//_S2 remove&replace - /* key */ //b1_modifierKey_arr[n7][0], - /* output */ //new TextEncoder().encode(b1_modifierKey_arr[n7][4]), - /* modifier_key*/ b1_modifierKey_obj[n7].modifier, /* key */ b1_modifierKey_obj[n7].key, /* output */ new TextEncoder().encode(b1_modifierKey_obj[n7].outchar), ); - - /* if ((b1_modifierKey_arr[n7][4] !== undefined)//_S2 remove&replace - && (b1_modifierKey_arr[n7][4] !== "undefined") - && (b1_modifierKey_arr[n7][4] !== "")) { - object_array.push(rule_obj); - }*/ if ((b1_modifierKey_obj[n7].outchar !== undefined) && (b1_modifierKey_obj[n7].outchar !== "undefined") && (b1_modifierKey_obj[n7].outchar !== "")) { @@ -700,7 +650,7 @@ export class KeylayoutToKmnConverter { } else { - add_modifier = String(modifier_state[i]) + " "; + add_modifier = modifier_state[i] + " "; } kmn_modifier += kmn_ncaps + add_modifier; } @@ -822,13 +772,13 @@ export class KeylayoutToKmnConverter { } } - /* @brief member function to return an index for a given actionID - * @param data :any - an object containing all data read from a .keylayout file - * @param search :string - value 'id' to be found - * @return a number specifying the index of an actionId - */ - // _S2 get 1 OK - public get_1_ActionIndex__From__ActionId(data: any, search: string): number { + /** + * @brief member function to return an index for a given actionID + * @param data :any - an object containing all data read from a .keylayout file + * @param search :string - value 'id' to be found + * @return a number specifying the index of an actionId + */ + public get_ActionIndex__From__ActionId(data: any, search: string): number { for (let i = 0; i < data.keyboard.actions.action.length; i++) { if (data.keyboard.actions.action[i]['@_id'] === search) { return i; @@ -836,14 +786,14 @@ export class KeylayoutToKmnConverter { } return 0; } + /** * @brief member function to find the actionID of a certain state-next pair * @param data :any an object containing all data read from a .keylayout file * @param search :string value 'next' to be found * @return a string containing the actionId of a certain state-next pair */ - // _S2 get 2 OK - public get_2_ActionID__From__ActionNext(data: any, search: string): string { + public get_ActionID__From__ActionNext(data: any, search: string): string { if (search !== "none") { for (let i = 0; i < data.keyboard.actions.action.length; i++) { for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { @@ -857,41 +807,15 @@ export class KeylayoutToKmnConverter { } /** - * @brief member function to create an array of modifier behaviours for a given keycode in [keycode,modifier] + * @brief member function to create an array of (modifier) behaviours for a given keycode in [{keycode,modifier}] * @param data : any - an object containing all data read from a .keylayout file - * @param search : (string | number)[][] - an array[keycode,modifier] to be found + * @param search : allArrayContents_object[] - an array[{keycode,modifier}] to be found * @return an array: string[] containing modifiers */ - // _S2 get 3 OK - public get_3o_Modifier_array__From__KeyModifier_array_oldArrayType(data: any, search: (string | number)[][]): string[] { - const mapIndexArray_2D: string[] = []; - - //console.log("Xsearch old ",search); - for (let i = 0; i < search.length; i++) { - mapIndexArray_2D.push(data[search[i][1]]); - } - return mapIndexArray_2D; - } - - public get_3_Modifier_array__From__KeyModifier_array_retObj(data: any, search: modifierKey_object[]): modifier_object[] { - const returnObjarray1D = []; - // console.log("Xsearch 3",search); - - let returnObject: modifier_object; - for (let i = 0; i < search.length; i++) { - returnObject = { - modifier: (data[search[i].modifier]) - }; - returnObjarray1D.push(returnObject); - } - return returnObjarray1D; - } - - - public get_3_Modifier_array__From__KeyModifier_array(data: any, search: modifierKey_object[]): string[] { + public get_Modifier_array__From__KeyModifier_array(data: any, search: allArrayContents_object[]): string[] { const returnString1D: string[] = []; for (let i = 0; i < search.length; i++) { - returnString1D.push(data[search[i].modifier]); + returnString1D.push(data[search[i].behaviour]); } return returnString1D; } @@ -903,10 +827,8 @@ export class KeylayoutToKmnConverter { * @param search :string an actionId to be found * @return a string containing the output character */ - // _S2 get 4 OK - public get_4_Output__From__ActionId_None(data: any, search: string): string { + public get_Output__From__ActionId_None(data: any, search: string): string { let OutputValue: string = ""; - for (let i = 0; i < data.keyboard.actions.action.length; i++) { if (data.keyboard.actions.action[i]['@_id'] === search) { for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { @@ -922,55 +844,28 @@ export class KeylayoutToKmnConverter { /** * @brief member function to return array of [Keycode,Keyname,actionId,actionIDIndex, output] for a given actionID in of [ actionID,state,output] * @param data :any - an object containing all data read from a .keylayout file - * @param search :string[][] - array of [ actionID,state,output] - * @return a string[][] containing [Keycode,Keyname,actionId,actionIDIndex, output] + * @param search :idStateOutput_object[] - array of [{ actionID,state,output }] + * @return a allArrayContents_object[] containing [{Keycode,Keyname,actionId,actionID, output}] */ - // _S2 get 5 OK - public get_5o_KeyActionOutput_array__From__ActionStateOutput_array_oldArrayType(data: any, search: string[][]): string[][] { - - if ((search === undefined) || (search === null)) - return []; - - - const returnarray2D: string[][] = []; - for (let k = 0; k < search.length; k++) { - for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { - for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { - if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search[k][0] && - data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'] <= KeylayoutToKmnConverter.USED_KEYS_COUNT) { - returnarray2D.push([ - data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], - this.map_UkeleleKC_To_VK(Number(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), - data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'], - data.keyboard.keyMapSet[0].keyMap[i]['@_index'], - search[k][2] - ]); - } - } - } - } - return returnarray2D; - } - // _S2 get 5 OK - public get_5_KeyActionOutput_array__From__ActionStateOutput_array(data: any, search: idStateOutput_object[]): ActionIdKeyModiOutput_object[] { + public get_KeyActionOutput_array__From__ActionStateOutput_array(data: any, search: idStateOutput_object[]): allArrayContents_object[] { if ((search === undefined) || (search === null)) return []; const returnObjarray1D = []; - let returnObject: ActionIdKeyModiOutput_object; + let returnObject: allArrayContents_object; for (let k = 0; k < search.length; k++) { for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search[k].id && - data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'] <= KeylayoutToKmnConverter.USED_KEYS_COUNT) { + data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'] <= KeylayoutToKmnConverter.USE_KEY_COUNT) { returnObject = { keyCode: data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], key: this.map_UkeleleKC_To_VK(Number(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), actionId: data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'], - modifier: data.keyboard.keyMapSet[0].keyMap[i]['@_index'], + behaviour: data.keyboard.keyMapSet[0].keyMap[i]['@_index'], outchar: search[k].output }; returnObjarray1D.push(returnObject); @@ -985,27 +880,9 @@ export class KeylayoutToKmnConverter { * @brief member function to get an array of all actionId-output pairs for a certain state * @param data : any an object containing all data read from a .keylayout file * @param search : string a 'state' to be found - * @return an array: string[][] containing all [actionId, state, output] for a certain state + * @return an array: idStateOutput_object[] containing all [{actionId, state, output}] for a certain state */ - // _S2 get 6 OK - public get_6o_ActionStateOutput_array__From__ActionState_oldArrayType(data: any, search: string): string[][] { - const returnarray2D: string[][] = []; - - for (let i = 0; i < data.keyboard.actions.action.length; i++) { - for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { - if ((data.keyboard.actions.action[i].when[j]['@_state'] === search)) { - returnarray2D.push([ - data.keyboard.actions.action[i]['@_id'], - data.keyboard.actions.action[i].when[j]['@_state'], - data.keyboard.actions.action[i].when[j]['@_output'] - ]); - } - } - } - return returnarray2D; - } - // _S2 get 6 OK - public get_6_ActionStateOutput_array__From__ActionState(data: any, search: string): idStateOutput_object[] { + public get_ActionStateOutput_array__From__ActionState(data: any, search: string): idStateOutput_object[] { const returnObjarray1D: idStateOutput_object[] = []; let returnObject: idStateOutput_object; @@ -1022,83 +899,31 @@ export class KeylayoutToKmnConverter { } } } - return returnObjarray1D; + return returnObjarray1D; // _S2 ToDo rewrite/change all functio comments to new datatypes!!! } /** * @brief member function to create an 2D array of [KeyName,actionId,behaviour,modifier,output] * @param data : any an object containing all data read from a .keylayout file - * @param search : array of [keycode,keyname,actionId,behaviour,output] to be found + * @param search : array of [{keycode,keyname,actionId,behaviour,output}] to be found * @param isCAPSused : boolean flag to indicate if CAPS is used in a keylayout file or not - * @return an array: string[][] containing [KeyName,actionId,behaviour,modifier,output] + * @return an array: allArrayContents_object[] containing [{KeyName,actionId,behaviour,modifier,output}] */ - // _S2 get 7 OK --> tests not OK - public get_7o_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array_oldArrayType(data: any, search: (boolean | string)[][], isCAPSused: boolean): string[][] { - const returnarray: string[][] = []; - - if (!((search === undefined) || (search === null) || (search.length === 0))) { - for (let i = 0; i < search.length; i++) { - const behaviour: number = Number(search[i][3]); - for (let j = 0; j < data.keyboard.modifierMap.keyMapSelect[behaviour].modifier.length; j++) { - returnarray.push([ - // KeyName - String(search[i][1]), - // actionId - String(search[i][2]), - // behaviour - String(search[i][3]), - // modifier - String(this.create_kmn_modifier(data.keyboard.modifierMap.keyMapSelect[behaviour].modifier[j]['@_keys'], isCAPSused)), - // output - String(search[i][4]) - ]); - } - } - } - // remove duplicates - const [unique_returnarray] = returnarray.reduce((acc, curr) => { - const [uniq, set] = acc; - if (!set.has(curr.join(','))) { - set.add(curr.join(',')); - uniq.push(curr); - } - return acc; - }, - [[], new Set()], - ); - return unique_returnarray; - } - public get_7o_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(data: any, search: ((boolean | string)[])[], isCAPSused: boolean): ActionIdOutputBehaviourKeyModi_object[] { - const returnarray: string[][] = []; + public get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(data: any, search: allArrayContents_object[], isCAPSused: boolean): allArrayContents_object[] { const returnObjarray1D = []; - let returnObject: ActionIdOutputBehaviourKeyModi_object; - + let returnObject: allArrayContents_object; if (!((search === undefined) || (search === null) || (search.length === 0))) { for (let i = 0; i < search.length; i++) { - const behaviour: number = Number(search[i][3]); - for (let j = 0; j < data.keyboard.modifierMap.keyMapSelect[behaviour].modifier.length; j++) { - - returnarray.push([ - // KeyName - String(search[i][1]), - // actionId - String(search[i][2]), - // behaviour - String(search[i][3]), - // modifier - String(this.create_kmn_modifier(data.keyboard.modifierMap.keyMapSelect[behaviour].modifier[j]['@_keys'], isCAPSused)), - // output - String(search[i][4]) - ]); + const behaviour_idx: number = Number(search[i].behaviour); + for (let j = 0; j < data.keyboard.modifierMap.keyMapSelect[behaviour_idx].modifier.length; j++) { returnObject = { - search: "", - actionId: String(search[i][2]), - behaviour: String(search[i][3]), - modifier: String(this.create_kmn_modifier(data.keyboard.modifierMap.keyMapSelect[behaviour].modifier[j]['@_keys'], isCAPSused)), - key: String(search[i][1]), - outchar: String(search[i][4]), + actionId: search[i].actionId, + key: search[i].key, + behaviour: search[i].behaviour, + modifier: this.create_kmn_modifier(data.keyboard.modifierMap.keyMapSelect[behaviour_idx].modifier[j]['@_keys'], isCAPSused), + outchar: search[i].outchar, }; returnObjarray1D.push(returnObject); } @@ -1108,55 +933,15 @@ export class KeylayoutToKmnConverter { const unique_Objarray = returnObjarray1D.reduce((unique, o) => { if (!unique.some(obj => obj.actionId === o.actionId && - obj.behaviour === o.behaviour && - obj.modifier === o.modifier && obj.key === o.key && - obj.outchar === o.outchar - )) { - unique.push(o); - } - return unique; - }, []); - - return unique_Objarray; - } - public get_7_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(data: any, search: ActionIdKeyModiOutput_object[], isCAPSused: boolean): ActionIdOutputBehaviourKeyModi_object[] { - - const returnObjarray1D = []; - let returnObject: ActionIdOutputBehaviourKeyModi_object; - - - if (!((search === undefined) || (search === null) || (search.length === 0))) { - for (let i = 0; i < search.length; i++) { - const behaviour: number = Number(search[i].modifier); - for (let j = 0; j < data.keyboard.modifierMap.keyMapSelect[behaviour].modifier.length; j++) { - - returnObject = { - search: "", - actionId: String(search[i].actionId), - behaviour: String(search[i].modifier), - modifier: String(this.create_kmn_modifier(data.keyboard.modifierMap.keyMapSelect[behaviour].modifier[j]['@_keys'], isCAPSused)), - key: String(search[i].key), - outchar: String(search[i].outchar), - }; - returnObjarray1D.push(returnObject); - } - } - } - // remove duplicates - const unique_Objarray = returnObjarray1D.reduce((unique, o) => { - if (!unique.some(obj => - obj.actionId === o.actionId && obj.behaviour === o.behaviour && obj.modifier === o.modifier && - obj.key === o.key && obj.outchar === o.outchar )) { unique.push(o); } return unique; }, []); - return unique_Objarray; } @@ -1167,30 +952,28 @@ export class KeylayoutToKmnConverter { * @param search : string - an actionId to be found * @param outchar : string - the output character * @param isCAPSused : boolean - flag to indicate if CAPS is used in a keylayout file or not - * @return an array: string[][] containing [actionID,output,actionID, behaviour,keyname,modifier] + * @return an array: allArrayContents_object[] containing [{actionID,output,actionID, behaviour,keyname,modifier}] */ - // _S2 get 8 OK - public get_8_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput(data: any, modi: any, search: string, outchar: string, isCapsused: boolean): ActionIdOutputBehaviourKeyModi_object[] { + public get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput(data: any, modi: string[][], search: string, outchar: string, isCapsused: boolean): allArrayContents_object[] { const returnObjarray1D = []; - let returnObject: ActionIdOutputBehaviourKeyModi_object; + let returnObject: allArrayContents_object; if ((search === "") || (search === undefined) || !((isCapsused === true) || (isCapsused === false))) { return []; } // loop behaviors (in ukelele it is possible to define multiple modifier combinations that behave in the same way) for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { - for (let j = 0; j <= KeylayoutToKmnConverter.USED_KEYS_COUNT; j++) { + + for (let j = 0; j <= KeylayoutToKmnConverter.USE_KEY_COUNT; j++) { if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { for (let k = 0; k < modi[data.keyboard.keyMapSet[0].keyMap[i]['@_index']].length; k++) { - const behaviour: string = data.keyboard.keyMapSet[0].keyMap[i]['@_index']; - + const behaviour_idx: number = data.keyboard.keyMapSet[0].keyMap[i]['@_index']; returnObject = { - search: search, outchar: outchar, actionId: data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'], behaviour: data.keyboard.keyMapSet[0].keyMap[i]['@_index'], key: this.map_UkeleleKC_To_VK(Number(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), - modifier: this.create_kmn_modifier(modi[behaviour][k], isCapsused), + modifier: this.create_kmn_modifier(modi[behaviour_idx][k], isCapsused), }; returnObjarray1D.push(returnObject); } @@ -1203,9 +986,8 @@ export class KeylayoutToKmnConverter { // remove duplicates const unique_Objarray = returnObjarray1D.reduce((unique, o) => { if (!unique.some(obj => - obj.actionId === o.actionId && obj.outchar === o.outchar && - obj.search === o.search && + obj.actionId === o.actionId && obj.behaviour === o.behaviour && obj.key === o.key && obj.modifier === o.modifier @@ -1219,47 +1001,24 @@ export class KeylayoutToKmnConverter { } /** - * @brief member function to create an array of [keycode,behaviour] for a given actionId + * @brief member function to create an array of [{keycode,behaviour}] for a given actionId * @param data : any - an object containing all data read from a .keylayout file * @param search : string - an actionId to be found - * @return an array: number[][] containing [keycode,behaviour] + * @return an array: allArrayContents_object[] containing [{keycode,behaviour}] */ - // _S2 get 9 OK //_S2 remove&replace - public get_9o_KeyModifier_array__From__ActionID_oldArrayType(data: any, search: string): number[][] { + public get_KeyModifier_array__From__ActionID(data: any, search: string): allArrayContents_object[] { const mapIndexArray_2D: number[][] = []; - let returnObject: modifierKey_object; - const mapIndexObject1D: modifierKey_object[] = []; + let returnObject: allArrayContents_object; + const mapIndexObject1D: allArrayContents_object[] = []; for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { - for (let j = 0; j <= KeylayoutToKmnConverter.USED_KEYS_COUNT; j++) { + for (let j = 0; j <= KeylayoutToKmnConverter.USE_KEY_COUNT; j++) { if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { mapIndexArray_2D.push([data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], i]); - returnObject = { key: data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], - modifier: i - }; - mapIndexObject1D.push(returnObject); - } - } - } - return mapIndexArray_2D; - } - public get_9_KeyModifier_array__From__ActionID(data: any, search: string): modifierKey_object[] { - const mapIndexArray_2D: number[][] = []; - let returnObject: modifierKey_object; - const mapIndexObject1D: modifierKey_object[] = []; - - for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { - for (let j = 0; j <= KeylayoutToKmnConverter.USED_KEYS_COUNT; j++) { - if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { - - mapIndexArray_2D.push([data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], i]); - - returnObject = { - key: data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], - modifier: i + behaviour: String(i), }; mapIndexObject1D.push(returnObject); } @@ -1272,101 +1031,6 @@ export class KeylayoutToKmnConverter { public convert_bound = { convert: this.convert.bind(this), }; - - - - public dummy(into: any) { - } - public compareBoth(arr: any, obj: any,) { - - // compare:----------------------------------- - for (let k = 0; k < obj.length; k++) { - /*console.log("k ", k); - - console.log(" arr", typeof (arr), arr, "----", typeof (arr[k]), arr[k]); - console.log("-------------------- ",); - console.log(" obj", typeof (obj), obj, "----", typeof (obj[k]), obj[k]); - - console.log("arr[k ", arr[k]); - console.log("obj[k].modifier ", obj[k].modifier);*/ - if ( - (arr.length === obj.length) && - - - (arr[k] === obj[k].modifier) - // (arr[k][1] === obj[k].key) - - /*(arr[k][0] === obj[k].key) && - (arr[k][1] === obj[k].actionId) && - (arr[k][2] === obj[k].behaviour) && - (arr[k][3] === obj[k].modifier) && - (arr[k][4] === obj[k].outchar)*/ - - ) { - console.log("IS_EQUAL ",); - } - else console.log("NONONO not_EQUAL \n", - (arr.length === obj.length), obj.length, "<->", arr.length, "\n", - - (arr[k] === obj[k].modifier), obj[k].modifier, "<->", arr[k], "\n", - // (arr[k][1] === obj[k].key), obj[k].key, "<->", arr[k][1], "\n", - - - /* (arr[k][0] === obj[k].key), obj[k].key, "<->", arr[k][0], "\n", - (arr[k][1] === obj[k].actionId), obj[k].actionId, "<->", arr[k][1], "\n", - (arr[k][2] === obj[k].behaviour), obj[k].behaviour, "<->", arr[k][2], "\n", - (arr[k][3] === obj[k].modifier), obj[k].modifier, "<->", arr[k][3], "\n", - (arr[k][4] === obj[k].outchar), obj[k].outchar, "<->", arr[k][4]*/ - ); - } - } - public compareSameType(arr1: any, arr2: any,) { - - - // compare:----------------------------------- - for (let k = 0; k < arr1.length; k++) { - /*console.log("k ", k); - - console.log(" arr1", typeof (arr1), arr1, "----", typeof (arr1[k]), arr1[k]); - console.log("-------------------- ",); - console.log(" arr2", typeof (arr2), arr2, "----", typeof (arr2[k]), arr2[k]); - - console.log("arr1[k ", arr1[k]); - console.log("arr2[k].modifier ", arr2[k].modifier);*/ - if ( - (arr1.length === arr2.length) && - - (arr1[k].search === arr2[k].search) && - (arr1[k].actionId === arr2[k].actionId) && - (arr1[k].behaviour === arr2[k].behaviour) && - (arr1[k].modifier === arr2[k].modifier) && - (arr1[k].key === arr2[k].key) && - (arr1[k].outchar === arr2[k].outchar) - - ) { - console.log("compareSameType: IS_EQUAL ",); - } - else console.log("compareSameType: NONONO not_EQUAL \n", - (arr1.length === arr2.length), arr2.length, "<->", arr1.length, "\n", - - (arr1[k] === arr2[k].modifier), arr2[k].modifier, "<->", arr1[k], "\n", - // (arr1[k][1] === arr2[k].key), arr2[k].key, "<->", arr1[k][1], "\n", - - - /* (arr1[k][0] === arr2[k].key), arr2[k].key, "<->", arr1[k][0], "\n", - (arr1[k][1] === arr2[k].actionId), arr2[k].actionId, "<->", arr1[k][1], "\n", - (arr1[k][2] === arr2[k].behaviour), arr2[k].behaviour, "<->", arr1[k][2], "\n", - (arr1[k][3] === arr2[k].modifier), arr2[k].modifier, "<->", arr1[k][3], "\n", - (arr1[k][4] === arr2[k].outchar), arr2[k].outchar, "<->", arr1[k][4]*/ - ); - } - } - - - - - - } /** diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts index f5044192209..2854940eccd 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts @@ -149,7 +149,7 @@ export class KmnFileWriter { // lookup key nr of the key which is being processed let keyNr: number = 0; - for (let j = 0; j <= KeylayoutToKmnConverter.USED_KEYS_COUNT; j++) { + for (let j = 0; j <= KeylayoutToKmnConverter.USE_KEY_COUNT; j++) { if (keylayoutKmnConverter.map_UkeleleKC_To_VK(j) === unique_data_Rules[k].key) { keyNr = j; break; diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index f3ac272cec0..de48dd1e22b 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -10,7 +10,7 @@ import 'mocha'; import { assert } from 'chai'; import { compilerTestCallbacks, compilerTestOptions, makePathToFixture } from './helpers/index.js'; -import { /*ActionIdOutputBehaviourKeyModi_object,*/ KeylayoutToKmnConverter } from '../src/keylayout-to-kmn/keylayout-to-kmn-converter.js'; +import { idStateOutput_object, allArrayContents_object, KeylayoutToKmnConverter } from '../src/keylayout-to-kmn/keylayout-to-kmn-converter.js'; import { KeylayoutFileReader } from '../src/keylayout-to-kmn/keylayout-file-reader.js'; import { ConverterMessages } from '../src/converter-messages.js'; import * as NodeAssert from 'node:assert'; @@ -21,49 +21,7 @@ describe('KeylayoutToKmnConverter', function () { compilerTestCallbacks.clear(); }); - // todo remove - describe('RunOneFile', function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const inputFilename = makePathToFixture('../data/Test.keylayout'); - sut.run(inputFilename); - assert.isTrue(true); - }); - - // todo remove - describe('RunOneFile', function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const inputFilename = makePathToFixture('../data/Italian.keylayout'); - sut.run(inputFilename); - assert.isTrue(true); - }); - - // todo remove - describe('RunAllFiles', function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - [ - [makePathToFixture('../data/Italian.keylayout')], - [makePathToFixture('../data/Italian_command.keylayout')], - [makePathToFixture('../data/Swiss_French.keylayout')], - [makePathToFixture('../data/Spanish.keylayout')], - [makePathToFixture('../data/Swiss_German.keylayout')], - [makePathToFixture('../data/US.keylayout')], - [makePathToFixture('../data/Polish.keylayout')], - [makePathToFixture('../data/French.keylayout')], - [makePathToFixture('../data/Latin_American.keylayout')], - // [makePathToFixture('../data/German_complete.keylayout')], - [makePathToFixture('../data/German_complete_reduced.keylayout')], - //[makePathToFixture('../data/German_Standard.keylayout')], - ].forEach(function (files_) { - sut.run(files_[0]); - assert.isTrue(true); - }); - }); describe('run() ', function () { - - // _S2 can I do this??? - some tests of the run() function might take longer than 2000 ms - // see https://pramod-mallick.medium.com/mocha-with-selenium-webdriver-exception-timeout-of-2000ms-exceeded-89df7b6230c6 - this.timeout(10000); - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); it('run() should throw on null input file name and null output file name', async function () { @@ -93,8 +51,16 @@ describe('KeylayoutToKmnConverter', function () { const inputFilename = makePathToFixture('../data/Unavailable.keylayout'); const result = sut.run(inputFilename, null); assert.isNotNull(result); - assert.equal(compilerTestCallbacks.messages.length, 2); - assert.deepEqual(compilerTestCallbacks.messages[0], ConverterMessages.Error_FileNotFound({ inputFilename: inputFilename })); + assert.equal(compilerTestCallbacks.messages.length, 1); + assert.deepEqual(compilerTestCallbacks.messages[0], ConverterMessages.Error_OutputFilenameIsRequired()); + }); + + it('run() should throw on and null output file name', async function () { + const inputFilename = makePathToFixture('../data/Test.keylayout'); + const result = sut.run(inputFilename, null); + assert.isNotNull(result); + assert.equal(compilerTestCallbacks.messages.length, 1); + assert.deepEqual(compilerTestCallbacks.messages[0], ConverterMessages.Error_OutputFilenameIsRequired()); }); it('run() should return on correct input file name and empty output file name ', async function () { @@ -290,123 +256,40 @@ describe('KeylayoutToKmnConverter', function () { }); }); - describe('get_3o_Modifier_array__From__KeyModifier_array_oldArrayType ', function () { + describe('get_Modifier_array__From__KeyModifier_array ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Test.keylayout'); const read = sut_r.read(inputFilename); const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); - - [ - [[['0', 0]], [['', 'shift? caps? ']]], - [[['0', 2]], [['shift? leftShift caps? ', 'anyShift caps?', 'shift leftShift caps ', 'shift? rightShift caps? ']]], - [[['0', 999]], [null]], - [[['999',]], [null]], - [[['0', -999]], [null]], - [[['0']], [null]], - - ].forEach(function (values) { - it((values[1][0] !== null) ? - ("get_3o_Modifier_array__From__KeyModifier_array_oldArrayType(['" + values[0][0][0] + "', '" + values[0][0][1] + "'])").padEnd(68, " ") + " should return ['" + values[1][0][0] + "', '" + values[1][0][1] + "']" : - ("get_3o_Modifier_array__From__KeyModifier_array_oldArrayType(['" + values[0][0][0] + "', '" + values[0][0][1] + "'])").padEnd(68, " ") + " should return ['" + values[1][0] + "']", async function () { - const result = sut.get_3o_Modifier_array__From__KeyModifier_array_oldArrayType(converted.arrayOf_Modifiers, values[0]); - assert.deepStrictEqual(JSON.stringify(result), JSON.stringify(values[1])); - }); - }); - - [[[[null]], [null]], - [[[undefined]], [null]], - [[[]], [null]], - ].forEach(function (values) { - it(("get_3o_Modifier_array__From__KeyModifier_array_oldArrayType([" + values[0][0] + "])").padEnd(68, " ") + " should return ['" + values[1][0] + "']", async function () { - const result = sut.get_3o_Modifier_array__From__KeyModifier_array_oldArrayType(converted.arrayOf_Modifiers, values[0]); - assert.deepStrictEqual(JSON.stringify(result), JSON.stringify(values[1])); - }); - }); - }); - describe('get_3_Modifier_array__From__KeyModifier_array ', function () { - /*const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); - const read = sut_r.read(inputFilename); - const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); - - - //search old [ [ '45', 5 ] ] - //search [ { key: '45', modifier: 5 } ] - - [ - - //search - [[{ key: '0', modifier: 0 }, ['', 'shift? caps? ']]], - [[{ key: '3', modifier: 0 },['', 'shixft? caps? ']]], - [[{ key: '7', modifier: 0 },['', 'shift? caxps? ']]], - [[{ key: '0', modifier: 2 },['', 'shift? caps? ']]], - [[{ key: '0', modifier: 999 },['', 'shift? caps? ']]], - [[{ key: '999', modifier: null },['', 'shift? caps? ']]], - [[{ key: '0', modifier: -999 },['', 'shift? caps? ']]], - [[{ key: '0', modifier: null },['', 'shift? caps? ']]], - - - - //[['0', 0], [['', 'shift? caps? ']]], - // [[['0', 2]], [['shift? leftShift caps? ', 'anyShift caps?', 'shift leftShift caps ', 'shift? rightShift caps? ']]], - // [[['0', 999]], [null]], - // [[['999',]], [null]], - // [[['0', -999]], [null]], - // [[['0']], [null]], - - - + [[{ key: '0', behaviour: 0 }], [['', 'shift? caps? ']]], + [[{ key: '0', behaviour: 2 }], [['shift? leftShift caps? ', 'anyShift caps?', 'shift leftShift caps ', 'shift? rightShift caps? ']]], + [[{ key: '0', behaviour: 999 }], [null]], + [[{ key: '999', behaviour: null }], [null]], + [[{ key: '0', behaviour: -999 }], [null]], + [[{ key: '0', behaviour: null }], [null]], + [[], []], ].forEach(function (values) { - - - - console.log("values ", values); - console.log("values[0] ", values[0]); - console.log("values[1] ", values[1]); - //console.log("values[1][0] ", values[1][0]); - // console.log("values[0][0][0] ", values[0][0][0]); - // console.log(" values[0][0][1]", values[0][0][1]); - // console.log("values[1][0][0] ", values[1][0][0]); - // console.log("values [1][0][1]", values[1][0][1]); - - -console.log("XXX get_3_Modifier_array__From__KeyModifier_array(['" , values[0] , "'])", " should return ['" , values[1] , "']"); - - - it((values[1] !== null) ? - ("get_3_Modifier_array__From__KeyModifier_array(['" + values[0] + "'])").padEnd(68, " ") + " should return ['" + values[1] + "']" : - ("get_3_Modifier_array__From__KeyModifier_array(['" + values[0] + "'])").padEnd(68, " ") + " should return ['" + values[1] + "']", async function () { - //const result = sut.get_3_Modifier_array__From__KeyModifier_array(converted.arrayOf_Modifiers, values[0]); - // assert.deepStrictEqual(JSON.stringify(result), JSON.stringify(values[1])); + ("get_Modifier_array__From__KeyModifier_array('" + JSON.stringify(values[0]) + "')").padEnd(68, " ") + " should return '" + /*values[1] +*/ JSON.stringify(values[1]) + "'" : + ("get_Modifier_array__From__KeyModifier_array('" + JSON.stringify(values[0]) + "')").padEnd(68, " ") + " should return '" + "null" + "'", async function () { + const result = sut.get_Modifier_array__From__KeyModifier_array(converted.arrayOf_Modifiers, values[0] as allArrayContents_object[]); + assert.deepStrictEqual(JSON.stringify(result), JSON.stringify(values[1])); }); }); - - /* [[[[null]], [null]], - [[[undefined]], [null]], - [[[]], [null]], - ].forEach(function (values) { - it(("get_3_Modifier_array__From__KeyModifier_array([" + values[0][0] + "])").padEnd(68, " ") + " should return ['" + values[1][0] + "']", async function () { - const result = sut.get_3_Modifier_array__From__KeyModifier_array(converted.arrayOf_Modifiers, values[0]); - assert.deepStrictEqual(JSON.stringify(result), JSON.stringify(values[1])); - }); - }); - */ }); - describe('get_9_KeyModifier_array__From__ActionID ', function () { + describe('get_KeyModifier_array__From__ActionID ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Test.keylayout'); const read = sut_r.read(inputFilename); [ - ['A_16', [{ "key": "32", "modifier": 5 }]], - ['A_19', [{ "key": "45", "modifier": 5 }]], - ['A_18', [{ "key": "24", "modifier": 0 }, { "key": "24", "modifier": 5 }]], + ['A_16', [{ "key": "32", "behaviour": "5" }]], + ['A_19', [{ "key": "45", "behaviour": "5" }]], + ['A_18', [{ "key": "24", "behaviour": "0" }, { "key": "24", "behaviour": "5" }]], ['unknown', []], [undefined, []], [null, []], @@ -417,44 +300,14 @@ console.log("XXX get_3_Modifier_array__From__KeyModifier_array(['" , values[0] , for (let i = 0; i < values[1].length; i++) { outstring = outstring + "[ " + JSON.stringify(values[1][i]) + "], "; } - it(("get_9_KeyModifier_array__From__ActionID('" + values[0] + "')").padEnd(57, " ") + ' should return ' + outstring.substring(0, outstring.lastIndexOf(']') + 2) + " ]", async function () { - //const result = sut.get_9_KeyModifier_array__From__ActionID_arr(read, String(values[0])); //_S2 remove&replace - const result = sut.get_9_KeyModifier_array__From__ActionID(read, String(values[0])); + it(("get_KeyModifier_array__From__ActionID('" + values[0] + "')").padEnd(57, " ") + ' should return ' + outstring.substring(0, outstring.lastIndexOf(']') + 2) + " ]", async function () { + const result = sut.get_KeyModifier_array__From__ActionID(read, String(values[0])); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); }); - describe('get_9o_KeyModifier_array__From__ActionID_oldArrayType ', function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); - const read = sut_r.read(inputFilename); - - [ - ['A_16', [['32', 5]]], - ['A_19', [['45', 5]]], - ['A_18', [['24', 0], ['24', 5]]], - - - ['unknown', []], - [undefined, []], - [null, []], - [' ', []], - ['', []], - ].forEach(function (values) { - let outstring = '[ '; - for (let i = 0; i < values[1].length; i++) { - outstring = outstring + "[ '" + values[1][i][0] + "', " + values[1][i][1].toString() + "], "; - } - it(("get_9o_KeyModifier_array__From__ActionID_oldArrayType('" + values[0] + "')").padEnd(57, " ") + ' should return ' + outstring.substring(0, outstring.lastIndexOf(']') + 2) + " ]", async function () { - const result = sut.get_9o_KeyModifier_array__From__ActionID_oldArrayType(read, String(values[0])); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); - }); - }); - }); - - describe('get_2_ActionID__From__ActionNext ', function () { + describe('get_ActionID__From__ActionNext ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Test.keylayout'); @@ -474,13 +327,13 @@ console.log("XXX get_3_Modifier_array__From__KeyModifier_array(['" , values[0] , [undefined, ''], ['unknown', ''], ].forEach(function (values) { - it(("get_2_ActionID__From__ActionNext('" + values[0] + "')").padEnd(49, " ") + ' should return ' + "'" + values[1] + "'", async function () { - const result = sut.get_2_ActionID__From__ActionNext(read, String(values[0])); + it(("get_ActionID__From__ActionNext('" + values[0] + "')").padEnd(49, " ") + ' should return ' + "'" + values[1] + "'", async function () { + const result = sut.get_ActionID__From__ActionNext(read, String(values[0])); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); }); - describe('get_1_ActionIndex__From__ActionId ', function () { + describe('get_ActionIndex__From__ActionId ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Test.keylayout'); @@ -498,14 +351,13 @@ console.log("XXX get_3_Modifier_array__From__KeyModifier_array(['" , values[0] , [undefined, 0], ['unknown', 0], ].forEach(function (values) { - it(("get_1_ActionIndex__From__ActionId('" + values[0] + "')").padEnd(50, " ") + ' should return ' + values[1], async function () { - const result = sut.get_1_ActionIndex__From__ActionId(read, String(values[0])); + it(("get_ActionIndex__From__ActionId('" + values[0] + "')").padEnd(50, " ") + ' should return ' + values[1], async function () { + const result = sut.get_ActionIndex__From__ActionId(read, String(values[0])); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); }); - - describe('get_4_Output__From__ActionId_None ', function () { + describe('get_Output__From__ActionId_None ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Test.keylayout'); @@ -519,8 +371,8 @@ console.log("XXX get_3_Modifier_array__From__KeyModifier_array(['" , values[0] , ['unknown', ''], ].forEach(function (values) { it( - ("get_4_Output__From__ActionId_None('" + values[0] + "')").padEnd(56, " ") + ' should return ' + "'" + values[1] + "'", async function () { - const result = sut.get_4_Output__From__ActionId_None(read, String(values[0])); + ("get_Output__From__ActionId_None('" + values[0] + "')").padEnd(56, " ") + ' should return ' + "'" + values[1] + "'", async function () { + const result = sut.get_Output__From__ActionId_None(read, String(values[0])); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); @@ -529,114 +381,105 @@ console.log("XXX get_3_Modifier_array__From__KeyModifier_array(['" , values[0] , [undefined, ''], [99, ''], ].forEach(function (values) { - it(("get_4_Output__From__ActionId_None('" + values[0] + "')").padEnd(56, " ") + ' should return ' + values[1], async function () { - const result = sut.get_4_Output__From__ActionId_None(read, String(values[0])); + it(("get_Output__From__ActionId_None('" + values[0] + "')").padEnd(56, " ") + ' should return ' + values[1], async function () { + const result = sut.get_Output__From__ActionId_None(read, String(values[0])); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); }); - - describe('get_7o_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array_oldArrayType ', function () { + describe('get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Test.keylayout'); const read = sut_r.read(inputFilename); - const b1_keycode_arr = [ - ['49', 'K_SPACE', 'A_0', '0', 'ˆ'], - ['49', 'K_SPACE', 'A_0', '1', 'ˆ'], - ['49', 'K_SPACE', 'A_0', '2', 'ˆ'], - ['6', 'K_Z', 'A_0', '4', 'ˆ'], - ['25', 'K_9', 'A_0', '4', 'ˆ'], - ['43', 'K_COMMA', 'A_0', '4', 'ˆ'], - ['49', 'K_SPACE', 'A_0', '3', 'ˆ'], - ['0', 'K_A', 'A_1', '2', 'Â'], - ['0', 'K_A', 'A_1', '1', 'Â'], - ['14', 'K_E', 'A_10', '0', 'ê'], - ['34', 'K_I', 'A_11', '0', 'î'], - ['31', 'K_O', 'A_13', '0', 'ô'], - ['32', 'K_U', 'A_14', '0', 'û'], - ['14', 'K_E', 'A_2', '2', 'Ê'], - ['14', 'K_E', 'A_2', '1', 'Ê'], - ['34', 'K_I', 'A_3', '2', 'Î'], - ['34', 'K_I', 'A_3', '1', 'Î'], - ['31', 'K_O', 'A_5', '2', 'Ô'], - ['31', 'K_O', 'A_5', '1', 'Ô'], - ['32', 'K_U', 'A_6', '2', 'Û'], - ['32', 'K_U', 'A_6', '1', 'Û'], - ['0', 'K_A', 'A_9', '0', 'â']/**/ + const b1_keycode_arr: allArrayContents_object[] = [ + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '0', outchar: 'ˆ' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '1', outchar: 'ˆ' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '2', outchar: 'ˆ' }, + { keyCode: '6', key: 'K_Z', actionId: 'A_0', behaviour: '4', outchar: 'ˆ' }, + { keyCode: '25', key: 'K_9', actionId: 'A_0', behaviour: '4', outchar: 'ˆ' }, + { keyCode: '43', key: 'K_COMMA', actionId: 'A_0', behaviour: '4', outchar: 'ˆ' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '3', outchar: 'ˆ' }, + { keyCode: '0', key: 'K_A', actionId: 'A_1', behaviour: '2', outchar: 'Â' }, + { keyCode: '0', key: 'K_A', actionId: 'A_1', behaviour: '1', outchar: 'Â' }, + { keyCode: '14', key: 'K_E', actionId: 'A_10', behaviour: '0', outchar: 'ê' }, + { keyCode: '34', key: 'K_I', actionId: 'A_11', behaviour: '0', outchar: 'î' }, + { keyCode: '31', key: 'K_O', actionId: 'A_13', behaviour: '0', outchar: 'ô' }, + { keyCode: '32', key: 'K_U', actionId: 'A_14', behaviour: '0', outchar: 'û' }, + { keyCode: '14', key: 'K_E', actionId: 'A_2', behaviour: '2', outchar: 'Ê' }, + { keyCode: '14', key: 'K_E', actionId: 'A_2', behaviour: '1', outchar: 'Ê' }, + { keyCode: '34', key: 'K_I', actionId: 'A_3', behaviour: '2', outchar: 'Î' }, + { keyCode: '34', key: 'K_I', actionId: 'A_3', behaviour: '1', outchar: 'Î' }, + { keyCode: '31', key: 'K_O', actionId: 'A_5', behaviour: '2', outchar: 'Ô' }, + { keyCode: '31', key: 'K_O', actionId: 'A_5', behaviour: '1', outchar: 'Ô' }, + { keyCode: '32', key: 'K_U', actionId: 'A_6', behaviour: '2', outchar: 'Û' }, + { keyCode: '32', key: 'K_U', actionId: 'A_6', behaviour: '1', outchar: 'Û' }, + { keyCode: '0', key: 'K_A', actionId: 'A_9', behaviour: '0', outchar: 'â' } + ]; - const b1_modifierKey_arr = [ - ['K_SPACE', 'A_0', '0', 'NCAPS', 'ˆ'], - ['K_SPACE', 'A_0', '1', 'CAPS', 'ˆ'], - ['K_SPACE', 'A_0', '2', 'NCAPS SHIFT', 'ˆ'], - ['K_SPACE', 'A_0', '2', 'SHIFT CAPS', 'ˆ'], - ['K_Z', 'A_0', '4', 'NCAPS SHIFT RALT', 'ˆ'], - ['K_9', 'A_0', '4', 'NCAPS SHIFT RALT', 'ˆ'], - ['K_COMMA', 'A_0', '4', 'NCAPS SHIFT RALT', 'ˆ'], - ['K_SPACE', 'A_0', '3', 'NCAPS RALT CTRL', 'ˆ'], - ['K_SPACE', 'A_0', '3', 'NCAPS CTRL', 'ˆ'], - ['K_A', 'A_1', '2', 'NCAPS SHIFT', 'Â'], - ['K_A', 'A_1', '2', 'SHIFT CAPS', 'Â'], - ['K_A', 'A_1', '1', 'CAPS', 'Â'], - ['K_E', 'A_10', '0', 'NCAPS', 'ê'], - ['K_I', 'A_11', '0', 'NCAPS', 'î'], - ['K_O', 'A_13', '0', 'NCAPS', 'ô'], - ['K_U', 'A_14', '0', 'NCAPS', 'û'], - ['K_E', 'A_2', '2', 'NCAPS SHIFT', 'Ê'], - ['K_E', 'A_2', '2', 'SHIFT CAPS', 'Ê'], - ['K_E', 'A_2', '1', 'CAPS', 'Ê'], - ['K_I', 'A_3', '2', 'NCAPS SHIFT', 'Î'], - ['K_I', 'A_3', '2', 'SHIFT CAPS', 'Î'], - ['K_I', 'A_3', '1', 'CAPS', 'Î'], - ['K_O', 'A_5', '2', 'NCAPS SHIFT', 'Ô'], - ['K_O', 'A_5', '2', 'SHIFT CAPS', 'Ô'], - ['K_O', 'A_5', '1', 'CAPS', 'Ô'], - ['K_U', 'A_6', '2', 'NCAPS SHIFT', 'Û'], - ['K_U', 'A_6', '2', 'SHIFT CAPS', 'Û'], - ['K_U', 'A_6', '1', 'CAPS', 'Û'], - ['K_A', 'A_9', '0', 'NCAPS', 'â']/**/ + const b1_modifierKey_arr: allArrayContents_object[] = [ + { actionId: 'A_0', key: 'K_SPACE', behaviour: '0', modifier: 'NCAPS', outchar: 'ˆ' }, + { actionId: 'A_0', key: 'K_SPACE', behaviour: '1', modifier: 'CAPS', outchar: 'ˆ' }, + { actionId: 'A_0', key: 'K_SPACE', behaviour: '2', modifier: 'NCAPS SHIFT', outchar: 'ˆ' }, + { actionId: 'A_0', key: 'K_SPACE', behaviour: '2', modifier: 'SHIFT CAPS', outchar: 'ˆ' }, + { actionId: 'A_0', key: 'K_Z', behaviour: '4', modifier: 'NCAPS SHIFT RALT', outchar: 'ˆ' }, + { actionId: 'A_0', key: 'K_9', behaviour: '4', modifier: 'NCAPS SHIFT RALT', outchar: 'ˆ' }, + { actionId: 'A_0', key: 'K_COMMA', behaviour: '4', modifier: 'NCAPS SHIFT RALT', outchar: 'ˆ' }, + { actionId: 'A_0', key: 'K_SPACE', behaviour: '3', modifier: 'NCAPS RALT CTRL', outchar: 'ˆ' }, + { actionId: 'A_0', key: 'K_SPACE', behaviour: '3', modifier: 'NCAPS CTRL', outchar: 'ˆ' }, + { actionId: 'A_1', key: 'K_A', behaviour: '2', modifier: 'NCAPS SHIFT', outchar: 'Â' }, + { actionId: 'A_1', key: 'K_A', behaviour: '2', modifier: 'SHIFT CAPS', outchar: 'Â' }, + { actionId: 'A_1', key: 'K_A', behaviour: '1', modifier: 'CAPS', outchar: 'Â' }, + { actionId: 'A_10', key: 'K_E', behaviour: '0', modifier: 'NCAPS', outchar: 'ê' }, + { actionId: 'A_11', key: 'K_I', behaviour: '0', modifier: 'NCAPS', outchar: 'î' }, + { actionId: 'A_13', key: 'K_O', behaviour: '0', modifier: 'NCAPS', outchar: 'ô' }, + { actionId: 'A_14', key: 'K_U', behaviour: '0', modifier: 'NCAPS', outchar: 'û' }, + { actionId: 'A_2', key: 'K_E', behaviour: '2', modifier: 'NCAPS SHIFT', outchar: 'Ê' }, + { actionId: 'A_2', key: 'K_E', behaviour: '2', modifier: 'SHIFT CAPS', outchar: 'Ê' }, + { actionId: 'A_2', key: 'K_E', behaviour: '1', modifier: 'CAPS', outchar: 'Ê' }, + { actionId: 'A_3', key: 'K_I', behaviour: '2', modifier: 'NCAPS SHIFT', outchar: 'Î' }, + { actionId: 'A_3', key: 'K_I', behaviour: '2', modifier: 'SHIFT CAPS', outchar: 'Î' }, + { actionId: 'A_3', key: 'K_I', behaviour: '1', modifier: 'CAPS', outchar: 'Î' }, + { actionId: 'A_5', key: 'K_O', behaviour: '2', modifier: 'NCAPS SHIFT', outchar: 'Ô' }, + { actionId: 'A_5', key: 'K_O', behaviour: '2', modifier: 'SHIFT CAPS', outchar: 'Ô' }, + { actionId: 'A_5', key: 'K_O', behaviour: '1', modifier: 'CAPS', outchar: 'Ô' }, + { actionId: 'A_6', key: 'K_U', behaviour: '2', modifier: 'NCAPS SHIFT', outchar: 'Û' }, + { actionId: 'A_6', key: 'K_U', behaviour: '2', modifier: 'SHIFT CAPS', outchar: 'Û' }, + { actionId: 'A_6', key: 'K_U', behaviour: '1', modifier: 'CAPS', outchar: 'Û' }, + { actionId: 'A_9', key: 'K_A', behaviour: '0', modifier: 'NCAPS', outchar: 'â' } ]; [[b1_keycode_arr, b1_modifierKey_arr], - [[['49', 'K_SPACE', 'A_0', '0', 'ˆ']], [['K_SPACE', 'A_0', '0', 'NCAPS', 'ˆ']]], - [[['49', 'K_SPACE', 'A_0', '0', '']], [['K_SPACE', 'A_0', '0', 'NCAPS', '']]], - [[['49', 'K_SPACE', 'A_0', '', 'ˆ']], [['K_SPACE', 'A_0', '', 'NCAPS', 'ˆ']]], - [[['49', 'K_SPACE', '', '0', 'ˆ']], [['K_SPACE', '', '0', 'NCAPS', 'ˆ']]], - [[['49', '', 'A_0', '0', 'ˆ']], [['', 'A_0', '0', 'NCAPS', 'ˆ']]], - [[['', 'K_SPACE', 'A_0', '0', 'ˆ']], [['K_SPACE', 'A_0', '0', 'NCAPS', 'ˆ']]], - [[['', 'K_SPACE', 'A_0', '0', 'ˆ']], [['K_SPACE', 'A_0', '0', 'NCAPS', 'ˆ']]], - [[['', '', '', '', '']], [['', '', '', 'NCAPS', '']]], + [[{ keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '0', modifier: '0', outchar: 'ˆ' }], [{ actionId: 'A_0', key: 'K_SPACE', behaviour: '0', modifier: 'NCAPS', outchar: 'ˆ' }]], + [[{ keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '0', modifier: '', outchar: 'ˆ' }], [{ actionId: 'A_0', key: 'K_SPACE', behaviour: '0', modifier: 'NCAPS', outchar: 'ˆ' }]], + [[{ keyCode: '49', key: 'K_SPACE', actionId: '', behaviour: '0', modifier: '0', outchar: 'ˆ' }], [{ actionId: '', key: 'K_SPACE', behaviour: '0', modifier: 'NCAPS', outchar: 'ˆ' }]], + [[{ keyCode: '49', key: '', actionId: 'A_0', behaviour: '0', modifier: '0', outchar: 'ˆ' }], [{ actionId: 'A_0', key: '', behaviour: '0', modifier: 'NCAPS', outchar: 'ˆ' }]], + [[{ keyCode: '', key: 'K_SPACE', actionId: 'A_0', behaviour: '0', modifier: '0', outchar: 'ˆ' }], [{ actionId: 'A_0', key: 'K_SPACE', behaviour: '0', modifier: 'NCAPS', outchar: 'ˆ' }]], + [[{ keyCode: '', key: '', actionId: '', behaviour: '0', modifier: '', outchar: '' }], [{ actionId: '', key: '', behaviour: '0', modifier: 'NCAPS', outchar: '' }]], ].forEach(function (values) { - const isCaps_used = true; - const string_in = "get_7o_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array_oldArrayType(['" + "', '" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "', '" + values[0][0][3] + "', '" + values[0][0][4] + "'])"; - const string_out = "['" + "', '" + values[1][0][0] + "', '" + values[1][0][1] + "', '" + values[1][0][2] + "', '" + values[1][0][3] + "', '" + values[1][0][4] + "']"; - - - //console.log("FUNCTION NEEDS ", values[0]); - + const string_in = "get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(['" + "', '" + "', '" + values[0][0].keyCode + "', '" + values[0][0].key + "', '" + values[0][0].actionId + "', '" + values[0][0].modifier + "', '" + values[0][0].outchar + "'])"; + const string_out = "['" + "', '" + "', '" + values[1][0].key + "', '" + values[1][0].actionId + "', '" + "', '" + values[1][0].modifier + "', '" + values[1][0].outchar + "']"; it((JSON.stringify(values[1]).length > 60) ? 'an array of objects should return an array of objects' : string_in.padEnd(74, " ") + ' should return ' + string_out, async function () { - const result = sut.get_7o_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array_oldArrayType(read, values[0], isCaps_used); + const result = sut.get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(read, values[0], isCaps_used); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); - [[[['49', 'K_SPACE', 'A_0', '0', 'ˆ']], [['K_SPACE', 'A_0', '0', '', 'ˆ']]], - [[['49', 'K_SPACE', 'A_0', '0', '']], [['K_SPACE', 'A_0', '0', '', '']]], - [[['', 'K_SPACE', 'A_0', '0', 'ˆ']], [['K_SPACE', 'A_0', '0', '', 'ˆ']]], - [[['', '', '', '', '']], [['', '', '', '', '']]], + [[{ keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '0', modifier: '0', outchar: 'ˆ' }, { actionId: 'A_0', key: 'K_SPACE', behaviour: '0', modifier: '', outchar: 'ˆ' }], + [{ keyCode: '', key: 'K_SPACE', actionId: 'A_0', behaviour: '0', modifier: '0', outchar: 'ˆ' }, { actionId: 'A_0', key: 'K_SPACE', behaviour: '0', modifier: '', outchar: 'ˆ' }], + [{ keyCode: '', key: '', actionId: '', behaviour: '0', modifier: '', outchar: '' }, { actionId: '', key: '', behaviour: '0', modifier: '', outchar: '' }], ].forEach(function (values) { - const isCaps_used = false; - const string_in = "get_7o_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array_oldArrayType(['" + "', '" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "', '" + values[0][0][3] + "', '" + values[0][0][4] + "'])"; - const string_out = "['" + "', '" + values[1][0][0] + "', '" + values[1][0][1] + "', '" + values[1][0][2] + "', '" + values[1][0][3] + "', '" + values[1][0][4] + "']"; + const string_in = "get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array([ '" + values[0].keyCode + "', '" + values[0].key + "', '" + values[0].actionId + "', '" + values[0].modifier + "', '" + values[0].outchar + "'])"; + const string_out = "['" + values[1].actionId + "', '" + "', '" + values[1].modifier + "', '" + values[1].key + "', '" + values[1].outchar + "']"; it(string_in.padEnd(74, " ") + ' should return ' + string_out, async function () { - const result = sut.get_7o_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array_oldArrayType(read, values[0], isCaps_used); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + const result = sut.get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(read, [values[0]], isCaps_used); + assert.equal(JSON.stringify(result), JSON.stringify([values[1]])); }); }); @@ -645,178 +488,13 @@ console.log("XXX get_3_Modifier_array__From__KeyModifier_array(['" , values[0] , [null, []], ].forEach(function (values) { const isCaps = true; - it(("get_7o_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array_oldArrayType([" + values[0] + "])").padEnd(74, " ") + ' should return ' + "[" + values[1] + "]", async function () { - const result = sut.get_7o_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array_oldArrayType(read, values[0], isCaps); + it(("get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array([" + values[0] + "])").padEnd(74, " ") + ' should return ' + "[" + values[1] + "]", async function () { + const result = sut.get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(read, values[0], isCaps); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); }); - //_S2 Todo finish !! - describe('get_7_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array ', function () { - /*const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); - const read = sut_r.read(inputFilename);*/ - - const b1_keycode_arr = [ - // _S2 Todo write in object-fornm - - ['49', 'K_SPACE', 'A_0', '0', 'ˆ'], - ['49', 'K_SPACE', 'A_0', '1', 'ˆ'], - ['49', 'K_SPACE', 'A_0', '2', 'ˆ'], - ['6', 'K_Z', 'A_0', '4', 'ˆ'], - ['25', 'K_9', 'A_0', '4', 'ˆ'], - ['43', 'K_COMMA', 'A_0', '4', 'ˆ'], - ['49', 'K_SPACE', 'A_0', '3', 'ˆ'], - ['0', 'K_A', 'A_1', '2', 'Â'], - ['0', 'K_A', 'A_1', '1', 'Â'], - ['14', 'K_E', 'A_10', '0', 'ê'], - ['34', 'K_I', 'A_11', '0', 'î'], - ['31', 'K_O', 'A_13', '0', 'ô'], - ['32', 'K_U', 'A_14', '0', 'û'], - ['14', 'K_E', 'A_2', '2', 'Ê'], - ['14', 'K_E', 'A_2', '1', 'Ê'], - ['34', 'K_I', 'A_3', '2', 'Î'], - ['34', 'K_I', 'A_3', '1', 'Î'], - ['31', 'K_O', 'A_5', '2', 'Ô'], - ['31', 'K_O', 'A_5', '1', 'Ô'], - ['32', 'K_U', 'A_6', '2', 'Û'], - ['32', 'K_U', 'A_6', '1', 'Û'], - ['0', 'K_A', 'A_9', '0', 'â']/**/ - ]; - const b1_modifierKey_arr = [ - /* ['K_SPACE', 'A_0', '0', 'NCAPS', 'ˆ'], - ... - ['K_A', 'A_9', '0', 'NCAPS', 'â'],*/ - { "search": "", "actionId": "A_0", "behaviour": "0", "modifier": "NCAPS", "key": "K_SPACE", "outchar": "ˆ" }, - { "search": "", "actionId": "A_0", "behaviour": "1", "modifier": "CAPS", "key": "K_SPACE", "outchar": "ˆ" }, - { "search": "", "actionId": "A_0", "behaviour": "2", "modifier": "NCAPS SHIFT", "key": "K_SPACE", "outchar": "ˆ" }, - { "search": "", "actionId": "A_0", "behaviour": "2", "modifier": "SHIFT CAPS", "key": "K_SPACE", "outchar": "ˆ" }, - { "search": "", "actionId": "A_0", "behaviour": "4", "modifier": "NCAPS SHIFT RALT", "key": "K_Z", "outchar": "ˆ" }, - { "search": "", "actionId": "A_0", "behaviour": "4", "modifier": "NCAPS SHIFT RALT", "key": "K_9", "outchar": "ˆ" }, - { "search": "", "actionId": "A_0", "behaviour": "4", "modifier": "NCAPS SHIFT RALT", "key": "K_COMMA", "outchar": "ˆ" }, - { "search": "", "actionId": "A_0", "behaviour": "3", "modifier": "NCAPS RALT CTRL", "key": "K_SPACE", "outchar": "ˆ" }, - { "search": "", "actionId": "A_0", "behaviour": "3", "modifier": "NCAPS CTRL", "key": "K_SPACE", "outchar": "ˆ" }, - { "search": "", "actionId": "A_1", "behaviour": "2", "modifier": "NCAPS SHIFT", "key": "K_A", "outchar": "Â" }, - { "search": "", "actionId": "A_1", "behaviour": "2", "modifier": "SHIFT CAPS", "key": "K_A", "outchar": "Â" }, - { "search": "", "actionId": "A_1", "behaviour": "1", "modifier": "CAPS", "key": "K_A", "outchar": "Â" }, - { "search": "", "actionId": "A_10", "behaviour": "0", "modifier": "NCAPS", "key": "K_E", "outchar": "ê" }, - { "search": "", "actionId": "A_11", "behaviour": "0", "modifier": "NCAPS", "key": "K_I", "outchar": "î" }, - { "search": "", "actionId": "A_13", "behaviour": "0", "modifier": "NCAPS", "key": "K_O", "outchar": "ô" }, - { "search": "", "actionId": "A_14", "behaviour": "0", "modifier": "NCAPS", "key": "K_U", "outchar": "û" }, - { "search": "", "actionId": "A_2", "behaviour": "2", "modifier": "NCAPS SHIFT", "key": "K_E", "outchar": "Ê" }, - { "search": "", "actionId": "A_2", "behaviour": "2", "modifier": "SHIFT CAPS", "key": "K_E", "outchar": "Ê" }, - { "search": "", "actionId": "A_2", "behaviour": "1", "modifier": "CAPS", "key": "K_E", "outchar": "Ê" }, - { "search": "", "actionId": "A_3", "behaviour": "2", "modifier": "NCAPS SHIFT", "key": "K_I", "outchar": "Î" }, - { "search": "", "actionId": "A_3", "behaviour": "2", "modifier": "SHIFT CAPS", "key": "K_I", "outchar": "Î" }, - { "search": "", "actionId": "A_3", "behaviour": "1", "modifier": "CAPS", "key": "K_I", "outchar": "Î" }, - { "search": "", "actionId": "A_5", "behaviour": "2", "modifier": "NCAPS SHIFT", "key": "K_O", "outchar": "Ô" }, - { "search": "", "actionId": "A_5", "behaviour": "2", "modifier": "SHIFT CAPS", "key": "K_O", "outchar": "Ô" }, - { "search": "", "actionId": "A_5", "behaviour": "1", "modifier": "CAPS", "key": "K_O", "outchar": "Ô" }, - { "search": "", "actionId": "A_6", "behaviour": "2", "modifier": "NCAPS SHIFT", "key": "K_U", "outchar": "Û" }, - { "search": "", "actionId": "A_6", "behaviour": "2", "modifier": "SHIFT CAPS", "key": "K_U", "outchar": "Û" }, - { "search": "", "actionId": "A_6", "behaviour": "1", "modifier": "CAPS", "key": "K_U", "outchar": "Û" }, - { "search": "", "actionId": "A_9", "behaviour": "0", "modifier": "NCAPS", "key": "K_A", "outchar": "â" } - ]; - - [[b1_keycode_arr, b1_modifierKey_arr], - [[['49', 'K_SPACE', 'A_0', '0', 'ˆ']], [['K_SPACE', 'A_0', '0', 'NCAPS', 'ˆ']]], - [[['49', 'K_SPACE', 'A_0', '0', '']], [['K_SPACE', 'A_0', '0', 'NCAPS', '']]], - [[['49', 'K_SPACE', 'A_0', '', 'ˆ']], [['K_SPACE', 'A_0', '', 'NCAPS', 'ˆ']]], - [[['49', 'K_SPACE', '', '0', 'ˆ']], [['K_SPACE', '', '0', 'NCAPS', 'ˆ']]], - [[['49', '', 'A_0', '0', 'ˆ']], [['', 'A_0', '0', 'NCAPS', 'ˆ']]], - [[['', 'K_SPACE', 'A_0', '0', 'ˆ']], [['K_SPACE', 'A_0', '0', 'NCAPS', 'ˆ']]], - [[['', 'K_SPACE', 'A_0', '0', 'ˆ']], [['K_SPACE', 'A_0', '0', 'NCAPS', 'ˆ']]], - [[['', '', '', '', '']], [['', '', '', 'NCAPS', '']]], - ].forEach(function (values) { - - /* // _S2 const isCaps_used = true; - const string_in = "get_7_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(['" + "', '" + values[0][0] + "', '" + values[0][1] + "', '" + values[0][2] + "', '" + values[0][3] + "', '" + values[0][4] + "'])"; - const string_out = "['" + "', '" + values[1][0] + "', '" + values[1][1] + "', '" + values[1][2] + "', '" + values[1][3] + "', '" + values[1][4] + "']"; - - it((JSON.stringify(values[1]).length > 60) ? 'an array of objects should return an array of objects' : - string_in.padEnd(74, " ") + ' should return ' + string_out, async function () { - const result = sut.get_7_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(read, values[0], isCaps_used); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); - });*/ - }); - - [[[['49', 'K_SPACE', 'A_0', '0', 'ˆ']], [['K_SPACE', 'A_0', '0', '', 'ˆ']]], - [[['49', 'K_SPACE', 'A_0', '0', '']], [['K_SPACE', 'A_0', '0', '', '']]], - [[['', 'K_SPACE', 'A_0', '0', 'ˆ']], [['K_SPACE', 'A_0', '0', '', 'ˆ']]], - [[['', '', '', '', '']], [['', '', '', '', '']]], - ].forEach(function (values) { - - /* const isCaps_used = false; // _S2 add again - const string_in = "get_7_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(['" + "', '" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "', '" + values[0][0][3] + "', '" + values[0][0][4] + "'])"; - const string_out = "['" + "', '" + values[1][0][0] + "', '" + values[1][0][1] + "', '" + values[1][0][2] + "', '" + values[1][0][3] + "', '" + values[1][0][4] + "']"; - - it(string_in.padEnd(74, " ") + ' should return ' + string_out, async function () { - const result = sut.get_7_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(read, values[0], isCaps_used); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); - });*/ - }); - - [[[], []], - [undefined, []], - [null, []], - ].forEach(function (values) { - /* const isCaps = true; - it(("get_7_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array([" + values[0] + "])").padEnd(74, " ") + ' should return ' + "[" + values[1] + "]", async function () { - const result = sut.get_7_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(read, values[0], isCaps); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); - });*/ - }); - }); - - - describe('get_6o_ActionStateOutput_array__From__ActionState_oldArrayType ', function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); - const read = sut_r.read(inputFilename); - - [['1', [ - ['A_0', '1', 'ˆ'], - ['A_1', '1', 'Â'], - ['A_10', '1', 'ê'], - ['A_11', '1', 'î'], - ['A_13', '1', 'ô'], - ['A_14', '1', 'û'], - ['A_2', '1', 'Ê'], - ['A_3', '1', 'Î'], - ['A_5', '1', 'Ô'], - ['A_6', '1', 'Û'], - ['A_9', '1', 'â']],], - ['2', [ - ['A_0', '2', '`'], - ['A_1', '2', 'À'], - ['A_10', '2', 'è'], - ['A_11', '2', 'ì'], - ['A_13', '2', 'ò'], - ['A_14', '2', 'ù'], - ['A_2', '2', 'È'], - ['A_3', '2', 'Ì'], - ['A_5', '2', 'Ò'], - ['A_6', '2', 'Ù'], - ['A_9', '2', 'à']],], - ['789', [],], - ['', [],], - [' ', [],], - [123, [],], - [null, [],], - [undefined, [],], - ].forEach(function (values) { - it((JSON.stringify(values[1]).length > 30) ? - ("get_6o_ActionStateOutput_array__From__ActionState_oldArrayType('" + values[0] + "')").padEnd(60, " ") + ' should return an array of objects' : - ("get_6o_ActionStateOutput_array__From__ActionState_oldArrayType('" + values[0] + "')").padEnd(60, " ") + ' should return ' + "'" + JSON.stringify(values[1]) + "'", async function () { - const result = sut.get_6o_ActionStateOutput_array__From__ActionState_oldArrayType(read, String(values[0])); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); - }); - }); - }); - - describe('get_6_ActionStateOutput_array__From__ActionState ', function () { + describe('get_ActionStateOutput_array__From__ActionState ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Test.keylayout'); @@ -856,16 +534,14 @@ console.log("XXX get_3_Modifier_array__From__KeyModifier_array(['" , values[0] , [undefined, [],], ].forEach(function (values) { it((JSON.stringify(values[1]).length > 30) ? - ("get_6_ActionStateOutput_array__From__ActionState('" + values[0] + "')").padEnd(60, " ") + ' should return an array of objects' : - ("get_6_ActionStateOutput_array__From__ActionState('" + values[0] + "')").padEnd(60, " ") + ' should return ' + "'" + JSON.stringify(values[1]) + "'", async function () { - const result = sut.get_6_ActionStateOutput_array__From__ActionState(read, String(values[0])); + ("get_ActionStateOutput_array__From__ActionState('" + values[0] + "')").padEnd(60, " ") + ' should return an array of objects' : + ("get_ActionStateOutput_array__From__ActionState('" + values[0] + "')").padEnd(60, " ") + ' should return ' + "'" + JSON.stringify(values[1]) + "'", async function () { + const result = sut.get_ActionStateOutput_array__From__ActionState(read, String(values[0])); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); }); - - - describe('get_8_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput ', function () { + describe('get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Test.keylayout'); @@ -874,254 +550,136 @@ console.log("XXX get_3_Modifier_array__From__KeyModifier_array(['" , values[0] , [ ['A_1', 'A', true, - [{ "search": "A_1", "outchar": "A", "actionId": "A_1", "behaviour": "1", "key": "K_A", "modifier": "CAPS" }, - { "search": "A_1", "outchar": "A", "actionId": "A_1", "behaviour": "2", "key": "K_A", "modifier": "NCAPS SHIFT" }, - { "search": "A_1", "outchar": "A", "actionId": "A_1", "behaviour": "2", "key": "K_A", "modifier": "SHIFT CAPS" }] + [{ "outchar": "A", "actionId": "A_1", "behaviour": "1", "key": "K_A", "modifier": "CAPS" }, + { "outchar": "A", "actionId": "A_1", "behaviour": "2", "key": "K_A", "modifier": "NCAPS SHIFT" }, + { "outchar": "A", "actionId": "A_1", "behaviour": "2", "key": "K_A", "modifier": "SHIFT CAPS" }] ], ['A_1', 'A', false, - [{ "search": "A_1", "outchar": "A", "actionId": "A_1", "behaviour": "1", "key": "K_A", "modifier": "CAPS" }, - { "search": "A_1", "outchar": "A", "actionId": "A_1", "behaviour": "2", "key": "K_A", "modifier": "SHIFT" }, - { "search": "A_1", "outchar": "A", "actionId": "A_1", "behaviour": "2", "key": "K_A", "modifier": "SHIFT CAPS" }] + [{ "outchar": "A", "actionId": "A_1", "behaviour": "1", "key": "K_A", "modifier": "CAPS" }, + { "outchar": "A", "actionId": "A_1", "behaviour": "2", "key": "K_A", "modifier": "SHIFT" }, + { "outchar": "A", "actionId": "A_1", "behaviour": "2", "key": "K_A", "modifier": "SHIFT CAPS" }] ], - ['A_9', 'a', true, [{ "search": "A_9", "outchar": "a", "actionId": "A_9", "behaviour": "0", "key": "K_A", "modifier": "NCAPS" }]], - ['A_9', 'a', false, [{ "search": "A_9", "outchar": "a", "actionId": "A_9", "behaviour": "0", "key": "K_A", "modifier": "" }]], - ['A_9', 'a', , [{ "search": "A_9", "outchar": "a", "actionId": "A_9", "behaviour": "0", "key": "K_A", "modifier": "" }]], - ['A_9', '', true, [{ "search": "A_9", "outchar": "", "actionId": "A_9", "behaviour": "0", "key": "K_A", "modifier": "NCAPS" }]], - ['A_9', '', false, [{ "search": "A_9", "outchar": "", "actionId": "A_9", "behaviour": "0", "key": "K_A", "modifier": "" }]], + ['A_9', 'a', true, [{ "outchar": "a", "actionId": "A_9", "behaviour": "0", "key": "K_A", "modifier": "NCAPS" }]], + ['A_9', 'a', false, [{ "outchar": "a", "actionId": "A_9", "behaviour": "0", "key": "K_A", "modifier": "" }]], + ['A_9', 'a', , [{ "outchar": "a", "actionId": "A_9", "behaviour": "0", "key": "K_A", "modifier": "" }]], + ['A_9', '', true, [{ "outchar": "", "actionId": "A_9", "behaviour": "0", "key": "K_A", "modifier": "NCAPS" }]], + ['A_9', '', false, [{ "outchar": "", "actionId": "A_9", "behaviour": "0", "key": "K_A", "modifier": "" }]], ['', 'a', true, []], ['', 'a', false, []], ['', '', , []], ].forEach(function (values) { it((JSON.stringify(values[3]).length > 35) ? - ("get_8_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput('" + values[0] + "', '" + values[1] + "', " + values[2] + ")").padEnd(67, " ") + ' should return an array of objects' : - ("get_8_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput('" + values[0] + "', '" + values[1] + "', " + values[2] + ")").padEnd(67, " ") + ' should return ' + "'" + JSON.stringify(values[3]) + "'", async function () { - const result = sut.get_8_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput(read, converted.arrayOf_Modifiers, String(values[0]), String(values[1]), Boolean(values[2])); - console.log("result ", result); - + ("get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput('" + values[0] + "', '" + values[1] + "', " + values[2] + ")").padEnd(67, " ") + ' should return an array of objects' : + ("get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput('" + values[0] + "', '" + values[1] + "', " + values[2] + ")").padEnd(67, " ") + ' should return ' + "'" + JSON.stringify(values[3]) + "'", async function () { + const result = sut.get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput(read, converted.arrayOf_Modifiers, String(values[0]), String(values[1]), Boolean(values[2])); assert.equal(JSON.stringify(result), JSON.stringify(values[3])); }); }); }); - - describe('get_5o_KeyActionOutput_array__From__ActionStateOutput_array_oldArrayType ', function () { + describe('get_KeyActionOutput_array__From__ActionStateOutput_array ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Test.keylayout'); const read = sut_r.read(inputFilename); - const b6_actionId_arr = [ - ['A_0', '1', 'ˆ'], - ['A_1', '1', 'Â'], - ['A_10', '1', 'ê'], - ['A_11', '1', 'î'], - ['A_13', '1', 'ô'], - ['A_14', '1', 'û'], - ['A_2', '1', 'Ê'], - ['A_3', '1', 'Î'], - ['A_5', '1', 'Ô'], - ['A_6', '1', 'Û'], - ['A_9', '1', 'â'] + const b6_actionId_arr: idStateOutput_object[] = [ + { "id": "A_0", "state": "1", "output": "ˆ" }, + { "id": "A_1", "state": "1", "output": "Â" }, + { "id": "A_10", "state": "1", "output": "ê" }, + { "id": "A_11", "state": "1", "output": "î" }, + { "id": "A_13", "state": "1", "output": "ô" }, + { "id": "A_14", "state": "1", "output": "û" }, + { "id": "A_2", "state": "1", "output": "Ê" }, + { "id": "A_3", "state": "1", "output": "Î" }, + { "id": "A_5", "state": "1", "output": "Ô" }, + { "id": "A_6", "state": "1", "output": "Û" }, + { "id": "A_9", "state": "1", "output": "â" } ]; - const b1_keycode_arr = [ - ['49', 'K_SPACE', 'A_0', '0', 'ˆ'], - ['49', 'K_SPACE', 'A_0', '1', 'ˆ'], - ['49', 'K_SPACE', 'A_0', '2', 'ˆ'], - ['49', 'K_SPACE', 'A_0', '3', 'ˆ'], - ['6', 'K_Z', 'A_0', '4', 'ˆ'], - ['25', 'K_9', 'A_0', '4', 'ˆ'], - ['43', 'K_COMMA', 'A_0', '4', 'ˆ'], - ['0', 'K_A', 'A_1', '1', 'Â'], - ['0', 'K_A', 'A_1', '2', 'Â'], - ['14', 'K_E', 'A_10', '0', 'ê'], - ['34', 'K_I', 'A_11', '0', 'î'], - ['31', 'K_O', 'A_13', '0', 'ô'], - ['32', 'K_U', 'A_14', '0', 'û'], - ['14', 'K_E', 'A_2', '1', 'Ê'], - ['14', 'K_E', 'A_2', '2', 'Ê'], - ['34', 'K_I', 'A_3', '1', 'Î'], - ['34', 'K_I', 'A_3', '2', 'Î'], - ['31', 'K_O', 'A_5', '1', 'Ô'], - ['31', 'K_O', 'A_5', '2', 'Ô'], - ['32', 'K_U', 'A_6', '1', 'Û'], - ['32', 'K_U', 'A_6', '2', 'Û'], - ['0', 'K_A', 'A_9', '0', 'â'] + const b1_keycode_arr: allArrayContents_object[] = [ + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '0', outchar: 'ˆ' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '1', outchar: 'ˆ' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '2', outchar: 'ˆ' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '3', outchar: 'ˆ' }, + { keyCode: '6', key: 'K_Z', actionId: 'A_0', behaviour: '4', outchar: 'ˆ' }, + { keyCode: '25', key: 'K_9', actionId: 'A_0', behaviour: '4', outchar: 'ˆ' }, + { keyCode: '43', key: 'K_COMMA', actionId: 'A_0', behaviour: '4', outchar: 'ˆ' }, + { keyCode: '0', key: 'K_A', actionId: 'A_1', behaviour: '1', outchar: 'Â' }, + { keyCode: '0', key: 'K_A', actionId: 'A_1', behaviour: '2', outchar: 'Â' }, + { keyCode: '14', key: 'K_E', actionId: 'A_10', behaviour: '0', outchar: 'ê' }, + { keyCode: '34', key: 'K_I', actionId: 'A_11', behaviour: '0', outchar: 'î' }, + { keyCode: '31', key: 'K_O', actionId: 'A_13', behaviour: '0', outchar: 'ô' }, + { keyCode: '32', key: 'K_U', actionId: 'A_14', behaviour: '0', outchar: 'û' }, + { keyCode: '14', key: 'K_E', actionId: 'A_2', behaviour: '1', outchar: 'Ê' }, + { keyCode: '14', key: 'K_E', actionId: 'A_2', behaviour: '2', outchar: 'Ê' }, + { keyCode: '34', key: 'K_I', actionId: 'A_3', behaviour: '1', outchar: 'Î' }, + { keyCode: '34', key: 'K_I', actionId: 'A_3', behaviour: '2', outchar: 'Î' }, + { keyCode: '31', key: 'K_O', actionId: 'A_5', behaviour: '1', outchar: 'Ô' }, + { keyCode: '31', key: 'K_O', actionId: 'A_5', behaviour: '2', outchar: 'Ô' }, + { keyCode: '32', key: 'K_U', actionId: 'A_6', behaviour: '1', outchar: 'Û' }, + { keyCode: '32', key: 'K_U', actionId: 'A_6', behaviour: '2', outchar: 'Û' }, + { keyCode: '0', key: 'K_A', actionId: 'A_9', behaviour: '0', outchar: 'â' } ]; [[b6_actionId_arr, b1_keycode_arr], ].forEach(function (values) { - it(("get_5o_KeyActionOutput_array__From__ActionStateOutput_array_oldArrayType([['" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "'],..])").padEnd(73, " ") + '1 should return an array of objects', async function () { - const result = sut.get_5o_KeyActionOutput_array__From__ActionStateOutput_array_oldArrayType(read, values[0]); + it(("get_KeyActionOutput_array__From__ActionStateOutput_array([['" + JSON.stringify(values[0]) + "'],..])").padEnd(73, " ") + '1 should return an array of objects', async function () { + const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0] as idStateOutput_object[]); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); const oneEntryResult = [ - ['49', 'K_SPACE', 'A_0', '0', 'ˆ'], - ['49', 'K_SPACE', 'A_0', '1', 'ˆ'], - ['49', 'K_SPACE', 'A_0', '2', 'ˆ'], - ['49', 'K_SPACE', 'A_0', '3', 'ˆ'], - ['6', 'K_Z', 'A_0', '4', 'ˆ'], - ['25', 'K_9', 'A_0', '4', 'ˆ'], - ['43', 'K_COMMA', 'A_0', '4', 'ˆ'] - ]; - const oneEntryResultNoOutput = [ - ['49', 'K_SPACE', 'A_0', '0', ''], - ['49', 'K_SPACE', 'A_0', '1', ''], - ['49', 'K_SPACE', 'A_0', '2', ''], - ['49', 'K_SPACE', 'A_0', '3', ''], - ['6', 'K_Z', 'A_0', '4', ''], - ['25', 'K_9', 'A_0', '4', ''], - ['43', 'K_COMMA', 'A_0', '4', ''] + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '0', outchar: 'ˆ' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '1', outchar: 'ˆ' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '2', outchar: 'ˆ' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '3', outchar: 'ˆ' }, + { keyCode: '6', key: 'K_Z', actionId: 'A_0', behaviour: '4', outchar: 'ˆ' }, + { keyCode: '25', key: 'K_9', actionId: 'A_0', behaviour: '4', outchar: 'ˆ' }, + { keyCode: '43', key: 'K_COMMA', actionId: 'A_0', behaviour: '4', outchar: 'ˆ' } ]; - [[[['A_0', '1', 'ˆ']], oneEntryResult], - [[['A_0', '1', '']], oneEntryResultNoOutput], - [[['A_0', '', 'ˆ']], oneEntryResult], - ].forEach(function (values) { - it(("get_5o_KeyActionOutput_array__From__ActionStateOutput_array_oldArrayType(['" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "'])").padEnd(73, " ") + '2 should return an array of objects', async function () { - const result = sut.get_5o_KeyActionOutput_array__From__ActionStateOutput_array_oldArrayType(read, values[0]); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); - }); - }); - - [[[['', '1', 'ˆ']], []], - [[['', '', '']], []], - [[[' ', ' ', '']], []], - ].forEach(function (values) { - it(("get_5o_KeyActionOutput_array__From__ActionStateOutput_array_oldArrayType(['" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "'])").padEnd(73, " ") + ' should return ' + "'[" + values[1] + "]'", async function () { - const result = sut.get_5o_KeyActionOutput_array__From__ActionStateOutput_array_oldArrayType(read, values[0]); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); - }); - }); - - [[[], []], - [undefined, []], - [null, []], - ].forEach(function (values) { - it(("get_5o_KeyActionOutput_array__From__ActionStateOutput_array_oldArrayType(" + values[0] + ")").padEnd(73, " ") + ' should return ' + "'[" + values[1] + "]'", async function () { - const result = sut.get_5o_KeyActionOutput_array__From__ActionStateOutput_array_oldArrayType(read, values[0]); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); - }); - }); - }); - - describe('get_5_KeyActionOutput_array__From__ActionStateOutput_array ', function () { - /* const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); - const read = sut_r.read(inputFilename); - - const b6_actionId_arr = [ -*/ - - // [{ "id": "A_0", "state": "1", "output": "ˆ" }], - // [{ "id": "A_1", "state": "1", "output": "Â" }], - // [{ "id": "A_10", "state": "1", "output": "ê" }], - // [{ "id": "A_11", "state": "1", "output": "î" }], - // [{ "id": "A_13", "state": "1", "output": "ô" }], - // [{ "id": "A_14", "state": "1", "output": "û" }], - // // [{ "id": "A_2", "state": "1", "output": "Ê" }], - // [{ "id": "A_3", "state": "1", "output": "Î" }], - // [{ "id": "A_5", "state": "1", "output": "Ô" }], - // [{ "id": "A_6", "state": "1", "output": "Û" }], - // [{ "id": "A_9", "state": "1", "output": "â" }] - - /* ['A_0', '1', 'ˆ'], - ['A_1', '1', 'Â'], - ['A_10', '1', 'ê'], - ['A_11', '1', 'î'], - ['A_13', '1', 'ô'], - ['A_14', '1', 'û'], - ['A_2', '1', 'Ê'], - ['A_3', '1', 'Î'], - ['A_5', '1', 'Ô'], - ['A_6', '1', 'Û'], - ['A_9', '1', 'â'] - ]; - const b1_keycode_arr = [ - ['49', 'K_SPACE', 'A_0', '0', 'ˆ'], - ['49', 'K_SPACE', 'A_0', '1', 'ˆ'], - ['49', 'K_SPACE', 'A_0', '2', 'ˆ'], - ['49', 'K_SPACE', 'A_0', '3', 'ˆ'], - ['6', 'K_Z', 'A_0', '4', 'ˆ'], - ['25', 'K_9', 'A_0', '4', 'ˆ'], - ['43', 'K_COMMA', 'A_0', '4', 'ˆ'], - - ['0', 'K_A', 'A_1', '1', 'Â'], - ['0', 'K_A', 'A_1', '2', 'Â'], - ['14', 'K_E', 'A_10', '0', 'ê'], - ['34', 'K_I', 'A_11', '0', 'î'], - ['31', 'K_O', 'A_13', '0', 'ô'], - ['32', 'K_U', 'A_14', '0', 'û'], - ['14', 'K_E', 'A_2', '1', 'Ê'], - ['14', 'K_E', 'A_2', '2', 'Ê'], - ['34', 'K_I', 'A_3', '1', 'Î'], - ['34', 'K_I', 'A_3', '2', 'Î'], - ['31', 'K_O', 'A_5', '1', 'Ô'], - ['31', 'K_O', 'A_5', '2', 'Ô'], - ['32', 'K_U', 'A_6', '1', 'Û'], - ['32', 'K_U', 'A_6', '2', 'Û'], - ['0', 'K_A', 'A_9', '0', 'â'] - ]; - - [[b6_actionId_arr, b1_keycode_arr], - ].forEach(function (values) { - it(("get_5_KeyActionOutput_array__From__ActionStateOutput_array([['" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "'],..])").padEnd(73, " ") + '1 should return an array of objects', async function () { - const result = sut.get_5_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0]); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); - }); - }); - - const oneEntryResult = [ - ['49', 'K_SPACE', 'A_0', '0', 'ˆ'], - ['49', 'K_SPACE', 'A_0', '1', 'ˆ'], - ['49', 'K_SPACE', 'A_0', '2', 'ˆ'], - ['49', 'K_SPACE', 'A_0', '3', 'ˆ'], - ['6', 'K_Z', 'A_0', '4', 'ˆ'], - ['25', 'K_9', 'A_0', '4', 'ˆ'], - ['43', 'K_COMMA', 'A_0', '4', 'ˆ'] - ]; const oneEntryResultNoOutput = [ - ['49', 'K_SPACE', 'A_0', '0', ''], - ['49', 'K_SPACE', 'A_0', '1', ''], - ['49', 'K_SPACE', 'A_0', '2', ''], - ['49', 'K_SPACE', 'A_0', '3', ''], - ['6', 'K_Z', 'A_0', '4', ''], - ['25', 'K_9', 'A_0', '4', ''], - ['43', 'K_COMMA', 'A_0', '4', ''] + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '0', outchar: '' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '1', outchar: '' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '2', outchar: '' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '3', outchar: '' }, + { keyCode: '6', key: 'K_Z', actionId: 'A_0', behaviour: '4', outchar: '' }, + { keyCode: '25', key: 'K_9', actionId: 'A_0', behaviour: '4', outchar: '' }, + { keyCode: '43', key: 'K_COMMA', actionId: 'A_0', behaviour: '4', outchar: '' }, ]; - [[[['A_0', '1', 'ˆ']], oneEntryResult], - [[['A_0', '1', '']], oneEntryResultNoOutput], - [[['A_0', '', 'ˆ']], oneEntryResult], + [[[{ "id": "A_0", "state": "1", "output": "ˆ" }], oneEntryResult], + [[{ "id": "A_0", "state": "1", "output": "" }], oneEntryResultNoOutput], + [[{ "id": "A_0", "state": "", "output": "ˆ" }], oneEntryResult], ].forEach(function (values) { - it(("get_5_KeyActionOutput_array__From__ActionStateOutput_array(['" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "'])").padEnd(73, " ") + '2 should return an array of objects', async function () { - const result = sut.get_5_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0]); + it(("get_KeyActionOutput_array__From__ActionStateOutput_array(['" + JSON.stringify(values[0]) + "'])").padEnd(73, " ") + '2 should return an array of objects', async function () { + const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0] as idStateOutput_object[]); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); - [[[['', '1', 'ˆ']], []], - [[['', '', '']], []], - [[[' ', ' ', '']], []], + [[[{ "id": "", "state": "1", "output": "ˆ" }], []], + [[{ "id": "", "state": "", "output": "" }], []], + [[{ "id": " ", "state": " ", "output": "" }], []], + ].forEach(function (values) { - it(("get_5_KeyActionOutput_array__From__ActionStateOutput_array(['" + values[0][0][0] + "', '" + values[0][0][1] + "', '" + values[0][0][2] + "'])").padEnd(73, " ") + ' should return ' + "'[" + values[1] + "]'", async function () { - const result = sut.get_5_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0]); + it(("get_KeyActionOutput_array__From__ActionStateOutput_array(" + JSON.stringify(values[0]) + ")").padEnd(73, " ") + ' should return ' + "'[" + JSON.stringify(values[1]) + "]'", async function () { + const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0] as idStateOutput_object[]); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); - [[[], []], + [[, []], [undefined, []], [null, []], ].forEach(function (values) { - it(("get_5_KeyActionOutput_array__From__ActionStateOutput_array(" + values[0] + ")").padEnd(73, " ") + ' should return ' + "'[" + values[1] + "]'", async function () { - const result = sut.get_5_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0]); + it(("get_KeyActionOutput_array__From__ActionStateOutput_array(" + JSON.stringify(values[0]) + ")").padEnd(73, " ") + ' should return ' + "'[" + JSON.stringify(values[1]) + "]'", async function () { + const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0] as idStateOutput_object[]); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); - });*/ + }); }); }); diff --git a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts index 9afaae5b7b8..65fbaf5029d 100644 --- a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts +++ b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts @@ -36,7 +36,6 @@ describe('KmnFileWriter', function () { const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); it('write() should return true (no error) if written', async function () { - const result = sut_w.write(converted); assert.isTrue(result); }); From f3d5cc4bd8672e0d6ca0ff7c6da544547e28d159 Mon Sep 17 00:00:00 2001 From: Sabine Date: Fri, 1 Aug 2025 18:54:24 +0200 Subject: [PATCH 157/251] feat(developer): add tests --- .../keylayout-to-kmn/keylayout-file-reader.ts | 25 +- .../keylayout-to-kmn-converter.ts | 264 ++++--- .../kmc-convert/test/data/Test_C0.keylayout | 41 + .../test/data/Test_C0_C1_C2_C3.keylayout | 104 +++ .../kmc-convert/test/data/Test_C1.keylayout | 41 + .../kmc-convert/test/data/Test_C2.keylayout | 41 + .../kmc-convert/test/data/Test_C3.keylayout | 61 ++ ...erentAmountMapSelect_KeyMapERROR.keylayout | 80 ++ .../Test_duplicate_missing_keycode.keylayout | 49 ++ .../test/data/Test_modifier.keylayout | 102 +++ .../test/data/Test_modifierNoCaps.keylayout | 106 +++ .../test/data/Test_nr_elements.keylayout | 45 ++ .../test/data/Test_onlyOneKeymap.keylayout | 42 ++ .../test/keylayout-to-kmn-converter.tests.ts | 708 ++---------------- 14 files changed, 927 insertions(+), 782 deletions(-) create mode 100644 developer/src/kmc-convert/test/data/Test_C0.keylayout create mode 100644 developer/src/kmc-convert/test/data/Test_C0_C1_C2_C3.keylayout create mode 100644 developer/src/kmc-convert/test/data/Test_C1.keylayout create mode 100644 developer/src/kmc-convert/test/data/Test_C2.keylayout create mode 100644 developer/src/kmc-convert/test/data/Test_C3.keylayout create mode 100644 developer/src/kmc-convert/test/data/Test_DifferentAmountMapSelect_KeyMapERROR.keylayout create mode 100644 developer/src/kmc-convert/test/data/Test_duplicate_missing_keycode.keylayout create mode 100644 developer/src/kmc-convert/test/data/Test_modifier.keylayout create mode 100644 developer/src/kmc-convert/test/data/Test_modifierNoCaps.keylayout create mode 100644 developer/src/kmc-convert/test/data/Test_nr_elements.keylayout create mode 100644 developer/src/kmc-convert/test/data/Test_onlyOneKeymap.keylayout diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts index eb3fbd0e3ca..5b267909f93 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts @@ -13,7 +13,7 @@ import { util } from '@keymanapp/common-types'; import { ConverterMessages } from '../converter-messages.js'; import { SchemaValidators } from '@keymanapp/common-types'; import { DeveloperUtilsMessages } from '@keymanapp/developer-utils'; -import { KeylayoutXMLSourceFile } from "@keymanapp/developer-utils" +import { KeylayoutXMLSourceFile } from "@keymanapp/developer-utils"; import boxXmlArray = util.boxXmlArray; @@ -73,27 +73,22 @@ export class KeylayoutFileReader { this.remove_whitespace(source); - this.removeWhitespace_boxArray(source.layouts, 'layout'); + this.removeWhitespace_boxArray(source, 'keyMapSet'); + this.removeWhitespace_boxArray(source.layouts, 'layout'); this.removeWhitespace_boxArray(source?.modifierMap, 'keyMapSelect'); + for (const keyMapSelect of source?.modifierMap?.keyMapSelect) { this.removeWhitespace_boxArray(keyMapSelect, 'modifier'); } - // keyMapSet is the only top level tag that might occur several times => we need to consider 2 cases - if (!Array.isArray(source?.keyMapSet) === false) { - for (let i = 0; i < source?.keyMapSet.length; i++) { - for (const keyMap of source?.keyMapSet[i]?.keyMap) { - this.removeWhitespace_boxArray(keyMap, 'key'); - } - this.removeWhitespace_boxArray(source.keyMapSet[i], 'keyMap'); - } - } else { - for (const keyMap of source?.keyMapSet?.keyMap) { + this.removeWhitespace_boxArray(source.keyMapSet[0], 'keyMap'); + + for (const keyMapSet of source?.keyMapSet) { + for (const keyMap of keyMapSet.keyMap) { this.removeWhitespace_boxArray(keyMap, 'key'); } - this.removeWhitespace_boxArray(source.keyMapSet, 'keyMap'); - this.removeWhitespace_boxArray(source, 'keyMapSet'); + this.removeWhitespace_boxArray(keyMapSet, 'keyMap'); } this.removeWhitespace_boxArray(source?.actions, 'action'); @@ -133,7 +128,7 @@ export class KeylayoutFileReader { return jsonObj; } catch (err) { - this.callbacks.reportMessage(ConverterMessages.Error_FileNotFound({ inputFilename })); + this.callbacks.reportMessage(ConverterMessages.Error_UnableToRead({ inputFilename })); return null; } } diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index a90aeff27a6..908d2e0ea22 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -48,10 +48,11 @@ export interface idStateOutput_object { * @param data data read from keylayout file * @return static variable USE_KEY_COUNT holding the number of keys used in a .keykayout file. */ -export function find_usedKeysCount(data: any): number { +export function find_usedKeysCount(data: any, pos: number): number { let USE_KEY_COUNT = KeylayoutToKmnConverter.MAX_KEY_COUNT; for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { - if (data.keyboard.keyMapSet[0].keyMap[i].key.length < USE_KEY_COUNT) { + //if (data.keyboard.keyMapSet[0].keyMap[i].key.length < USE_KEY_COUNT) { + if ((i === pos) && (data.keyboard.keyMapSet[0].keyMap[i].key.length < USE_KEY_COUNT)) { // set the max to n-1 (use key 0 -> nth-1) USE_KEY_COUNT = data.keyboard.keyMapSet[0].keyMap[i].key.length - 1; } @@ -164,9 +165,9 @@ export class KeylayoutToKmnConverter { } modifierBehavior.push(singleModifierSet); } - + const behav = 0; // fix the amount of processable keys to the maximun nr of keys of a keyMap to avoid processing more keys than defined - KeylayoutToKmnConverter.USE_KEY_COUNT = find_usedKeysCount(jsonObj); + KeylayoutToKmnConverter.USE_KEY_COUNT = find_usedKeysCount(jsonObj, behav); // fill rules into arrayOf_Rules of data_object return this.createRuleData(data_object, jsonObj); @@ -191,30 +192,53 @@ export class KeylayoutToKmnConverter { // check if we use CAPS in a modifier throughout the .keylayout file. In this case we need to add NCAPS const isCapsused: boolean = this.checkIfCapsIsUsed(data_ukelele.arrayOf_Modifiers); + // if there are different amounts of keyMapSelect vs keyMap + if (jsonObj.keyboard.modifierMap?.keyMapSelect.length !== jsonObj.keyboard.keyMapSet[0].keyMap.length) { + const errorText = data_ukelele.keylayout_filename; + this.callbacks.reportMessage(ConverterMessages.Error_InvalidFile({ errorText })); + } // loop keys 0-49 (= all keys we use) - for (let j = 0; j <= KeylayoutToKmnConverter.USE_KEY_COUNT; j++) { + //for (let j = 0; j <= KeylayoutToKmnConverter.MAX_KEY_COUNT; j++) { + for (let j = 0; j <= KeylayoutToKmnConverter.MAX_KEY_COUNT; j++) { // loop behaviors (in ukelele it is possible to define multiple modifier combinations that behave in the same way) for (let i = 0; i < jsonObj.keyboard.keyMapSet[0].keyMap.length; i++) { + const KeyIndex_j = j; + const BehavIndex_i = i; + const maxKey = jsonObj.keyboard.keyMapSet[0].keyMap[i].key.length; + const maxBeh = jsonObj.keyboard.keyMapSet[0].keyMap.length; + + const isItAvailable = (((KeyIndex_j < maxKey) && (BehavIndex_i < maxBeh))); + + if (!isItAvailable) { + continue; + } + + let rule_obj: Rule; + //if (i < maxkey) { + if ((j < jsonObj.keyboard.keyMapSet[0].keyMap[i].key.length)) { + + //if (i < maxBeh) { + // if (i < jsonObj.keyboard.keyMapSet[0].keyMap.length) { + // ............................................................................................................................... + // case C0: output ............................................................................................................... + // C0 see: https://docs.google.com/document/d/12J3NGO6RxIthCpZDTR8FYSRjiMgXJDLwPY2z9xqKzJ0/edit?tab=t.0#heading=h.g7jwx3lx0ydd ... + // a key is mapped to a character directly ( code -> output) ..................................................................... + // ...............e. g. ............................................................................... + // ............................................................................................................................... - // ............................................................................................................................... - // case C0: output ............................................................................................................... - // C0 see: https://docs.google.com/document/d/12J3NGO6RxIthCpZDTR8FYSRjiMgXJDLwPY2z9xqKzJ0/edit?tab=t.0#heading=h.g7jwx3lx0ydd ... - // a key is mapped to a character directly ( code -> output) ..................................................................... - // ...............e. g. ............................................................................... - // ............................................................................................................................... + if ((jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] !== undefined) + && (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] !== "")) { - if ((jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] !== undefined) - && (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] !== "")) { + // loop modifiers + for (let l = 0; l < data_ukelele.arrayOf_Modifiers[i].length; l++) { - // loop behaviours - for (let l = 0; l < data_ukelele.arrayOf_Modifiers[i].length; l++) { - if (this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']))) { + if (this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']))) { - rule_obj = new Rule( + rule_obj = new Rule( /* rule_type */ "C0", /* modifier_prev_deadkey*/ "", @@ -230,35 +254,36 @@ export class KeylayoutToKmnConverter { /* modifier_key*/ this.create_kmn_modifier(data_ukelele.arrayOf_Modifiers[i][l], isCapsused), /* key */ this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), /* output */ new TextEncoder().encode(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output']), - ); - object_array.push(rule_obj); + ); + object_array.push(rule_obj); + } } - } + // } - } - else if (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] !== undefined) { + } + else if (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] !== undefined) { - action_id = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action']; - // ............................................................................................................................... - // case C1: action + state none + output ......................................................................................... - // C1 see: https://docs.google.com/document/d/12J3NGO6RxIthCpZDTR8FYSRjiMgXJDLwPY2z9xqKzJ0/edit?tab=t.0#heading=h.g7jwx3lx0ydd ... - // a key is mapped to an action and then to an output ............................................................................ - // KeyMap:code -> KeyMap:action->action:action_state(none) -> action_output ...................................................... - // ...............e. g. KeyMap:action->action:action_state(none) -> action_output ...................................................... + // ...............e. g. ............................................................................ - // replace state x with all rules that result in 14 ( ............................................................................ + // replace state x with all rules that result in 14 ( for action id a18 ...................................................................................................................... - for (let l = 0; l < jsonObj.keyboard.actions.action[b1_actionIndex].when.length; l++) { - if ((jsonObj.keyboard.actions.action[b1_actionIndex].when[l]['@_state'] === "none") // find "none" - && (jsonObj.keyboard.actions.action[b1_actionIndex].when[l]['@_next'] !== undefined)) { // find "next" + // with action_id from above loop all 'action' and search for a state(none)-next-pair ............................................................................................................ + // e.g. in Block 5: find for action id a18 ...................................................................................................................... + for (let l = 0; l < jsonObj.keyboard.actions.action[b1_actionIndex].when.length; l++) { + if ((jsonObj.keyboard.actions.action[b1_actionIndex].when[l]['@_state'] === "none") // find "none" + && (jsonObj.keyboard.actions.action[b1_actionIndex].when[l]['@_next'] !== undefined)) { // find "next" // Data of Block Nr 5 ..................................................................................................................................................................... // of this state(none)-next-pair get value of next (next="1") ............................................................................................................................. @@ -322,14 +347,14 @@ export class KeylayoutToKmnConverter { // create array[Keycode,Keyname,action id,actionIndex,output] and array[Keyname,action id,behaviour,modifier,output] ...................................................................... /* eg: ['0','K_A','a9','0','â'] */ const b1_keycode_obj: allArrayContents_object[] = this.get_KeyActionOutput_array__From__ActionStateOutput_array(jsonObj, b6_actionId_obj); /* eg: ['K_A','a9','0','NCAPS','â']*/ const b1_modifierKey_obj: allArrayContents_object[] = this.get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(jsonObj, b1_keycode_obj, isCapsused); - // ....................................................................................................................................................................................... + // ....................................................................................................................................................................................... - for (let n1 = 0; n1 < b4_deadkeyModifier_obj.length; n1++) { - for (let n2 = 0; n2 < b4_deadkeyModifier_obj[n1].length; n2++) { - for (let n3 = 0; n3 < b4_deadkey_obj.length; n3++) { - for (let n4 = 0; n4 < b1_modifierKey_obj.length; n4++) { + for (let n1 = 0; n1 < b4_deadkeyModifier_obj.length; n1++) { + for (let n2 = 0; n2 < b4_deadkeyModifier_obj[n1].length; n2++) { + for (let n3 = 0; n3 < b4_deadkey_obj.length; n3++) { + for (let n4 = 0; n4 < b1_modifierKey_obj.length; n4++) { - rule_obj = new Rule( + rule_obj = new Rule( /* rule_type */ "C2", /* modifier_prev_deadkey*/ "", @@ -345,35 +370,35 @@ export class KeylayoutToKmnConverter { /* modifier_key*/ b1_modifierKey_obj[n4].modifier, /* key */ b1_modifierKey_obj[n4].key, /* output */ new TextEncoder().encode(b1_modifierKey_obj[n4].outchar), - ); - if ((b1_modifierKey_obj[n4].outchar !== undefined) - && (b1_modifierKey_obj[n4].outchar !== "undefined") - && (b1_modifierKey_obj[n4].outchar !== "")) { - object_array.push(rule_obj); + ); + if ((b1_modifierKey_obj[n4].outchar !== undefined) + && (b1_modifierKey_obj[n4].outchar !== "undefined") + && (b1_modifierKey_obj[n4].outchar !== "")) { + object_array.push(rule_obj); + } } } } } } } - } - // ............................................................................................................................... - // case C3: action + state Nr + Next ............................................................................................. - // ...............e. g. ................................................................................ - // replace state x with all rules that result in 1 ( ................................................................................ + // replace state x with all rules that result in 1 ( for action id a16 ............................................................................................................................. - for (let l = 0; l < jsonObj.keyboard.actions.action[b1_actionIndex].when.length; l++) { - if ((jsonObj.keyboard.actions.action[b1_actionIndex].when[l]['@_state'] !== "none") - && (jsonObj.keyboard.actions.action[b1_actionIndex].when[l]['@_next'] !== undefined)) { + // with action_id from above loop all 'action' and search for a state-next-pair ................................................................................................................... + // e.g. in Block 5: find for action id a16 ............................................................................................................................. + for (let l = 0; l < jsonObj.keyboard.actions.action[b1_actionIndex].when.length; l++) { + if ((jsonObj.keyboard.actions.action[b1_actionIndex].when[l]['@_state'] !== "none") + && (jsonObj.keyboard.actions.action[b1_actionIndex].when[l]['@_next'] !== undefined)) { // Data of Block Nr 5 ........................................................................................................................................................................ // of this state-next-pair get value of next (next="1") and state="3" ........................................................................................................................ @@ -408,17 +433,17 @@ export class KeylayoutToKmnConverter { // create array[Keycode,Keyname,action id,actionIndex,output] and array[Keyname,action id,behaviour,modifier,output] ......................................................................... /* eg: ['49','K_SPACE','a0','0','Â'] */ const b1_keycode_obj: allArrayContents_object[] = this.get_KeyActionOutput_array__From__ActionStateOutput_array(jsonObj, b6_actionId_obj); /* eg: ['K_SPACE','a0','0','NCAPS','Â'] */ const b1_modifierKey_obj: allArrayContents_object[] = this.get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(jsonObj, b1_keycode_obj, isCapsused); - // ........................................................................................................................................................................................... + // ........................................................................................................................................................................................... - for (let n1 = 0; n1 < b2_prev_deadkeyModifier_obj.length; n1++) { - for (let n2 = 0; n2 < b2_prev_deadkeyModifier_obj[n1].length; n2++) { - for (let n3 = 0; n3 < b2_prev_deadkey_obj.length; n3++) { - for (let n4 = 0; n4 < b4_deadkeyModifier_obj.length; n4++) { - for (let n5 = 0; n5 < b4_deadkeyModifier_obj[n4].length; n5++) { - for (let n6 = 0; n6 < b4_deadkey_obj.length; n6++) { - for (let n7 = 0; n7 < b1_modifierKey_obj.length; n7++) { + for (let n1 = 0; n1 < b2_prev_deadkeyModifier_obj.length; n1++) { + for (let n2 = 0; n2 < b2_prev_deadkeyModifier_obj[n1].length; n2++) { + for (let n3 = 0; n3 < b2_prev_deadkey_obj.length; n3++) { + for (let n4 = 0; n4 < b4_deadkeyModifier_obj.length; n4++) { + for (let n5 = 0; n5 < b4_deadkeyModifier_obj[n4].length; n5++) { + for (let n6 = 0; n6 < b4_deadkey_obj.length; n6++) { + for (let n7 = 0; n7 < b1_modifierKey_obj.length; n7++) { - rule_obj = new Rule( + rule_obj = new Rule( /* rule_type */ "C3", /* modifier_prev_deadkey*/ this.create_kmn_modifier(b2_prev_deadkeyModifier_obj[n1][n2], isCapsused), /* prev_deadkey */ this.map_UkeleleKC_To_VK(Number(b2_prev_deadkey_obj[n3].key)), @@ -433,11 +458,12 @@ export class KeylayoutToKmnConverter { /* modifier_key*/ b1_modifierKey_obj[n7].modifier, /* key */ b1_modifierKey_obj[n7].key, /* output */ new TextEncoder().encode(b1_modifierKey_obj[n7].outchar), - ); - if ((b1_modifierKey_obj[n7].outchar !== undefined) - && (b1_modifierKey_obj[n7].outchar !== "undefined") - && (b1_modifierKey_obj[n7].outchar !== "")) { - object_array.push(rule_obj); + ); + if ((b1_modifierKey_obj[n7].outchar !== undefined) + && (b1_modifierKey_obj[n7].outchar !== "undefined") + && (b1_modifierKey_obj[n7].outchar !== "")) { + object_array.push(rule_obj); + } } } } @@ -448,24 +474,24 @@ export class KeylayoutToKmnConverter { } } } + } else { + + /* QUESTION + // _S2 why does this not work here? Correct data in this.callback.messages is available !?!?! + this.callbacks.reportMessage(ConverterMessages.Error_UnsupportedCharactersDetected({ + inputFilename: jsonObj.keyboard['@_name'] + ".keylayout", + keymap_index: jsonObj.keyboard.keyMapSet[0].keyMap[i]['@_index'], + output: jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'], + key: jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'] + })); + return null;*/ + + console.log(" ERROR : some output characters can not be used in Keyman \"", + (jsonObj.keyboard['@_name'] + ".keylayout\""), + "\"\" :", + jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]); + continue; } - } else { - - /* QUESTION - // _S2 why does this not work here? Correct data in this.callback.messages is available !?!?! - this.callbacks.reportMessage(ConverterMessages.Error_UnsupportedCharactersDetected({ - inputFilename: jsonObj.keyboard['@_name'] + ".keylayout", - keymap_index: jsonObj.keyboard.keyMapSet[0].keyMap[i]['@_index'], - output: jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'], - key: jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'] - })); - return null;*/ - - console.log("ERROR : some output characters can not be used in Keyman \"", - (jsonObj.keyboard['@_name'] + ".keylayout\""), - "\"\" :", - jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]); - continue; } } } @@ -495,7 +521,12 @@ export class KeylayoutToKmnConverter { unique_dkB_count++; for (let i = 0; i < object_array.length; i++) { - if ((object_array[i].modifier_deadkey !== "") && (object_array[i].deadkey !== "")) { + + + if ( + ((object_array[i].modifier_deadkey !== undefined) && (object_array[i].modifier_deadkey !== "")) && + ((object_array[i].deadkey !== undefined) && (object_array[i].deadkey !== "")) + ) { let isFirstUsedHere_dk: boolean = true; // check if not used before @@ -1006,16 +1037,15 @@ export class KeylayoutToKmnConverter { * @param search : string - an actionId to be found * @return an array: allArrayContents_object[] containing [{keycode,behaviour}] */ + // _S2 check if all array2d types ate deleted + // _S2 check if action/search is available in all get_ func public get_KeyModifier_array__From__ActionID(data: any, search: string): allArrayContents_object[] { - const mapIndexArray_2D: number[][] = []; let returnObject: allArrayContents_object; const mapIndexObject1D: allArrayContents_object[] = []; for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { for (let j = 0; j <= KeylayoutToKmnConverter.USE_KEY_COUNT; j++) { if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { - - mapIndexArray_2D.push([data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], i]); returnObject = { key: data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], behaviour: String(i), diff --git a/developer/src/kmc-convert/test/data/Test_C0.keylayout b/developer/src/kmc-convert/test/data/Test_C0.keylayout new file mode 100644 index 00000000000..e715d09b95c --- /dev/null +++ b/developer/src/kmc-convert/test/data/Test_C0.keylayout @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/Test_C0_C1_C2_C3.keylayout b/developer/src/kmc-convert/test/data/Test_C0_C1_C2_C3.keylayout new file mode 100644 index 00000000000..3525fcb7ed0 --- /dev/null +++ b/developer/src/kmc-convert/test/data/Test_C0_C1_C2_C3.keylayout @@ -0,0 +1,104 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/Test_C1.keylayout b/developer/src/kmc-convert/test/data/Test_C1.keylayout new file mode 100644 index 00000000000..9917dc30aa5 --- /dev/null +++ b/developer/src/kmc-convert/test/data/Test_C1.keylayout @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/Test_C2.keylayout b/developer/src/kmc-convert/test/data/Test_C2.keylayout new file mode 100644 index 00000000000..f13fe24eb38 --- /dev/null +++ b/developer/src/kmc-convert/test/data/Test_C2.keylayout @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/Test_C3.keylayout b/developer/src/kmc-convert/test/data/Test_C3.keylayout new file mode 100644 index 00000000000..fe72fc0ca89 --- /dev/null +++ b/developer/src/kmc-convert/test/data/Test_C3.keylayout @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/Test_DifferentAmountMapSelect_KeyMapERROR.keylayout b/developer/src/kmc-convert/test/data/Test_DifferentAmountMapSelect_KeyMapERROR.keylayout new file mode 100644 index 00000000000..a95f29fd14e --- /dev/null +++ b/developer/src/kmc-convert/test/data/Test_DifferentAmountMapSelect_KeyMapERROR.keylayout @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/Test_duplicate_missing_keycode.keylayout b/developer/src/kmc-convert/test/data/Test_duplicate_missing_keycode.keylayout new file mode 100644 index 00000000000..193c0495563 --- /dev/null +++ b/developer/src/kmc-convert/test/data/Test_duplicate_missing_keycode.keylayout @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/Test_modifier.keylayout b/developer/src/kmc-convert/test/data/Test_modifier.keylayout new file mode 100644 index 00000000000..44b2c841435 --- /dev/null +++ b/developer/src/kmc-convert/test/data/Test_modifier.keylayout @@ -0,0 +1,102 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/Test_modifierNoCaps.keylayout b/developer/src/kmc-convert/test/data/Test_modifierNoCaps.keylayout new file mode 100644 index 00000000000..92256b9329a --- /dev/null +++ b/developer/src/kmc-convert/test/data/Test_modifierNoCaps.keylayout @@ -0,0 +1,106 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/Test_nr_elements.keylayout b/developer/src/kmc-convert/test/data/Test_nr_elements.keylayout new file mode 100644 index 00000000000..4b770866cd6 --- /dev/null +++ b/developer/src/kmc-convert/test/data/Test_nr_elements.keylayout @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/Test_onlyOneKeymap.keylayout b/developer/src/kmc-convert/test/data/Test_onlyOneKeymap.keylayout new file mode 100644 index 00000000000..d9a873e15e4 --- /dev/null +++ b/developer/src/kmc-convert/test/data/Test_onlyOneKeymap.keylayout @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index de48dd1e22b..534a90477ec 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -10,10 +10,8 @@ import 'mocha'; import { assert } from 'chai'; import { compilerTestCallbacks, compilerTestOptions, makePathToFixture } from './helpers/index.js'; -import { idStateOutput_object, allArrayContents_object, KeylayoutToKmnConverter } from '../src/keylayout-to-kmn/keylayout-to-kmn-converter.js'; -import { KeylayoutFileReader } from '../src/keylayout-to-kmn/keylayout-file-reader.js'; -import { ConverterMessages } from '../src/converter-messages.js'; -import * as NodeAssert from 'node:assert'; +import { KeylayoutToKmnConverter } from '../src/keylayout-to-kmn/keylayout-to-kmn-converter.js'; + describe('KeylayoutToKmnConverter', function () { @@ -21,665 +19,75 @@ describe('KeylayoutToKmnConverter', function () { compilerTestCallbacks.clear(); }); - describe('run() ', function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - - it('run() should throw on null input file name and null output file name', async function () { - // note, could use 'chai as promised' library to make this more fluent: - const result = sut.run(null, null); - assert.isNotNull(result); - assert.equal(compilerTestCallbacks.messages.length, 1); - assert.deepEqual(compilerTestCallbacks.messages[0], ConverterMessages.Error_FileNotFound({ inputFilename: null })); - }); - - it('run() should throw on null input file name and empty output file name', async function () { - const result = sut.run(null, ''); - assert.isNotNull(result); - assert.equal(compilerTestCallbacks.messages.length, 1); - assert.deepEqual(compilerTestCallbacks.messages[0], ConverterMessages.Error_FileNotFound({ inputFilename: null })); - }); - - - it('run() should throw on null input file name and unknown output file name', async function () { - const result = sut.run(null, 'X'); - assert.isNotNull(result); - assert.equal(compilerTestCallbacks.messages.length, 1); - assert.deepEqual(compilerTestCallbacks.messages[0], ConverterMessages.Error_FileNotFound({ inputFilename: null })); - }); - - it('run() should throw on unavailable input file name and null output file name', async function () { - const inputFilename = makePathToFixture('../data/Unavailable.keylayout'); - const result = sut.run(inputFilename, null); - assert.isNotNull(result); - assert.equal(compilerTestCallbacks.messages.length, 1); - assert.deepEqual(compilerTestCallbacks.messages[0], ConverterMessages.Error_OutputFilenameIsRequired()); - }); - - it('run() should throw on and null output file name', async function () { - const inputFilename = makePathToFixture('../data/Test.keylayout'); - const result = sut.run(inputFilename, null); - assert.isNotNull(result); - assert.equal(compilerTestCallbacks.messages.length, 1); - assert.deepEqual(compilerTestCallbacks.messages[0], ConverterMessages.Error_OutputFilenameIsRequired()); - }); - - it('run() should return on correct input file name and empty output file name ', async function () { - const inputFilename = makePathToFixture('../data/Test.keylayout'); - await NodeAssert.doesNotReject(async () => sut.run(inputFilename, '')); - }); - - it('run() should return on correct input file name and null output file name', async function () { - const inputFilename = makePathToFixture('../data/Test.keylayout'); - await NodeAssert.doesNotReject(async () => sut.run(inputFilename, null)); - }); - - it('run() should return on correct input file name and given output file name ', async function () { - const inputFilename = makePathToFixture('../data/Test.keylayout'); - const outputFilename = makePathToFixture('../data/OutputName.kmn'); - await NodeAssert.doesNotReject(async () => sut.run(inputFilename, outputFilename)); - }); - - it('run() should throw on incorrect input file extention and output file extention', async function () { - const inputFilename = makePathToFixture('../data/Test_command.A'); - const outputFilename = makePathToFixture('../data/data/OutputXName.B'); - const result = sut.run(inputFilename, outputFilename); - assert.isNotNull(result); - assert.equal(compilerTestCallbacks.messages.length, 2); - assert.deepEqual(compilerTestCallbacks.messages[0], ConverterMessages.Error_FileNotFound({ inputFilename: inputFilename })); - }); - - it('run() return on correct input file extention and unsupperted output file extention', async function () { - const inputFilename = makePathToFixture('../data/Test.keylayout'); - const outputFilename = makePathToFixture('../data/OutputXName.B'); - await NodeAssert.doesNotReject(async () => sut.run(inputFilename, outputFilename)); - }); - }); - - describe('convert() ', function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); - const read = sut_r.read(inputFilename); - const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); - - // convert_object from unavailable file name - const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); - const read_unavailable = sut_r.read(inputFilename_unavailable); - const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); - - // convert_object from empty filename - const inputFilename_empty = makePathToFixture(''); - const read_empty = sut_r.read(inputFilename_empty); - const converted_empty = sut.convert_bound.convert(read_empty, inputFilename_empty); - - it('should return converted array on correct input', async function () { - assert.isTrue(converted.arrayOf_Rules.length !== 0); - }); - - it('should return empty on empty input', async function () { - assert.isTrue((converted_empty.keylayout_filename === '' - && converted_empty.arrayOf_Modifiers.length === 0 - && converted_empty.arrayOf_Rules.length === 0)); - }); - - it('should return empty on only name as input', async function () { - assert.isTrue((converted_unavailable.keylayout_filename === '' - && converted_unavailable.arrayOf_Modifiers.length === 0 - && converted_unavailable.arrayOf_Rules.length === 0)); - }); - - it('should return empty on only modifiers as input', async function () { - const converted_mod = sut.convert_bound.convert({ - keylayout_filename: '', - arrayOf_Modifiers: [['caps'], ['Shift'], ['command']], - arrayOf_Rules: [] - }, ''); - assert.isTrue((converted_mod.keylayout_filename === '' - && converted_mod.arrayOf_Modifiers.length === 0 - && converted_mod.arrayOf_Rules.length === 0)); - }); - - it('should return empty on only rules as input', async function () { - const converted_rule = sut.convert_bound.convert({ - keylayout_filename: '', - arrayOf_Modifiers: [], - arrayOf_Rules: [['C0', '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_A', 'A']] - }, ''); - assert.isTrue((converted_rule.keylayout_filename === '' - && converted_rule.arrayOf_Modifiers.length === 0 - && converted_rule.arrayOf_Rules.length === 0)); - }); - }); - - describe('create_kmn_modifier ', function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - - [ - ['shift', true, 'NCAPS SHIFT'], - ['leftshift', true, 'NCAPS SHIFT'], - ['rightShift', true, 'NCAPS SHIFT'], - ['shift rightShift?', true, 'NCAPS SHIFT'], - ['rightShift?', true, 'NCAPS'], - ['shift Shift?', true, 'NCAPS SHIFT'], - ['shift rightShift? caps? rightOption? rightControl', true, 'NCAPS SHIFT RCTRL'], - ['leftshift rightShift? caps? rightOption? rightControl', true, 'NCAPS SHIFT RCTRL'], - ['anycontrol', true, 'NCAPS CTRL'], - ['shift?', true, 'NCAPS'], - ['?', true, 'NCAPS'], - ['?', false, ''], - ['caps', true, 'CAPS'], - ['', true, 'NCAPS'], - [' ', false, ''], - ['wrongModifierName', false, 'wrongModifierName'], - ['shift', false, 'SHIFT'], - ['shift command', true, 'NCAPS SHIFT command'], - ['rshift', true, 'NCAPS SHIFT'], - ['rshift', false, 'SHIFT'], - ['rightshift', true, 'NCAPS SHIFT'], - ['riGhtsHift', true, 'NCAPS SHIFT'], - ['LEFTCONTROL', true, 'NCAPS LCTRL'], - ['RCONTROL', true, 'NCAPS RCTRL'], - ['leftoption', true, 'NCAPS LALT'], - ['loption', true, 'NCAPS LALT'], - ].forEach(function (values) { - it(('should convert "' + values[0] + '"').padEnd(36, " ") + 'to "' + values[2] + '"', async function () { - const result = sut.create_kmn_modifier(values[0] as string, values[1] as boolean); - assert.equal(result, values[2]); - }); - }); - }); - - describe('isAcceptableKeymanModifier ', function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - - [ - ['NCAPS', true], - ['NxCAPS', false], - ['SHIFT', true], - ['ALT', true], - ['RALT', true], - ['LALT', true], - ['CTRL', true], - ['LCTRL', true], - ['RCTRL', true], - ['LCTRL CAPS', true], - ['LCTRL X', false], - ['', true], - [null, false], - ].forEach(function (values) { - it(("isAcceptableKeymanModifier(" + values[0] + ")").padEnd(38, " ") + ' should return ' + values[1], async function () { - const result = sut.isAcceptableKeymanModifier(values[0] as string); - assert.equal(result, values[1]); - }); - }); - }); - - describe('map_UkeleleKC_To_VK ', function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - [ - [0x00, 'K_A'], - [0x31, 'K_SPACE'], - [0x18, 'K_EQUAL'], - [0x10, 'K_Y'], - [0x18, 'K_EQUAL'], - [0x21, 'K_LBRKT'], - [0x999, ''], - [-1, ''], - [null, ''], - [undefined, ''], - [, ''], - ].forEach(function (values) { - it(("map_UkeleleKC_To_VK(" + values[0] + ")").padEnd(26, " ") + "should return " + "'" + values[1] + "'", async function () { - const result = sut.map_UkeleleKC_To_VK(values[0] as number); - assert.equal(result, values[1]); - }); - }); - }); - - describe('checkIfCapsIsUsed ', function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - - [ - [[['caps', 'xxx'], ['yyy']], true], - [[['Caps', 'xxx'], ['yyy']], true], - [[['Caps?', 'xxx'], ['yyy']], true], - [[['caps?', 'xxx'], ['yyy']], true], - [[['CaPs', 'xxx'], ['yyy']], true], - [[['zzz', 'xxx'], ['yyy']], false], - [[['', ''], ['']], false], - [[null], false], - ].forEach(function (values) { - it(("checkIfCapsIsUsed([['caps', 'xxx'], ['yyy']])").padEnd(45, " ") + "should return " + "'" + values[1] + "'", async function () { - const result = sut.checkIfCapsIsUsed(values[0] as string[][]) === values[1]; - assert.isTrue(result); - }); - }); - }); - - describe('get_Modifier_array__From__KeyModifier_array ', function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); - const read = sut_r.read(inputFilename); - const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); - [ - [[{ key: '0', behaviour: 0 }], [['', 'shift? caps? ']]], - [[{ key: '0', behaviour: 2 }], [['shift? leftShift caps? ', 'anyShift caps?', 'shift leftShift caps ', 'shift? rightShift caps? ']]], - [[{ key: '0', behaviour: 999 }], [null]], - [[{ key: '999', behaviour: null }], [null]], - [[{ key: '0', behaviour: -999 }], [null]], - [[{ key: '0', behaviour: null }], [null]], - [[], []], - - ].forEach(function (values) { - it((values[1] !== null) ? - ("get_Modifier_array__From__KeyModifier_array('" + JSON.stringify(values[0]) + "')").padEnd(68, " ") + " should return '" + /*values[1] +*/ JSON.stringify(values[1]) + "'" : - ("get_Modifier_array__From__KeyModifier_array('" + JSON.stringify(values[0]) + "')").padEnd(68, " ") + " should return '" + "null" + "'", async function () { - const result = sut.get_Modifier_array__From__KeyModifier_array(converted.arrayOf_Modifiers, values[0] as allArrayContents_object[]); - assert.deepStrictEqual(JSON.stringify(result), JSON.stringify(values[1])); - }); - }); - }); - - describe('get_KeyModifier_array__From__ActionID ', function () { + // todo remove + describe('RunAllFiles', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); - const read = sut_r.read(inputFilename); [ - ['A_16', [{ "key": "32", "behaviour": "5" }]], - ['A_19', [{ "key": "45", "behaviour": "5" }]], - ['A_18', [{ "key": "24", "behaviour": "0" }, { "key": "24", "behaviour": "5" }]], - ['unknown', []], - [undefined, []], - [null, []], - [' ', []], - ['', []], - ].forEach(function (values) { - let outstring = '[ '; - for (let i = 0; i < values[1].length; i++) { - outstring = outstring + "[ " + JSON.stringify(values[1][i]) + "], "; - } - it(("get_KeyModifier_array__From__ActionID('" + values[0] + "')").padEnd(57, " ") + ' should return ' + outstring.substring(0, outstring.lastIndexOf(']') + 2) + " ]", async function () { - const result = sut.get_KeyModifier_array__From__ActionID(read, String(values[0])); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); - }); - }); - }); - - describe('get_ActionID__From__ActionNext ', function () { + [makePathToFixture('../data/Italian.keylayout')], + [makePathToFixture('../data/Italian_command.keylayout')], + [makePathToFixture('../data/Swiss_French.keylayout')], + [makePathToFixture('../data/Spanish.keylayout')], + [makePathToFixture('../data/Swiss_German.keylayout')], + [makePathToFixture('../data/US.keylayout')], + [makePathToFixture('../data/Polish.keylayout')], + [makePathToFixture('../data/French.keylayout')], + [makePathToFixture('../data/Latin_American.keylayout')], + // [makePathToFixture('../data/German_complete.keylayout')], + [makePathToFixture('../data/German_complete_reduced.keylayout')], + //[makePathToFixture('../data/German_Standard.keylayout')], + ].forEach(function (files_) { + sut.run(files_[0]); + assert.isTrue(true); + }); + }); + + describe('RunTestFiles resulting in errors ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); - const read = sut_r.read(inputFilename); - [ - ['none', ''], - ['0', ''], - ['A_18', ''], - ['1', 'A_16'], - ['2', 'A_8'], - ['3', 'A_17'], - ['', ''], - [' ', ''], - ['99', ''], - [null, ''], - [undefined, ''], - ['unknown', ''], - ].forEach(function (values) { - it(("get_ActionID__From__ActionNext('" + values[0] + "')").padEnd(49, " ") + ' should return ' + "'" + values[1] + "'", async function () { - const result = sut.get_ActionID__From__ActionNext(read, String(values[0])); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + ['../data/Test_DifferentAmountMapSelect_KeyMapERROR.keylayout', 5292040], + ['../data/Test_DifferentAmountMapSelect_KeyMapERROR_1.keylayout', 5292040], + ['../data/Test_MissingkeyMapERROR.keylayout', 5246977], + ['../data/Test_MissingkeyERROR.keylayout', 5246977], + ['../data/Test_MissingLayoutsERROR.keylayout', 5292036], + ['../data/Test_MissingmodifierMapERROR.keylayout', 5292036], + ['../data/Test_MissingkeyMapSetERROR.keylayout', 5292036], + ['../data/Test_MissingActionsERROR.keylayout', 5292036], + ['../data/Test_MissingTerminatorsERROR.keylayout', 5292036], + ['../data/Test_MissingAllERROR.keylayout', 5292036], + ].forEach(function (files_) { + it(files_ + " should give error ", async function () { + sut.run(makePathToFixture(files_[0] as string)); + assert.isTrue(compilerTestCallbacks.messages.length > 0); + assert.isTrue(String(compilerTestCallbacks.messages[0].code) === String(files_[1])); }); }); }); - describe('get_ActionIndex__From__ActionId ', function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); - const read = sut_r.read(inputFilename); - [ - ['none', 0], - ['A_16', 8], - ['A_18', 10], - ['A_19', 11], - ['0', 0], - ['', 0], - [' ', 0], - [null, 0], - [undefined, 0], - ['unknown', 0], - ].forEach(function (values) { - it(("get_ActionIndex__From__ActionId('" + values[0] + "')").padEnd(50, " ") + ' should return ' + values[1], async function () { - const result = sut.get_ActionIndex__From__ActionId(read, String(values[0])); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); - }); - }); - }); - describe('get_Output__From__ActionId_None ', function () { + describe('RunSpecialTestFiles', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); - const read = sut_r.read(inputFilename); - [ - ['A_14', 'u'], - ['', ''], - [' ', ''], - ['A_18', undefined], - ['unknown', ''], - ].forEach(function (values) { - it( - ("get_Output__From__ActionId_None('" + values[0] + "')").padEnd(56, " ") + ' should return ' + "'" + values[1] + "'", async function () { - const result = sut.get_Output__From__ActionId_None(read, String(values[0])); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); - }); - }); - - [[null, ''], - [undefined, ''], - [99, ''], - ].forEach(function (values) { - it(("get_Output__From__ActionId_None('" + values[0] + "')").padEnd(56, " ") + ' should return ' + values[1], async function () { - const result = sut.get_Output__From__ActionId_None(read, String(values[0])); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); - }); - }); - }); - describe('get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array ', function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); - const read = sut_r.read(inputFilename); - - const b1_keycode_arr: allArrayContents_object[] = [ - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '0', outchar: 'ˆ' }, - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '1', outchar: 'ˆ' }, - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '2', outchar: 'ˆ' }, - { keyCode: '6', key: 'K_Z', actionId: 'A_0', behaviour: '4', outchar: 'ˆ' }, - { keyCode: '25', key: 'K_9', actionId: 'A_0', behaviour: '4', outchar: 'ˆ' }, - { keyCode: '43', key: 'K_COMMA', actionId: 'A_0', behaviour: '4', outchar: 'ˆ' }, - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '3', outchar: 'ˆ' }, - { keyCode: '0', key: 'K_A', actionId: 'A_1', behaviour: '2', outchar: 'Â' }, - { keyCode: '0', key: 'K_A', actionId: 'A_1', behaviour: '1', outchar: 'Â' }, - { keyCode: '14', key: 'K_E', actionId: 'A_10', behaviour: '0', outchar: 'ê' }, - { keyCode: '34', key: 'K_I', actionId: 'A_11', behaviour: '0', outchar: 'î' }, - { keyCode: '31', key: 'K_O', actionId: 'A_13', behaviour: '0', outchar: 'ô' }, - { keyCode: '32', key: 'K_U', actionId: 'A_14', behaviour: '0', outchar: 'û' }, - { keyCode: '14', key: 'K_E', actionId: 'A_2', behaviour: '2', outchar: 'Ê' }, - { keyCode: '14', key: 'K_E', actionId: 'A_2', behaviour: '1', outchar: 'Ê' }, - { keyCode: '34', key: 'K_I', actionId: 'A_3', behaviour: '2', outchar: 'Î' }, - { keyCode: '34', key: 'K_I', actionId: 'A_3', behaviour: '1', outchar: 'Î' }, - { keyCode: '31', key: 'K_O', actionId: 'A_5', behaviour: '2', outchar: 'Ô' }, - { keyCode: '31', key: 'K_O', actionId: 'A_5', behaviour: '1', outchar: 'Ô' }, - { keyCode: '32', key: 'K_U', actionId: 'A_6', behaviour: '2', outchar: 'Û' }, - { keyCode: '32', key: 'K_U', actionId: 'A_6', behaviour: '1', outchar: 'Û' }, - { keyCode: '0', key: 'K_A', actionId: 'A_9', behaviour: '0', outchar: 'â' } - - ]; - const b1_modifierKey_arr: allArrayContents_object[] = [ - { actionId: 'A_0', key: 'K_SPACE', behaviour: '0', modifier: 'NCAPS', outchar: 'ˆ' }, - { actionId: 'A_0', key: 'K_SPACE', behaviour: '1', modifier: 'CAPS', outchar: 'ˆ' }, - { actionId: 'A_0', key: 'K_SPACE', behaviour: '2', modifier: 'NCAPS SHIFT', outchar: 'ˆ' }, - { actionId: 'A_0', key: 'K_SPACE', behaviour: '2', modifier: 'SHIFT CAPS', outchar: 'ˆ' }, - { actionId: 'A_0', key: 'K_Z', behaviour: '4', modifier: 'NCAPS SHIFT RALT', outchar: 'ˆ' }, - { actionId: 'A_0', key: 'K_9', behaviour: '4', modifier: 'NCAPS SHIFT RALT', outchar: 'ˆ' }, - { actionId: 'A_0', key: 'K_COMMA', behaviour: '4', modifier: 'NCAPS SHIFT RALT', outchar: 'ˆ' }, - { actionId: 'A_0', key: 'K_SPACE', behaviour: '3', modifier: 'NCAPS RALT CTRL', outchar: 'ˆ' }, - { actionId: 'A_0', key: 'K_SPACE', behaviour: '3', modifier: 'NCAPS CTRL', outchar: 'ˆ' }, - { actionId: 'A_1', key: 'K_A', behaviour: '2', modifier: 'NCAPS SHIFT', outchar: 'Â' }, - { actionId: 'A_1', key: 'K_A', behaviour: '2', modifier: 'SHIFT CAPS', outchar: 'Â' }, - { actionId: 'A_1', key: 'K_A', behaviour: '1', modifier: 'CAPS', outchar: 'Â' }, - { actionId: 'A_10', key: 'K_E', behaviour: '0', modifier: 'NCAPS', outchar: 'ê' }, - { actionId: 'A_11', key: 'K_I', behaviour: '0', modifier: 'NCAPS', outchar: 'î' }, - { actionId: 'A_13', key: 'K_O', behaviour: '0', modifier: 'NCAPS', outchar: 'ô' }, - { actionId: 'A_14', key: 'K_U', behaviour: '0', modifier: 'NCAPS', outchar: 'û' }, - { actionId: 'A_2', key: 'K_E', behaviour: '2', modifier: 'NCAPS SHIFT', outchar: 'Ê' }, - { actionId: 'A_2', key: 'K_E', behaviour: '2', modifier: 'SHIFT CAPS', outchar: 'Ê' }, - { actionId: 'A_2', key: 'K_E', behaviour: '1', modifier: 'CAPS', outchar: 'Ê' }, - { actionId: 'A_3', key: 'K_I', behaviour: '2', modifier: 'NCAPS SHIFT', outchar: 'Î' }, - { actionId: 'A_3', key: 'K_I', behaviour: '2', modifier: 'SHIFT CAPS', outchar: 'Î' }, - { actionId: 'A_3', key: 'K_I', behaviour: '1', modifier: 'CAPS', outchar: 'Î' }, - { actionId: 'A_5', key: 'K_O', behaviour: '2', modifier: 'NCAPS SHIFT', outchar: 'Ô' }, - { actionId: 'A_5', key: 'K_O', behaviour: '2', modifier: 'SHIFT CAPS', outchar: 'Ô' }, - { actionId: 'A_5', key: 'K_O', behaviour: '1', modifier: 'CAPS', outchar: 'Ô' }, - { actionId: 'A_6', key: 'K_U', behaviour: '2', modifier: 'NCAPS SHIFT', outchar: 'Û' }, - { actionId: 'A_6', key: 'K_U', behaviour: '2', modifier: 'SHIFT CAPS', outchar: 'Û' }, - { actionId: 'A_6', key: 'K_U', behaviour: '1', modifier: 'CAPS', outchar: 'Û' }, - { actionId: 'A_9', key: 'K_A', behaviour: '0', modifier: 'NCAPS', outchar: 'â' } - ]; - - [[b1_keycode_arr, b1_modifierKey_arr], - [[{ keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '0', modifier: '0', outchar: 'ˆ' }], [{ actionId: 'A_0', key: 'K_SPACE', behaviour: '0', modifier: 'NCAPS', outchar: 'ˆ' }]], - [[{ keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '0', modifier: '', outchar: 'ˆ' }], [{ actionId: 'A_0', key: 'K_SPACE', behaviour: '0', modifier: 'NCAPS', outchar: 'ˆ' }]], - [[{ keyCode: '49', key: 'K_SPACE', actionId: '', behaviour: '0', modifier: '0', outchar: 'ˆ' }], [{ actionId: '', key: 'K_SPACE', behaviour: '0', modifier: 'NCAPS', outchar: 'ˆ' }]], - [[{ keyCode: '49', key: '', actionId: 'A_0', behaviour: '0', modifier: '0', outchar: 'ˆ' }], [{ actionId: 'A_0', key: '', behaviour: '0', modifier: 'NCAPS', outchar: 'ˆ' }]], - [[{ keyCode: '', key: 'K_SPACE', actionId: 'A_0', behaviour: '0', modifier: '0', outchar: 'ˆ' }], [{ actionId: 'A_0', key: 'K_SPACE', behaviour: '0', modifier: 'NCAPS', outchar: 'ˆ' }]], - [[{ keyCode: '', key: '', actionId: '', behaviour: '0', modifier: '', outchar: '' }], [{ actionId: '', key: '', behaviour: '0', modifier: 'NCAPS', outchar: '' }]], - ].forEach(function (values) { - const isCaps_used = true; - const string_in = "get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(['" + "', '" + "', '" + values[0][0].keyCode + "', '" + values[0][0].key + "', '" + values[0][0].actionId + "', '" + values[0][0].modifier + "', '" + values[0][0].outchar + "'])"; - const string_out = "['" + "', '" + "', '" + values[1][0].key + "', '" + values[1][0].actionId + "', '" + "', '" + values[1][0].modifier + "', '" + values[1][0].outchar + "']"; - - it((JSON.stringify(values[1]).length > 60) ? 'an array of objects should return an array of objects' : - string_in.padEnd(74, " ") + ' should return ' + string_out, async function () { - const result = sut.get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(read, values[0], isCaps_used); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); - }); - }); - - [[{ keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '0', modifier: '0', outchar: 'ˆ' }, { actionId: 'A_0', key: 'K_SPACE', behaviour: '0', modifier: '', outchar: 'ˆ' }], - [{ keyCode: '', key: 'K_SPACE', actionId: 'A_0', behaviour: '0', modifier: '0', outchar: 'ˆ' }, { actionId: 'A_0', key: 'K_SPACE', behaviour: '0', modifier: '', outchar: 'ˆ' }], - [{ keyCode: '', key: '', actionId: '', behaviour: '0', modifier: '', outchar: '' }, { actionId: '', key: '', behaviour: '0', modifier: '', outchar: '' }], - ].forEach(function (values) { - const isCaps_used = false; - const string_in = "get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array([ '" + values[0].keyCode + "', '" + values[0].key + "', '" + values[0].actionId + "', '" + values[0].modifier + "', '" + values[0].outchar + "'])"; - const string_out = "['" + values[1].actionId + "', '" + "', '" + values[1].modifier + "', '" + values[1].key + "', '" + values[1].outchar + "']"; - - it(string_in.padEnd(74, " ") + ' should return ' + string_out, async function () { - const result = sut.get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(read, [values[0]], isCaps_used); - assert.equal(JSON.stringify(result), JSON.stringify([values[1]])); - }); - }); - - [[[], []], - [undefined, []], - [null, []], - ].forEach(function (values) { - const isCaps = true; - it(("get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array([" + values[0] + "])").padEnd(74, " ") + ' should return ' + "[" + values[1] + "]", async function () { - const result = sut.get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(read, values[0], isCaps); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + [makePathToFixture('../data/Test_C0.keylayout')], + [makePathToFixture('../data/Test_C1.keylayout')], + [makePathToFixture('../data/Test_C2.keylayout')], + [makePathToFixture('../data/Test_C2_several.keylayout')], + [makePathToFixture('../data/Test_C3.keylayout')], + [makePathToFixture('../data/Test_C3_several.keylayout')], + [makePathToFixture('../data/Test_C0_C1_C2_C3.keylayout')], + + [makePathToFixture('../data/Test_duplicate_missing_keycode.keylayout')], + [makePathToFixture('../data/Test_characters.keylayout')], + [makePathToFixture('../data/Test_modifier.keylayout')], + [makePathToFixture('../data/Test_modifierNoCaps.keylayout')], + [makePathToFixture('../data/Test_onlyOneKeymap.keylayout')], + [makePathToFixture('../data/Test_nr_elements.keylayout')], + [makePathToFixture('../data/Test.keylayout')], + ].forEach(function (files_) { + it(files_ + " should give no errors ", async function () { + sut.run(files_[0]); + assert.isTrue(compilerTestCallbacks.messages.length === 0); }); }); }); - describe('get_ActionStateOutput_array__From__ActionState ', function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); - const read = sut_r.read(inputFilename); - - [['1', [ - { "id": "A_0", "state": "1", "output": "ˆ" }, - { "id": "A_1", "state": "1", "output": "Â" }, - { "id": "A_10", "state": "1", "output": "ê" }, - { "id": "A_11", "state": "1", "output": "î" }, - { "id": "A_13", "state": "1", "output": "ô" }, - { "id": "A_14", "state": "1", "output": "û" }, - { "id": "A_2", "state": "1", "output": "Ê" }, - { "id": "A_3", "state": "1", "output": "Î" }, - { "id": "A_5", "state": "1", "output": "Ô" }, - { "id": "A_6", "state": "1", "output": "Û" }, - { "id": "A_9", "state": "1", "output": "â" } - ],], - ['2', [ - { "id": "A_0", "state": "2", "output": "`" }, - { "id": "A_1", "state": "2", "output": "À" }, - { "id": "A_10", "state": "2", "output": "è" }, - { "id": "A_11", "state": "2", "output": "ì" }, - { "id": "A_13", "state": "2", "output": "ò" }, - { "id": "A_14", "state": "2", "output": "ù" }, - { "id": "A_2", "state": "2", "output": "È" }, - { "id": "A_3", "state": "2", "output": "Ì" }, - { "id": "A_5", "state": "2", "output": "Ò" }, - { "id": "A_6", "state": "2", "output": "Ù" }, - { "id": "A_9", "state": "2", "output": "à" } - ],], - ['789', [],], - ['', [],], - [' ', [],], - [123, [],], - [null, [],], - [undefined, [],], - ].forEach(function (values) { - it((JSON.stringify(values[1]).length > 30) ? - ("get_ActionStateOutput_array__From__ActionState('" + values[0] + "')").padEnd(60, " ") + ' should return an array of objects' : - ("get_ActionStateOutput_array__From__ActionState('" + values[0] + "')").padEnd(60, " ") + ' should return ' + "'" + JSON.stringify(values[1]) + "'", async function () { - const result = sut.get_ActionStateOutput_array__From__ActionState(read, String(values[0])); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); - }); - }); - }); - describe('get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput ', function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); - const read = sut_r.read(inputFilename); - const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); - - [ - ['A_1', 'A', true, - [{ "outchar": "A", "actionId": "A_1", "behaviour": "1", "key": "K_A", "modifier": "CAPS" }, - { "outchar": "A", "actionId": "A_1", "behaviour": "2", "key": "K_A", "modifier": "NCAPS SHIFT" }, - { "outchar": "A", "actionId": "A_1", "behaviour": "2", "key": "K_A", "modifier": "SHIFT CAPS" }] - ], - ['A_1', 'A', false, - [{ "outchar": "A", "actionId": "A_1", "behaviour": "1", "key": "K_A", "modifier": "CAPS" }, - { "outchar": "A", "actionId": "A_1", "behaviour": "2", "key": "K_A", "modifier": "SHIFT" }, - { "outchar": "A", "actionId": "A_1", "behaviour": "2", "key": "K_A", "modifier": "SHIFT CAPS" }] - ], - ['A_9', 'a', true, [{ "outchar": "a", "actionId": "A_9", "behaviour": "0", "key": "K_A", "modifier": "NCAPS" }]], - ['A_9', 'a', false, [{ "outchar": "a", "actionId": "A_9", "behaviour": "0", "key": "K_A", "modifier": "" }]], - ['A_9', 'a', , [{ "outchar": "a", "actionId": "A_9", "behaviour": "0", "key": "K_A", "modifier": "" }]], - ['A_9', '', true, [{ "outchar": "", "actionId": "A_9", "behaviour": "0", "key": "K_A", "modifier": "NCAPS" }]], - ['A_9', '', false, [{ "outchar": "", "actionId": "A_9", "behaviour": "0", "key": "K_A", "modifier": "" }]], - ['', 'a', true, []], - ['', 'a', false, []], - ['', '', , []], - - ].forEach(function (values) { - it((JSON.stringify(values[3]).length > 35) ? - ("get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput('" + values[0] + "', '" + values[1] + "', " + values[2] + ")").padEnd(67, " ") + ' should return an array of objects' : - ("get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput('" + values[0] + "', '" + values[1] + "', " + values[2] + ")").padEnd(67, " ") + ' should return ' + "'" + JSON.stringify(values[3]) + "'", async function () { - const result = sut.get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput(read, converted.arrayOf_Modifiers, String(values[0]), String(values[1]), Boolean(values[2])); - assert.equal(JSON.stringify(result), JSON.stringify(values[3])); - }); - }); - }); - describe('get_KeyActionOutput_array__From__ActionStateOutput_array ', function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); - const read = sut_r.read(inputFilename); - - const b6_actionId_arr: idStateOutput_object[] = [ - { "id": "A_0", "state": "1", "output": "ˆ" }, - { "id": "A_1", "state": "1", "output": "Â" }, - { "id": "A_10", "state": "1", "output": "ê" }, - { "id": "A_11", "state": "1", "output": "î" }, - { "id": "A_13", "state": "1", "output": "ô" }, - { "id": "A_14", "state": "1", "output": "û" }, - { "id": "A_2", "state": "1", "output": "Ê" }, - { "id": "A_3", "state": "1", "output": "Î" }, - { "id": "A_5", "state": "1", "output": "Ô" }, - { "id": "A_6", "state": "1", "output": "Û" }, - { "id": "A_9", "state": "1", "output": "â" } - ]; - const b1_keycode_arr: allArrayContents_object[] = [ - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '0', outchar: 'ˆ' }, - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '1', outchar: 'ˆ' }, - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '2', outchar: 'ˆ' }, - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '3', outchar: 'ˆ' }, - { keyCode: '6', key: 'K_Z', actionId: 'A_0', behaviour: '4', outchar: 'ˆ' }, - { keyCode: '25', key: 'K_9', actionId: 'A_0', behaviour: '4', outchar: 'ˆ' }, - { keyCode: '43', key: 'K_COMMA', actionId: 'A_0', behaviour: '4', outchar: 'ˆ' }, - { keyCode: '0', key: 'K_A', actionId: 'A_1', behaviour: '1', outchar: 'Â' }, - { keyCode: '0', key: 'K_A', actionId: 'A_1', behaviour: '2', outchar: 'Â' }, - { keyCode: '14', key: 'K_E', actionId: 'A_10', behaviour: '0', outchar: 'ê' }, - { keyCode: '34', key: 'K_I', actionId: 'A_11', behaviour: '0', outchar: 'î' }, - { keyCode: '31', key: 'K_O', actionId: 'A_13', behaviour: '0', outchar: 'ô' }, - { keyCode: '32', key: 'K_U', actionId: 'A_14', behaviour: '0', outchar: 'û' }, - { keyCode: '14', key: 'K_E', actionId: 'A_2', behaviour: '1', outchar: 'Ê' }, - { keyCode: '14', key: 'K_E', actionId: 'A_2', behaviour: '2', outchar: 'Ê' }, - { keyCode: '34', key: 'K_I', actionId: 'A_3', behaviour: '1', outchar: 'Î' }, - { keyCode: '34', key: 'K_I', actionId: 'A_3', behaviour: '2', outchar: 'Î' }, - { keyCode: '31', key: 'K_O', actionId: 'A_5', behaviour: '1', outchar: 'Ô' }, - { keyCode: '31', key: 'K_O', actionId: 'A_5', behaviour: '2', outchar: 'Ô' }, - { keyCode: '32', key: 'K_U', actionId: 'A_6', behaviour: '1', outchar: 'Û' }, - { keyCode: '32', key: 'K_U', actionId: 'A_6', behaviour: '2', outchar: 'Û' }, - { keyCode: '0', key: 'K_A', actionId: 'A_9', behaviour: '0', outchar: 'â' } - ]; - - [[b6_actionId_arr, b1_keycode_arr], - ].forEach(function (values) { - it(("get_KeyActionOutput_array__From__ActionStateOutput_array([['" + JSON.stringify(values[0]) + "'],..])").padEnd(73, " ") + '1 should return an array of objects', async function () { - const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0] as idStateOutput_object[]); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); - }); - }); - - const oneEntryResult = [ - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '0', outchar: 'ˆ' }, - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '1', outchar: 'ˆ' }, - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '2', outchar: 'ˆ' }, - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '3', outchar: 'ˆ' }, - { keyCode: '6', key: 'K_Z', actionId: 'A_0', behaviour: '4', outchar: 'ˆ' }, - { keyCode: '25', key: 'K_9', actionId: 'A_0', behaviour: '4', outchar: 'ˆ' }, - { keyCode: '43', key: 'K_COMMA', actionId: 'A_0', behaviour: '4', outchar: 'ˆ' } - ]; - - const oneEntryResultNoOutput = [ - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '0', outchar: '' }, - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '1', outchar: '' }, - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '2', outchar: '' }, - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '3', outchar: '' }, - { keyCode: '6', key: 'K_Z', actionId: 'A_0', behaviour: '4', outchar: '' }, - { keyCode: '25', key: 'K_9', actionId: 'A_0', behaviour: '4', outchar: '' }, - { keyCode: '43', key: 'K_COMMA', actionId: 'A_0', behaviour: '4', outchar: '' }, - ]; - - [[[{ "id": "A_0", "state": "1", "output": "ˆ" }], oneEntryResult], - [[{ "id": "A_0", "state": "1", "output": "" }], oneEntryResultNoOutput], - [[{ "id": "A_0", "state": "", "output": "ˆ" }], oneEntryResult], - ].forEach(function (values) { - it(("get_KeyActionOutput_array__From__ActionStateOutput_array(['" + JSON.stringify(values[0]) + "'])").padEnd(73, " ") + '2 should return an array of objects', async function () { - const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0] as idStateOutput_object[]); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); - }); - }); - - [[[{ "id": "", "state": "1", "output": "ˆ" }], []], - [[{ "id": "", "state": "", "output": "" }], []], - [[{ "id": " ", "state": " ", "output": "" }], []], - - ].forEach(function (values) { - it(("get_KeyActionOutput_array__From__ActionStateOutput_array(" + JSON.stringify(values[0]) + ")").padEnd(73, " ") + ' should return ' + "'[" + JSON.stringify(values[1]) + "]'", async function () { - const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0] as idStateOutput_object[]); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); - }); - }); - - [[, []], - [undefined, []], - [null, []], - ].forEach(function (values) { - it(("get_KeyActionOutput_array__From__ActionStateOutput_array(" + JSON.stringify(values[0]) + ")").padEnd(73, " ") + ' should return ' + "'[" + JSON.stringify(values[1]) + "]'", async function () { - const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0] as idStateOutput_object[]); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); - }); - }); - }); }); From 1997a71e1c56f078ac70480065740808a16e7292 Mon Sep 17 00:00:00 2001 From: Sabine Date: Sat, 9 Aug 2025 16:18:24 +0200 Subject: [PATCH 158/251] feat(developer): add and edit tests --- .../src/kmc-convert/test/data/Test.keylayout | 5 +- .../kmc-convert/test/data/Test_C0.keylayout | 12 +- .../test/data/Test_C0_C1_C2_C3.keylayout | 76 +-- .../kmc-convert/test/data/Test_C1.keylayout | 10 +- .../kmc-convert/test/data/Test_C2.keylayout | 10 +- .../test/data/Test_C2_several.keylayout | 73 +++ .../kmc-convert/test/data/Test_C3.keylayout | 18 +- .../test/data/Test_C3_several.keylayout | 99 +++ ...erentAmountMapSelect_KeyMapERROR.keylayout | 20 +- ...ntAmountOfMapSelectInKeyMapERROR.keylayout | 66 ++ ...AmountOfMapSelectInKeyMapERROR_1.keylayout | 78 +++ .../test/data/Test_additionalTags.keylayout | 601 ------------------ .../test/data/Test_ambiguous_keys.keylayout | 57 ++ .../test/data/Test_characters.keylayout | 51 ++ ...ifferentAmountOfKeysInBehaviours.keylayout | 45 ++ .../test/data/Test_duplicate_keys.keylayout | 61 ++ .../Test_duplicate_missing_keycode.keylayout | 6 +- .../Test_duplicate_missing_keys.keylayout | 59 ++ .../test/data/Test_maxKeyCode.keylayout | 37 ++ .../test/data/Test_messages.keylayout | 80 +++ .../test/data/Test_missingTags.keylayout | 595 ----------------- .../test/data/Test_modifier.keylayout | 15 +- .../test/data/Test_modifierNoCaps.keylayout | 22 +- .../test/data/Test_noActionWhen.keylayout | 598 ----------------- .../test/data/Test_nr_elements.keylayout | 6 +- .../test/data/Test_onlyOneKeymap.keylayout | 19 +- .../test/data/Test_unknownTags.keylayout | 598 ----------------- 27 files changed, 787 insertions(+), 2530 deletions(-) create mode 100644 developer/src/kmc-convert/test/data/Test_C2_several.keylayout create mode 100644 developer/src/kmc-convert/test/data/Test_C3_several.keylayout create mode 100644 developer/src/kmc-convert/test/data/Test_DifferentAmountOfMapSelectInKeyMapERROR.keylayout create mode 100644 developer/src/kmc-convert/test/data/Test_DifferentAmountOfMapSelectInKeyMapERROR_1.keylayout delete mode 100644 developer/src/kmc-convert/test/data/Test_additionalTags.keylayout create mode 100644 developer/src/kmc-convert/test/data/Test_ambiguous_keys.keylayout create mode 100644 developer/src/kmc-convert/test/data/Test_characters.keylayout create mode 100644 developer/src/kmc-convert/test/data/Test_differentAmountOfKeysInBehaviours.keylayout create mode 100644 developer/src/kmc-convert/test/data/Test_duplicate_keys.keylayout create mode 100644 developer/src/kmc-convert/test/data/Test_duplicate_missing_keys.keylayout create mode 100644 developer/src/kmc-convert/test/data/Test_maxKeyCode.keylayout create mode 100644 developer/src/kmc-convert/test/data/Test_messages.keylayout delete mode 100644 developer/src/kmc-convert/test/data/Test_missingTags.keylayout delete mode 100644 developer/src/kmc-convert/test/data/Test_noActionWhen.keylayout delete mode 100644 developer/src/kmc-convert/test/data/Test_unknownTags.keylayout diff --git a/developer/src/kmc-convert/test/data/Test.keylayout b/developer/src/kmc-convert/test/data/Test.keylayout index 2c903b418bf..76fd91b4db6 100644 --- a/developer/src/kmc-convert/test/data/Test.keylayout +++ b/developer/src/kmc-convert/test/data/Test.keylayout @@ -5,6 +5,7 @@ Data generated April 15 2025 Generated by S. Schmitt + a test with lots of shiftstates, behaviours and C0, C1, C2 C3 rules --> @@ -38,11 +39,11 @@ - + - + diff --git a/developer/src/kmc-convert/test/data/Test_C0.keylayout b/developer/src/kmc-convert/test/data/Test_C0.keylayout index e715d09b95c..d8c49ea62ae 100644 --- a/developer/src/kmc-convert/test/data/Test_C0.keylayout +++ b/developer/src/kmc-convert/test/data/Test_C0.keylayout @@ -5,6 +5,8 @@ Data generated August 1st 2025 Generated by S. Schmitt + + tests several C0 rules --> @@ -17,15 +19,17 @@ - - + + + + - - + + diff --git a/developer/src/kmc-convert/test/data/Test_C0_C1_C2_C3.keylayout b/developer/src/kmc-convert/test/data/Test_C0_C1_C2_C3.keylayout index 3525fcb7ed0..f5e7ab06468 100644 --- a/developer/src/kmc-convert/test/data/Test_C0_C1_C2_C3.keylayout +++ b/developer/src/kmc-convert/test/data/Test_C0_C1_C2_C3.keylayout @@ -5,86 +5,41 @@ Data generated August 1st 2025 Generated by S. Schmitt + + tests C0, C1, C2, C3 rules --> - + - + - - - - - - - - - - - - - + - - - - + - - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + - - + @@ -95,7 +50,6 @@ - diff --git a/developer/src/kmc-convert/test/data/Test_C1.keylayout b/developer/src/kmc-convert/test/data/Test_C1.keylayout index 9917dc30aa5..e785e58ca18 100644 --- a/developer/src/kmc-convert/test/data/Test_C1.keylayout +++ b/developer/src/kmc-convert/test/data/Test_C1.keylayout @@ -4,7 +4,9 @@ Data generated August 1st 2025 + Generated by S. Schmitt + tests several C1 rules --> @@ -17,15 +19,15 @@ - - + + - + - + diff --git a/developer/src/kmc-convert/test/data/Test_C2.keylayout b/developer/src/kmc-convert/test/data/Test_C2.keylayout index f13fe24eb38..ca6c1940a9d 100644 --- a/developer/src/kmc-convert/test/data/Test_C2.keylayout +++ b/developer/src/kmc-convert/test/data/Test_C2.keylayout @@ -6,8 +6,10 @@ Generated by S. Schmitt + tests C2 rule + --> - + @@ -18,7 +20,7 @@ - + @@ -32,9 +34,9 @@ - + - + diff --git a/developer/src/kmc-convert/test/data/Test_C2_several.keylayout b/developer/src/kmc-convert/test/data/Test_C2_several.keylayout new file mode 100644 index 00000000000..d51369c934c --- /dev/null +++ b/developer/src/kmc-convert/test/data/Test_C2_several.keylayout @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/Test_C3.keylayout b/developer/src/kmc-convert/test/data/Test_C3.keylayout index fe72fc0ca89..32c294256d9 100644 --- a/developer/src/kmc-convert/test/data/Test_C3.keylayout +++ b/developer/src/kmc-convert/test/data/Test_C3.keylayout @@ -2,12 +2,12 @@ - @@ -25,11 +25,9 @@ - - + - @@ -47,15 +45,11 @@ - + - + - - - - diff --git a/developer/src/kmc-convert/test/data/Test_C3_several.keylayout b/developer/src/kmc-convert/test/data/Test_C3_several.keylayout new file mode 100644 index 00000000000..1d3384be84f --- /dev/null +++ b/developer/src/kmc-convert/test/data/Test_C3_several.keylayout @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/Test_DifferentAmountMapSelect_KeyMapERROR.keylayout b/developer/src/kmc-convert/test/data/Test_DifferentAmountMapSelect_KeyMapERROR.keylayout index a95f29fd14e..15b8a9a72ca 100644 --- a/developer/src/kmc-convert/test/data/Test_DifferentAmountMapSelect_KeyMapERROR.keylayout +++ b/developer/src/kmc-convert/test/data/Test_DifferentAmountMapSelect_KeyMapERROR.keylayout @@ -20,10 +20,10 @@ - + - + @@ -55,26 +55,12 @@ - - - - - - + - - - - - - - - - diff --git a/developer/src/kmc-convert/test/data/Test_DifferentAmountOfMapSelectInKeyMapERROR.keylayout b/developer/src/kmc-convert/test/data/Test_DifferentAmountOfMapSelectInKeyMapERROR.keylayout new file mode 100644 index 00000000000..2fe9c05e76d --- /dev/null +++ b/developer/src/kmc-convert/test/data/Test_DifferentAmountOfMapSelectInKeyMapERROR.keylayout @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/Test_DifferentAmountOfMapSelectInKeyMapERROR_1.keylayout b/developer/src/kmc-convert/test/data/Test_DifferentAmountOfMapSelectInKeyMapERROR_1.keylayout new file mode 100644 index 00000000000..38621b27002 --- /dev/null +++ b/developer/src/kmc-convert/test/data/Test_DifferentAmountOfMapSelectInKeyMapERROR_1.keylayout @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/Test_additionalTags.keylayout b/developer/src/kmc-convert/test/data/Test_additionalTags.keylayout deleted file mode 100644 index 990b60a23a0..00000000000 --- a/developer/src/kmc-convert/test/data/Test_additionalTags.keylayout +++ /dev/null @@ -1,601 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/developer/src/kmc-convert/test/data/Test_ambiguous_keys.keylayout b/developer/src/kmc-convert/test/data/Test_ambiguous_keys.keylayout new file mode 100644 index 00000000000..97778e876ee --- /dev/null +++ b/developer/src/kmc-convert/test/data/Test_ambiguous_keys.keylayout @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/Test_characters.keylayout b/developer/src/kmc-convert/test/data/Test_characters.keylayout new file mode 100644 index 00000000000..2aae8f1bb46 --- /dev/null +++ b/developer/src/kmc-convert/test/data/Test_characters.keylayout @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/Test_differentAmountOfKeysInBehaviours.keylayout b/developer/src/kmc-convert/test/data/Test_differentAmountOfKeysInBehaviours.keylayout new file mode 100644 index 00000000000..4b770866cd6 --- /dev/null +++ b/developer/src/kmc-convert/test/data/Test_differentAmountOfKeysInBehaviours.keylayout @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/Test_duplicate_keys.keylayout b/developer/src/kmc-convert/test/data/Test_duplicate_keys.keylayout new file mode 100644 index 00000000000..a5cb09069bf --- /dev/null +++ b/developer/src/kmc-convert/test/data/Test_duplicate_keys.keylayout @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/Test_duplicate_missing_keycode.keylayout b/developer/src/kmc-convert/test/data/Test_duplicate_missing_keycode.keylayout index 193c0495563..39da3300f4f 100644 --- a/developer/src/kmc-convert/test/data/Test_duplicate_missing_keycode.keylayout +++ b/developer/src/kmc-convert/test/data/Test_duplicate_missing_keycode.keylayout @@ -11,7 +11,7 @@ tests duplicate keys in keymap --> - + @@ -23,7 +23,7 @@ - + @@ -39,7 +39,7 @@ - + diff --git a/developer/src/kmc-convert/test/data/Test_duplicate_missing_keys.keylayout b/developer/src/kmc-convert/test/data/Test_duplicate_missing_keys.keylayout new file mode 100644 index 00000000000..b3670561432 --- /dev/null +++ b/developer/src/kmc-convert/test/data/Test_duplicate_missing_keys.keylayout @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/Test_maxKeyCode.keylayout b/developer/src/kmc-convert/test/data/Test_maxKeyCode.keylayout new file mode 100644 index 00000000000..60ff92dd425 --- /dev/null +++ b/developer/src/kmc-convert/test/data/Test_maxKeyCode.keylayout @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/Test_messages.keylayout b/developer/src/kmc-convert/test/data/Test_messages.keylayout new file mode 100644 index 00000000000..5d8d1b86820 --- /dev/null +++ b/developer/src/kmc-convert/test/data/Test_messages.keylayout @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/Test_missingTags.keylayout b/developer/src/kmc-convert/test/data/Test_missingTags.keylayout deleted file mode 100644 index 271eeda562e..00000000000 --- a/developer/src/kmc-convert/test/data/Test_missingTags.keylayout +++ /dev/null @@ -1,595 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/developer/src/kmc-convert/test/data/Test_modifier.keylayout b/developer/src/kmc-convert/test/data/Test_modifier.keylayout index 44b2c841435..67ccf4db63e 100644 --- a/developer/src/kmc-convert/test/data/Test_modifier.keylayout +++ b/developer/src/kmc-convert/test/data/Test_modifier.keylayout @@ -5,14 +5,15 @@ Data generated August 1st 2025 Generated by S. Schmitt + test how modifiers will be translated into kmn modifieres (includes caps) --> - + - + @@ -20,7 +21,7 @@ - + @@ -33,14 +34,14 @@ - + - + - - + + diff --git a/developer/src/kmc-convert/test/data/Test_modifierNoCaps.keylayout b/developer/src/kmc-convert/test/data/Test_modifierNoCaps.keylayout index 92256b9329a..9656413d7e6 100644 --- a/developer/src/kmc-convert/test/data/Test_modifierNoCaps.keylayout +++ b/developer/src/kmc-convert/test/data/Test_modifierNoCaps.keylayout @@ -6,17 +6,19 @@ Generated by S. Schmitt - this is esentoiially the same as Test_modifier.keylayout with every CAPS removed which results in - skipping NCAPS in this case - creating ambiguous rules in some cases since removing caps creates a new shiftstate: shift + caps => shift + tests how modifiers will be translated into kmn modifieres (with caps) + + this is esentiially the same as Test_modifier.keylayout with every CAPS removed which results in + - skipping NCAPS in these cases + - creating ambiguous rules in some cases since removing caps creates a new shiftstate: shift caps =>shift --> - + - + @@ -24,7 +26,7 @@ - + @@ -37,14 +39,14 @@ - + - + - - + + diff --git a/developer/src/kmc-convert/test/data/Test_noActionWhen.keylayout b/developer/src/kmc-convert/test/data/Test_noActionWhen.keylayout deleted file mode 100644 index 61d87537ad6..00000000000 --- a/developer/src/kmc-convert/test/data/Test_noActionWhen.keylayout +++ /dev/null @@ -1,598 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/developer/src/kmc-convert/test/data/Test_nr_elements.keylayout b/developer/src/kmc-convert/test/data/Test_nr_elements.keylayout index 4b770866cd6..7a32f4b3c25 100644 --- a/developer/src/kmc-convert/test/data/Test_nr_elements.keylayout +++ b/developer/src/kmc-convert/test/data/Test_nr_elements.keylayout @@ -6,7 +6,7 @@ Generated by S. Schmitt - if keymaps have different amount of keys derfined -> should print all ( here 2+4 rules) + if keymaps have different amount of keys defined -> should print all ( here 2+4 rules) --> @@ -21,7 +21,7 @@ - + @@ -35,7 +35,7 @@ - + diff --git a/developer/src/kmc-convert/test/data/Test_onlyOneKeymap.keylayout b/developer/src/kmc-convert/test/data/Test_onlyOneKeymap.keylayout index d9a873e15e4..8f173994576 100644 --- a/developer/src/kmc-convert/test/data/Test_onlyOneKeymap.keylayout +++ b/developer/src/kmc-convert/test/data/Test_onlyOneKeymap.keylayout @@ -6,16 +6,18 @@ Generated by S. Schmitt + tests if definition of only one Keymap works + --> - + - - + + @@ -24,16 +26,11 @@ - - + + - + - - - - - diff --git a/developer/src/kmc-convert/test/data/Test_unknownTags.keylayout b/developer/src/kmc-convert/test/data/Test_unknownTags.keylayout deleted file mode 100644 index e34ee307946..00000000000 --- a/developer/src/kmc-convert/test/data/Test_unknownTags.keylayout +++ /dev/null @@ -1,598 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From 0d38c05f1ec1a9a283cbf001df04d530400e04da Mon Sep 17 00:00:00 2001 From: Sabine Date: Sat, 9 Aug 2025 19:48:56 +0200 Subject: [PATCH 159/251] feat(developer): tidy up, ''' -> "'" and tests --- .../src/kmc-convert/src/converter-messages.ts | 11 +- .../keylayout-to-kmn/keylayout-file-reader.ts | 10 +- .../keylayout-to-kmn-converter.ts | 72 +- .../src/keylayout-to-kmn/kmn-file-writer.ts | 60 +- .../test/keylayout-to-kmn-converter.tests.ts | 739 +++++++++++++++++- .../kmc-convert/test/kmn-file-reader.tests.ts | 2 +- .../kmc-convert/test/kmn-file-writer.tests.ts | 2 +- 7 files changed, 775 insertions(+), 121 deletions(-) diff --git a/developer/src/kmc-convert/src/converter-messages.ts b/developer/src/kmc-convert/src/converter-messages.ts index 1d8aa5e70ba..460704c41bc 100644 --- a/developer/src/kmc-convert/src/converter-messages.ts +++ b/developer/src/kmc-convert/src/converter-messages.ts @@ -6,7 +6,7 @@ import { CompilerErrorNamespace, CompilerErrorSeverity, CompilerMessageSpec as m, CompilerMessageDef as def } from '@keymanapp/developer-utils'; const Namespace = CompilerErrorNamespace.Converter; -// const SevInfo = CompilerErrorSeverity.Info | Namespace; + const SevInfo = CompilerErrorSeverity.Info | Namespace; // const SevHint = CompilerErrorSeverity.Hint | Namespace; // const SevWarn = CompilerErrorSeverity.Warn | Namespace; const SevError = CompilerErrorSeverity.Error | Namespace; @@ -52,14 +52,13 @@ export class ConverterMessages { ' could not be written.` ); - static ERROR_UnsupportedCharactersDetected = SevError | 0x0007; - static Error_UnsupportedCharactersDetected = (o: { inputFilename: string, keymap_index: string, key: string, output: string; }) => m( - this.ERROR_UnsupportedCharactersDetected, `Input file ${def(o.inputFilename)} contains unsupported character ('${def(o.output)}') on key (${def(o.key)}) at keyMap index ${def(o.keymap_index)}` - ); - static ERROR_InvalidFile = SevError | 0x0008; static Error_InvalidFile = (o: { errorText: string; }) => m( this.ERROR_InvalidFile, `The source file has an invalid structure: ${def(o.errorText)}` ); + static INFO_UnsupportedCharactersDetected = SevInfo | 0x0007; + static Info_UnsupportedCharactersDetected = (o: { inputFilename: string, keymap_index: string, key: string,KeyName:string, output: string; }) => m( + this.INFO_UnsupportedCharactersDetected, `INFO: Input file ${def(o.inputFilename)} contains unsupported character '${def(o.output)}' at keyMap index ${def(o.keymap_index)} on Keycode ${def(o.key)} (${def(o.KeyName)})` + ); } diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts index 5b267909f93..9d69218bb77 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts @@ -26,14 +26,10 @@ export class KeylayoutFileReader { */ public validate(source: KeylayoutXMLSourceFile): boolean { - if (!SchemaValidators.default.keylayout(source)) { - for (const err of (SchemaValidators.default.keylayout).errors) { - this.callbacks.reportMessage(DeveloperUtilsMessages.Error_SchemaValidationError({ - instancePath: err.instancePath, - keyword: err.keyword, - message: err.message || 'Unknown AJV Error', // docs say 'message' is optional if 'messages:false' in options - params: Object.entries(err.params || {}).sort().map(([k, v]) => `${k}="${v}"`).join(' '), + for (const err of (SchemaValidators.default.keylayout).errors) { + this.callbacks.reportMessage(DeveloperUtilsMessages.Error_InvalidXml({ + e: err.instancePath })); } return false; diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 908d2e0ea22..8d335c5e652 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -12,7 +12,7 @@ import { ConverterToKmnArtifacts } from "../converter-artifacts.js"; import { KmnFileWriter } from './kmn-file-writer.js'; import { KeylayoutFileReader } from './keylayout-file-reader.js'; import { ConverterMessages } from '../converter-messages.js'; -import { KeylayoutXMLSourceFile } from '../../../common/web/utils/src/types/keylayout/keylayout-xml.js'; +import { KeylayoutXMLSourceFile } from '@keymanapp/developer-utils'; /** * Object holding all important data for the conversion between @@ -205,24 +205,15 @@ export class KeylayoutToKmnConverter { // loop behaviors (in ukelele it is possible to define multiple modifier combinations that behave in the same way) for (let i = 0; i < jsonObj.keyboard.keyMapSet[0].keyMap.length; i++) { - const KeyIndex_j = j; - const BehavIndex_i = i; - const maxKey = jsonObj.keyboard.keyMapSet[0].keyMap[i].key.length; - const maxBeh = jsonObj.keyboard.keyMapSet[0].keyMap.length; - - const isItAvailable = (((KeyIndex_j < maxKey) && (BehavIndex_i < maxBeh))); - + // if index of keys and behaviours exist + const isItAvailable = ((j < jsonObj.keyboard.keyMapSet[0].keyMap[i].key.length) && (i < jsonObj.keyboard.keyMapSet[0].keyMap.length)); if (!isItAvailable) { continue; } - let rule_obj: Rule; - //if (i < maxkey) { - if ((j < jsonObj.keyboard.keyMapSet[0].keyMap[i].key.length)) { - //if (i < maxBeh) { - // if (i < jsonObj.keyboard.keyMapSet[0].keyMap.length) { + if ((j < jsonObj.keyboard.keyMapSet[0].keyMap[i].key.length)) { // ............................................................................................................................... // case C0: output ............................................................................................................... // C0 see: https://docs.google.com/document/d/12J3NGO6RxIthCpZDTR8FYSRjiMgXJDLwPY2z9xqKzJ0/edit?tab=t.0#heading=h.g7jwx3lx0ydd ... @@ -475,22 +466,13 @@ export class KeylayoutToKmnConverter { } } } else { - - /* QUESTION - // _S2 why does this not work here? Correct data in this.callback.messages is available !?!?! - this.callbacks.reportMessage(ConverterMessages.Error_UnsupportedCharactersDetected({ - inputFilename: jsonObj.keyboard['@_name'] + ".keylayout", - keymap_index: jsonObj.keyboard.keyMapSet[0].keyMap[i]['@_index'], - output: jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'], - key: jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'] - })); - return null;*/ - - console.log(" ERROR : some output characters can not be used in Keyman \"", - (jsonObj.keyboard['@_name'] + ".keylayout\""), - "\"\" :", - jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]); - continue; + this.callbacks.reportMessage(ConverterMessages.Info_UnsupportedCharactersDetected({ + inputFilename: jsonObj.keyboard['@_name'] + ".keylayout", + keymap_index: jsonObj.keyboard.keyMapSet[0].keyMap[i]['@_index'], + output: jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'], + key: jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], + KeyName: this.map_UkeleleKC_To_VK(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code']) + })); } } } @@ -864,7 +846,9 @@ export class KeylayoutToKmnConverter { if (data.keyboard.actions.action[i]['@_id'] === search) { for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { if (data.keyboard.actions.action[i].when[j]['@_state'] === "none") { - OutputValue = data.keyboard.actions.action[i].when[j]['@_output']; + if (data.keyboard.actions.action[i].when[j]['@_output'] !== undefined) { + OutputValue = data.keyboard.actions.action[i].when[j]['@_output']; + } } } } @@ -890,8 +874,7 @@ export class KeylayoutToKmnConverter { for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search[k].id && - data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'] <= KeylayoutToKmnConverter.USE_KEY_COUNT) { - + data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'] <= KeylayoutToKmnConverter.MAX_KEY_COUNT) { returnObject = { keyCode: data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], key: this.map_UkeleleKC_To_VK(Number(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])), @@ -920,17 +903,18 @@ export class KeylayoutToKmnConverter { for (let i = 0; i < data.keyboard.actions.action.length; i++) { for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { if ((data.keyboard.actions.action[i].when[j]['@_state'] === search)) { - - returnObject = { - id: data.keyboard.actions.action[i]['@_id'], - state: data.keyboard.actions.action[i].when[j]['@_state'], - output: data.keyboard.actions.action[i].when[j]['@_output'] - }; - returnObjarray1D.push(returnObject); + if (data.keyboard.actions.action[i].when[j]['@_output'] !== undefined) { + returnObject = { + id: data.keyboard.actions.action[i]['@_id'], + state: data.keyboard.actions.action[i].when[j]['@_state'], + output: data.keyboard.actions.action[i].when[j]['@_output'] + }; + returnObjarray1D.push(returnObject); + } } } } - return returnObjarray1D; // _S2 ToDo rewrite/change all functio comments to new datatypes!!! + return returnObjarray1D; } /** @@ -994,8 +978,7 @@ export class KeylayoutToKmnConverter { } // loop behaviors (in ukelele it is possible to define multiple modifier combinations that behave in the same way) for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { - - for (let j = 0; j <= KeylayoutToKmnConverter.USE_KEY_COUNT; j++) { + for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { for (let k = 0; k < modi[data.keyboard.keyMapSet[0].keyMap[i]['@_index']].length; k++) { const behaviour_idx: number = data.keyboard.keyMapSet[0].keyMap[i]['@_index']; @@ -1037,14 +1020,11 @@ export class KeylayoutToKmnConverter { * @param search : string - an actionId to be found * @return an array: allArrayContents_object[] containing [{keycode,behaviour}] */ - // _S2 check if all array2d types ate deleted - // _S2 check if action/search is available in all get_ func public get_KeyModifier_array__From__ActionID(data: any, search: string): allArrayContents_object[] { let returnObject: allArrayContents_object; const mapIndexObject1D: allArrayContents_object[] = []; - for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { - for (let j = 0; j <= KeylayoutToKmnConverter.USE_KEY_COUNT; j++) { + for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { returnObject = { key: data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'], diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts index 2854940eccd..e43db3d426e 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts @@ -149,7 +149,7 @@ export class KmnFileWriter { // lookup key nr of the key which is being processed let keyNr: number = 0; - for (let j = 0; j <= KeylayoutToKmnConverter.USE_KEY_COUNT; j++) { + for (let j = 0; j <= KeylayoutToKmnConverter.MAX_KEY_COUNT; j++) { if (keylayoutKmnConverter.map_UkeleleKC_To_VK(j) === unique_data_Rules[k].key) { keyNr = j; break; @@ -207,12 +207,22 @@ export class KmnFileWriter { } if (!((warn_text[2].length > 0) && KeylayoutToKmnConverter.SKIP_COMMENTED_LINES)) { - data += warningTextToWrite - + "+ [" - + (unique_data_Rules[k].modifier_key + ' ' + unique_data_Rules[k].key).trim() - + `] > \'` - + version_output_character - + '\'\n'; + if (version_output_character === "'") { + data += warningTextToWrite + + "+ [" + + (unique_data_Rules[k].modifier_key + ' ' + unique_data_Rules[k].key).trim() + + `] > \"` + + version_output_character + + '\"\n'; + } + else { + data += warningTextToWrite + + "+ [" + + (unique_data_Rules[k].modifier_key + ' ' + unique_data_Rules[k].key).trim() + + `] > \'` + + version_output_character + + '\'\n'; + } } } } @@ -235,7 +245,6 @@ export class KmnFileWriter { if ((output_Unicode_Character !== undefined) && (output_Unicode_CodePoint !== undefined)) { // if we are about to print a unicode codepoint instead of a single character we need to check if it is a control character if (Number("0x" + output_Unicode_Character.substring(2, output_Unicode_Character.length)) < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER) { - version_output_character = output_Unicode_CodePoint; if (output_Unicode_Character.length > 1) { if (warn_text[2] == "") { @@ -245,7 +254,6 @@ export class KmnFileWriter { warn_text[2] = warn_text[2] + "; Use of a control character "; } } - } else { version_output_character = output_Unicode_Character; } @@ -278,14 +286,28 @@ export class KmnFileWriter { } if (!((warn_text[2].length > 0) && KeylayoutToKmnConverter.SKIP_COMMENTED_LINES)) { - data += warningTextToWrite - + "dk(A" - + (String(unique_data_Rules[k].id_deadkey) + ") + [" - + unique_data_Rules[k].modifier_key).trim() - + " " - + unique_data_Rules[k].key + "] > \'" - + version_output_character - + "\'\n"; + if (version_output_character === "'") { + data += warningTextToWrite + + "dk(A" + + (String(unique_data_Rules[k].id_deadkey) + ") + [" + + unique_data_Rules[k].modifier_key).trim() + + " " + + unique_data_Rules[k].key + '] > \"' + + version_output_character + + '\"\n'; + } + else { + data += warningTextToWrite + + "dk(A" + + (String(unique_data_Rules[k].id_deadkey) + ") + [" + + unique_data_Rules[k].modifier_key).trim() + + " " + + unique_data_Rules[k].key + "] > \'" + + version_output_character + + "\'\n"; + } + + } data += "\n"; } @@ -508,7 +530,7 @@ export class KmnFileWriter { if (amb_4_1.length > 0) { warningTextArray[2] = warningTextArray[2] - + ("ambiguous 4-1 rule: later: [" + + ("ambiguous rule: later: [" + amb_4_1[0].modifier_prev_deadkey + " " + amb_4_1[0].prev_deadkey @@ -519,7 +541,7 @@ export class KmnFileWriter { if (amb_2_1.length > 0) { warningTextArray[2] = warningTextArray[2] - + ("ambiguous 2-1 rule: later: [" + + ("ambiguous rule: later: [" + amb_2_1[0].modifier_deadkey + " " + amb_2_1[0].deadkey diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index 534a90477ec..9ce3a7768c5 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -9,9 +9,12 @@ import 'mocha'; import { assert } from 'chai'; +import * as NodeAssert from 'node:assert'; +import { CompilerErrorNamespace, CompilerErrorSeverity } from '@keymanapp/developer-utils'; import { compilerTestCallbacks, compilerTestOptions, makePathToFixture } from './helpers/index.js'; -import { KeylayoutToKmnConverter } from '../src/keylayout-to-kmn/keylayout-to-kmn-converter.js'; - +import { idStateOutput_object, allArrayContents_object, KeylayoutToKmnConverter } from '../src/keylayout-to-kmn/keylayout-to-kmn-converter.js'; +import { KeylayoutFileReader } from '../src/keylayout-to-kmn/keylayout-file-reader.js'; +import { ConverterMessages } from '../src/converter-messages.js'; describe('KeylayoutToKmnConverter', function () { @@ -19,46 +22,23 @@ describe('KeylayoutToKmnConverter', function () { compilerTestCallbacks.clear(); }); - // todo remove - describe('RunAllFiles', function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - [ - [makePathToFixture('../data/Italian.keylayout')], - [makePathToFixture('../data/Italian_command.keylayout')], - [makePathToFixture('../data/Swiss_French.keylayout')], - [makePathToFixture('../data/Spanish.keylayout')], - [makePathToFixture('../data/Swiss_German.keylayout')], - [makePathToFixture('../data/US.keylayout')], - [makePathToFixture('../data/Polish.keylayout')], - [makePathToFixture('../data/French.keylayout')], - [makePathToFixture('../data/Latin_American.keylayout')], - // [makePathToFixture('../data/German_complete.keylayout')], - [makePathToFixture('../data/German_complete_reduced.keylayout')], - //[makePathToFixture('../data/German_Standard.keylayout')], - ].forEach(function (files_) { - sut.run(files_[0]); - assert.isTrue(true); - }); - }); - describe('RunTestFiles resulting in errors ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); [ - ['../data/Test_DifferentAmountMapSelect_KeyMapERROR.keylayout', 5292040], - ['../data/Test_DifferentAmountMapSelect_KeyMapERROR_1.keylayout', 5292040], - ['../data/Test_MissingkeyMapERROR.keylayout', 5246977], - ['../data/Test_MissingkeyERROR.keylayout', 5246977], - ['../data/Test_MissingLayoutsERROR.keylayout', 5292036], - ['../data/Test_MissingmodifierMapERROR.keylayout', 5292036], - ['../data/Test_MissingkeyMapSetERROR.keylayout', 5292036], - ['../data/Test_MissingActionsERROR.keylayout', 5292036], - ['../data/Test_MissingTerminatorsERROR.keylayout', 5292036], - ['../data/Test_MissingAllERROR.keylayout', 5292036], + [makePathToFixture('../data/Test_DifferentAmountOfMapSelectInKeyMapERROR.keylayout')], + [makePathToFixture('../data/Test_DifferentAmountOfMapSelectInKeyMapERROR_1.keylayout')], + [makePathToFixture('../data/Test_MissingkeyERROR.keylayout')], + [makePathToFixture('../data/Test_MissingkeyMapERROR.keylayout')], + [makePathToFixture('../data/Test_MissingLayoutsERROR.keylayout')], + [makePathToFixture('../data/Test_MissingmodifierMapERROR.keylayout')], + [makePathToFixture('../data/Test_MissingkeyMapSetERROR.keylayout')], + [makePathToFixture('../data/Test_MissingActionsERROR.keylayout')], + [makePathToFixture('../data/Test_MissingTerminatorsERROR.keylayout')], + [makePathToFixture('../data/Test_MissingAllERROR.keylayout')], ].forEach(function (files_) { - it(files_ + " should give error ", async function () { - sut.run(makePathToFixture(files_[0] as string)); + it(files_ + " should give an error ", async function () { + sut.run(files_[0]); assert.isTrue(compilerTestCallbacks.messages.length > 0); - assert.isTrue(String(compilerTestCallbacks.messages[0].code) === String(files_[1])); }); }); }); @@ -73,12 +53,15 @@ describe('KeylayoutToKmnConverter', function () { [makePathToFixture('../data/Test_C3.keylayout')], [makePathToFixture('../data/Test_C3_several.keylayout')], [makePathToFixture('../data/Test_C0_C1_C2_C3.keylayout')], - + [makePathToFixture('../data/Test_maxKeyCode.keylayout')], + [makePathToFixture('../data/Test_messages.keylayout')], [makePathToFixture('../data/Test_duplicate_missing_keycode.keylayout')], - [makePathToFixture('../data/Test_characters.keylayout')], [makePathToFixture('../data/Test_modifier.keylayout')], [makePathToFixture('../data/Test_modifierNoCaps.keylayout')], - [makePathToFixture('../data/Test_onlyOneKeymap.keylayout')], + [makePathToFixture('../data/Test_differentAmountOfKeysInBehaviours.keylayout')], + [makePathToFixture('../data/Test_duplicate_missing_keys.keylayout')], + [makePathToFixture('../data/Test_duplicate_keys.keylayout')], + [makePathToFixture('../data/Test_ambiguous_keys.keylayout')], [makePathToFixture('../data/Test_nr_elements.keylayout')], [makePathToFixture('../data/Test.keylayout')], ].forEach(function (files_) { @@ -89,5 +72,679 @@ describe('KeylayoutToKmnConverter', function () { }); }); + describe('RunSpecialTestFiles - create Info', function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + [ + [makePathToFixture('../data/Test_characters.keylayout')], + [makePathToFixture('../data/Test_onlyOneKeymap.keylayout')], + ].forEach(function (files_) { + it(files_ + " should give Info: unsupported characters ", async function () { + sut.run(files_[0]); + assert.isTrue(compilerTestCallbacks.messages.length === 1); + assert.isTrue(compilerTestCallbacks.messages[0].code === (CompilerErrorSeverity.Info | CompilerErrorNamespace.Converter | 0x0007)); + }); + }); + }); + + describe('run() ', function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + + it('run() should throw on null input file name and null output file name', async function () { + // note, could use 'chai as promised' library to make this more fluent: + const result = sut.run(null, null); + assert.isNotNull(result); + assert.equal(compilerTestCallbacks.messages.length, 1); + assert.deepEqual(compilerTestCallbacks.messages[0], ConverterMessages.Error_FileNotFound({ inputFilename: null })); + }); + + it('run() should throw on null input file name and empty output file name', async function () { + const result = sut.run(null, ''); + assert.isNotNull(result); + assert.equal(compilerTestCallbacks.messages.length, 1); + assert.deepEqual(compilerTestCallbacks.messages[0], ConverterMessages.Error_FileNotFound({ inputFilename: null })); + }); + + + it('run() should throw on null input file name and unknown output file name', async function () { + const result = sut.run(null, 'X'); + assert.isNotNull(result); + assert.equal(compilerTestCallbacks.messages.length, 1); + assert.deepEqual(compilerTestCallbacks.messages[0], ConverterMessages.Error_FileNotFound({ inputFilename: null })); + }); + + it('run() should throw on unavailable input file name and null output file name', async function () { + const inputFilename = makePathToFixture('../data/Unavailable.keylayout'); + const result = sut.run(inputFilename, null); + assert.isNotNull(result); + assert.equal(compilerTestCallbacks.messages.length, 1); + assert.deepEqual(compilerTestCallbacks.messages[0], ConverterMessages.Error_OutputFilenameIsRequired()); + }); + + it('run() should throw on and null output file name', async function () { + const inputFilename = makePathToFixture('../data/Test.keylayout'); + const result = sut.run(inputFilename, null); + assert.isNotNull(result); + assert.equal(compilerTestCallbacks.messages.length, 1); + assert.deepEqual(compilerTestCallbacks.messages[0], ConverterMessages.Error_OutputFilenameIsRequired()); + }); + + it('run() should return on correct input file name and empty output file name ', async function () { + const inputFilename = makePathToFixture('../data/Test.keylayout'); + await NodeAssert.doesNotReject(async () => sut.run(inputFilename, '')); + }); + + it('run() should return on correct input file name and null output file name', async function () { + const inputFilename = makePathToFixture('../data/Test.keylayout'); + await NodeAssert.doesNotReject(async () => sut.run(inputFilename, null)); + }); + + it('run() should return on correct input file name and given output file name ', async function () { + const inputFilename = makePathToFixture('../data/Test.keylayout'); + const outputFilename = makePathToFixture('../data/OutputName.kmn'); + await NodeAssert.doesNotReject(async () => sut.run(inputFilename, outputFilename)); + }); + + it('run() return on correct input file extention and unsupperted output file extention', async function () { + const inputFilename = makePathToFixture('../data/Test.keylayout'); + const outputFilename = makePathToFixture('../data/OutputXName.B'); + await NodeAssert.doesNotReject(async () => sut.run(inputFilename, outputFilename)); + }); + }); + + describe('convert() ', function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sut_r = new KeylayoutFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/Test.keylayout'); + const read = sut_r.read(inputFilename); + const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); + + // convert_object from unavailable file name + const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); + const read_unavailable = sut_r.read(inputFilename_unavailable); + const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); + + // convert_object from empty filename + const inputFilename_empty = makePathToFixture(''); + const read_empty = sut_r.read(inputFilename_empty); + const converted_empty = sut.convert_bound.convert(read_empty, inputFilename_empty); + + it('should return converted array on correct input', async function () { + assert.isTrue(converted.arrayOf_Rules.length !== 0); + }); + + it('should return empty on empty input', async function () { + assert.isTrue((converted_empty.keylayout_filename === '' + && converted_empty.arrayOf_Modifiers.length === 0 + && converted_empty.arrayOf_Rules.length === 0)); + }); + + it('should return empty on only name as input', async function () { + assert.isTrue((converted_unavailable.keylayout_filename === '' + && converted_unavailable.arrayOf_Modifiers.length === 0 + && converted_unavailable.arrayOf_Rules.length === 0)); + }); + + it('should return empty on only modifiers as input', async function () { + const converted_mod = sut.convert_bound.convert({ + keylayout_filename: '', + arrayOf_Modifiers: [['caps'], ['Shift'], ['command']], + arrayOf_Rules: [] + }, ''); + assert.isTrue((converted_mod.keylayout_filename === '' + && converted_mod.arrayOf_Modifiers.length === 0 + && converted_mod.arrayOf_Rules.length === 0)); + }); + + it('should return empty on only rules as input', async function () { + const converted_rule = sut.convert_bound.convert({ + keylayout_filename: '', + arrayOf_Modifiers: [], + arrayOf_Rules: [['C0', '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_A', 'A']] + }, ''); + assert.isTrue((converted_rule.keylayout_filename === '' + && converted_rule.arrayOf_Modifiers.length === 0 + && converted_rule.arrayOf_Rules.length === 0)); + }); + + it('should return empty array of rukes on null input', async function () { + const converted_rule = sut.convert_bound.convert(null, 'ABC.kmn'); + assert.isTrue(converted_rule.arrayOf_Rules.length === 0); + }); + }); + + describe('create_kmn_modifier ', function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + + [ + ['NCAPS', true, 'NCAPS'], + ['NCAPS shift', true, 'NCAPS SHIFT'], + ['shift', true, 'NCAPS SHIFT'], + ['leftshift', true, 'NCAPS SHIFT'], + ['rightShift', true, 'NCAPS SHIFT'], + ['shift rightShift?', true, 'NCAPS SHIFT'], + ['rightShift?', true, 'NCAPS'], + ['shift Shift?', true, 'NCAPS SHIFT'], + ['shift rightShift? caps? rightOption? rightControl', true, 'NCAPS SHIFT RCTRL'], + ['leftshift rightShift? caps? rightOption? rightControl', true, 'NCAPS SHIFT RCTRL'], + ['anycontrol', true, 'NCAPS CTRL'], + ['shift?', true, 'NCAPS'], + ['?', true, 'NCAPS'], + ['?', false, ''], + ['caps', true, 'CAPS'], + ['', true, 'NCAPS'], + [' ', false, ''], + ['wrongModifierName', false, 'wrongModifierName'], + ['shift', false, 'SHIFT'], + ['shift command', true, 'NCAPS SHIFT command'], + ['rshift', true, 'NCAPS SHIFT'], + ['rshift', false, 'SHIFT'], + ['rightshift', true, 'NCAPS SHIFT'], + ['riGhtsHift', true, 'NCAPS SHIFT'], + ['LEFTCONTROL', true, 'NCAPS LCTRL'], + ['RCONTROL', true, 'NCAPS RCTRL'], + ['leftoption', true, 'NCAPS LALT'], + ['loption', true, 'NCAPS LALT'], + ['rightoption', true, 'NCAPS RALT'], + ['roption', true, 'NCAPS RALT'], + ].forEach(function (values) { + it(('should convert "' + values[0] + '"').padEnd(36, " ") + 'to "' + values[2] + '"', async function () { + const result = sut.create_kmn_modifier(values[0] as string, values[1] as boolean); + assert.equal(result, values[2]); + }); + }); + }); + + describe('isAcceptableKeymanModifier ', function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + + [ + ['NCAPS', true], + ['NxCAPS', false], + ['SHIFT', true], + ['ALT', true], + ['RALT', true], + ['LALT', true], + ['CTRL', true], + ['LCTRL', true], + ['RCTRL', true], + ['LCTRL CAPS', true], + ['LCTRL X', false], + ['', true], + [null, false], + ].forEach(function (values) { + it(("isAcceptableKeymanModifier(" + values[0] + ")").padEnd(38, " ") + ' should return ' + values[1], async function () { + const result = sut.isAcceptableKeymanModifier(values[0] as string); + assert.equal(result, values[1]); + }); + }); + }); + + describe('map_UkeleleKC_To_VK ', function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + [ + [0x00, 'K_A'], + [0x31, 'K_SPACE'], + [0x18, 'K_EQUAL'], + [0x10, 'K_Y'], + [0x18, 'K_EQUAL'], + [0x21, 'K_LBRKT'], + [0x999, ''], + [-1, ''], + [null, ''], + [undefined, ''], + [, ''], + ].forEach(function (values) { + it(("map_UkeleleKC_To_VK(" + values[0] + ")").padEnd(26, " ") + "should return " + "'" + values[1] + "'", async function () { + const result = sut.map_UkeleleKC_To_VK(values[0] as number); + assert.equal(result, values[1]); + }); + }); + }); + + describe('checkIfCapsIsUsed ', function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + + [ + [[['caps', 'xxx'], ['yyy']], true], + [[['Caps', 'xxx'], ['yyy']], true], + [[['Caps?', 'xxx'], ['yyy']], true], + [[['caps?', 'xxx'], ['yyy']], true], + [[['CaPs', 'xxx'], ['yyy']], true], + [[['zzz', 'xxx'], ['yyy']], false], + [[['', ''], ['']], false], + [[null], false], + ].forEach(function (values) { + it(("checkIfCapsIsUsed([['caps', 'xxx'], ['yyy']])").padEnd(45, " ") + "should return " + "'" + values[1] + "'", async function () { + const result = sut.checkIfCapsIsUsed(values[0] as string[][]) === values[1]; + assert.isTrue(result); + }); + }); + }); + + describe('get_Modifier_array__From__KeyModifier_array ', function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sut_r = new KeylayoutFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/Test.keylayout'); + const read = sut_r.read(inputFilename); + const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); + [ + [[{ key: '0', behaviour: 0 }], [['', 'shift? caps? ']]], + [[{ key: '0', behaviour: 2 }], [['shift? leftShift caps? ', 'anyShift caps?', 'shift leftShift caps ', 'shift? rightShift caps? ']]], + [[{ key: '0', behaviour: 999 }], [null]], + [[{ key: '999', behaviour: null }], [null]], + [[{ key: '0', behaviour: -999 }], [null]], + [[{ key: '0', behaviour: null }], [null]], + [[], []], + + ].forEach(function (values) { + it((values[1] !== null) ? + ("get_Modifier_array__From__KeyModifier_array('" + JSON.stringify(values[0]) + "')").padEnd(68, " ") + " should return '" + JSON.stringify(values[1]) + "'" : + ("get_Modifier_array__From__KeyModifier_array('" + JSON.stringify(values[0]) + "')").padEnd(68, " ") + " should return '" + "null" + "'", async function () { + const result = sut.get_Modifier_array__From__KeyModifier_array(converted.arrayOf_Modifiers, values[0] as allArrayContents_object[]); + assert.deepStrictEqual(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); + }); + + describe('get_KeyModifier_array__From__ActionID ', function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sut_r = new KeylayoutFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/Test.keylayout'); + const read = sut_r.read(inputFilename); + [ + ['A_16', [{ "key": "32", "behaviour": "5" }]], + ['A_19', [{ "key": "45", "behaviour": "5" }]], + ['A_18', [{ "key": "24", "behaviour": "0" }, { "key": "24", "behaviour": "5" }]], + ['unknown', []], + [undefined, []], + [null, []], + [' ', []], + ['', []], + ].forEach(function (values) { + let outstring = '[ '; + for (let i = 0; i < values[1].length; i++) { + outstring = outstring + "[ " + JSON.stringify(values[1][i]) + "], "; + } + it(("get_KeyModifier_array__From__ActionID('" + values[0] + "')").padEnd(57, " ") + ' should return ' + outstring.substring(0, outstring.lastIndexOf(']') + 2) + " ]", async function () { + const result = sut.get_KeyModifier_array__From__ActionID(read, String(values[0])); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); + }); + + describe('get_ActionID__From__ActionNext ', function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sut_r = new KeylayoutFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/Test.keylayout'); + const read = sut_r.read(inputFilename); + + [ + ['none', ''], + ['0', ''], + ['A_18', ''], + ['1', 'A_16'], + ['2', 'A_8'], + ['3', 'A_17'], + ['', ''], + [' ', ''], + ['99', ''], + [null, ''], + [undefined, ''], + ['unknown', ''], + ].forEach(function (values) { + it(("get_ActionID__From__ActionNext('" + values[0] + "')").padEnd(49, " ") + ' should return ' + "'" + values[1] + "'", async function () { + const result = sut.get_ActionID__From__ActionNext(read, String(values[0])); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); + }); + describe('get_ActionIndex__From__ActionId ', function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sut_r = new KeylayoutFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/Test.keylayout'); + const read = sut_r.read(inputFilename); + + [ + ['none', 0], + ['A_16', 8], + ['A_18', 10], + ['A_19', 11], + ['0', 0], + ['', 0], + [' ', 0], + [null, 0], + [undefined, 0], + ['unknown', 0], + ].forEach(function (values) { + it(("get_ActionIndex__From__ActionId('" + values[0] + "')").padEnd(50, " ") + ' should return ' + values[1], async function () { + const result = sut.get_ActionIndex__From__ActionId(read, String(values[0])); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); + }); + describe('get_Output__From__ActionId_None ', function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sut_r = new KeylayoutFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/Test.keylayout'); + const read = sut_r.read(inputFilename); + + [ + ['A_14', 'u'], + ['', ''], + [' ', ''], + ['A_18', ''], + ['unknown', ''], + ].forEach(function (values) { + it( + ("get_Output__From__ActionId_None('" + values[0] + "')").padEnd(56, " ") + ' should return ' + "'" + values[1] + "'", async function () { + const result = sut.get_Output__From__ActionId_None(read, String(values[0])); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); + + [[null, ''], + [undefined, ''], + [99, ''], + ].forEach(function (values) { + it(("get_Output__From__ActionId_None('" + values[0] + "')").padEnd(56, " ") + ' should return ' + values[1], async function () { + const result = sut.get_Output__From__ActionId_None(read, String(values[0])); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); + }); + describe('get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array ', function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sut_r = new KeylayoutFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/Test.keylayout'); + const read = sut_r.read(inputFilename); + + const b1_keycode_arr: allArrayContents_object[] = [ + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '0', outchar: 'ˆ' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '1', outchar: 'ˆ' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '2', outchar: 'ˆ' }, + { keyCode: '6', key: 'K_Z', actionId: 'A_0', behaviour: '4', outchar: 'ˆ' }, + { keyCode: '25', key: 'K_9', actionId: 'A_0', behaviour: '4', outchar: 'ˆ' }, + { keyCode: '43', key: 'K_COMMA', actionId: 'A_0', behaviour: '4', outchar: 'ˆ' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '3', outchar: 'ˆ' }, + { keyCode: '0', key: 'K_A', actionId: 'A_1', behaviour: '2', outchar: 'Â' }, + { keyCode: '0', key: 'K_A', actionId: 'A_1', behaviour: '1', outchar: 'Â' }, + { keyCode: '14', key: 'K_E', actionId: 'A_10', behaviour: '0', outchar: 'ê' }, + { keyCode: '34', key: 'K_I', actionId: 'A_11', behaviour: '0', outchar: 'î' }, + { keyCode: '31', key: 'K_O', actionId: 'A_13', behaviour: '0', outchar: 'ô' }, + { keyCode: '32', key: 'K_U', actionId: 'A_14', behaviour: '0', outchar: 'û' }, + { keyCode: '14', key: 'K_E', actionId: 'A_2', behaviour: '2', outchar: 'Ê' }, + { keyCode: '14', key: 'K_E', actionId: 'A_2', behaviour: '1', outchar: 'Ê' }, + { keyCode: '34', key: 'K_I', actionId: 'A_3', behaviour: '2', outchar: 'Î' }, + { keyCode: '34', key: 'K_I', actionId: 'A_3', behaviour: '1', outchar: 'Î' }, + { keyCode: '31', key: 'K_O', actionId: 'A_5', behaviour: '2', outchar: 'Ô' }, + { keyCode: '31', key: 'K_O', actionId: 'A_5', behaviour: '1', outchar: 'Ô' }, + { keyCode: '32', key: 'K_U', actionId: 'A_6', behaviour: '2', outchar: 'Û' }, + { keyCode: '32', key: 'K_U', actionId: 'A_6', behaviour: '1', outchar: 'Û' }, + { keyCode: '0', key: 'K_A', actionId: 'A_9', behaviour: '0', outchar: 'â' } + + ]; + const b1_modifierKey_arr: allArrayContents_object[] = [ + { actionId: 'A_0', key: 'K_SPACE', behaviour: '0', modifier: 'NCAPS', outchar: 'ˆ' }, + { actionId: 'A_0', key: 'K_SPACE', behaviour: '1', modifier: 'CAPS', outchar: 'ˆ' }, + { actionId: 'A_0', key: 'K_SPACE', behaviour: '2', modifier: 'NCAPS SHIFT', outchar: 'ˆ' }, + { actionId: 'A_0', key: 'K_SPACE', behaviour: '2', modifier: 'SHIFT CAPS', outchar: 'ˆ' }, + { actionId: 'A_0', key: 'K_Z', behaviour: '4', modifier: 'NCAPS SHIFT RALT', outchar: 'ˆ' }, + { actionId: 'A_0', key: 'K_9', behaviour: '4', modifier: 'NCAPS SHIFT RALT', outchar: 'ˆ' }, + { actionId: 'A_0', key: 'K_COMMA', behaviour: '4', modifier: 'NCAPS SHIFT RALT', outchar: 'ˆ' }, + { actionId: 'A_0', key: 'K_SPACE', behaviour: '3', modifier: 'NCAPS RALT CTRL', outchar: 'ˆ' }, + { actionId: 'A_0', key: 'K_SPACE', behaviour: '3', modifier: 'NCAPS CTRL', outchar: 'ˆ' }, + { actionId: 'A_1', key: 'K_A', behaviour: '2', modifier: 'NCAPS SHIFT', outchar: 'Â' }, + { actionId: 'A_1', key: 'K_A', behaviour: '2', modifier: 'SHIFT CAPS', outchar: 'Â' }, + { actionId: 'A_1', key: 'K_A', behaviour: '1', modifier: 'CAPS', outchar: 'Â' }, + { actionId: 'A_10', key: 'K_E', behaviour: '0', modifier: 'NCAPS', outchar: 'ê' }, + { actionId: 'A_11', key: 'K_I', behaviour: '0', modifier: 'NCAPS', outchar: 'î' }, + { actionId: 'A_13', key: 'K_O', behaviour: '0', modifier: 'NCAPS', outchar: 'ô' }, + { actionId: 'A_14', key: 'K_U', behaviour: '0', modifier: 'NCAPS', outchar: 'û' }, + { actionId: 'A_2', key: 'K_E', behaviour: '2', modifier: 'NCAPS SHIFT', outchar: 'Ê' }, + { actionId: 'A_2', key: 'K_E', behaviour: '2', modifier: 'SHIFT CAPS', outchar: 'Ê' }, + { actionId: 'A_2', key: 'K_E', behaviour: '1', modifier: 'CAPS', outchar: 'Ê' }, + { actionId: 'A_3', key: 'K_I', behaviour: '2', modifier: 'NCAPS SHIFT', outchar: 'Î' }, + { actionId: 'A_3', key: 'K_I', behaviour: '2', modifier: 'SHIFT CAPS', outchar: 'Î' }, + { actionId: 'A_3', key: 'K_I', behaviour: '1', modifier: 'CAPS', outchar: 'Î' }, + { actionId: 'A_5', key: 'K_O', behaviour: '2', modifier: 'NCAPS SHIFT', outchar: 'Ô' }, + { actionId: 'A_5', key: 'K_O', behaviour: '2', modifier: 'SHIFT CAPS', outchar: 'Ô' }, + { actionId: 'A_5', key: 'K_O', behaviour: '1', modifier: 'CAPS', outchar: 'Ô' }, + { actionId: 'A_6', key: 'K_U', behaviour: '2', modifier: 'NCAPS SHIFT', outchar: 'Û' }, + { actionId: 'A_6', key: 'K_U', behaviour: '2', modifier: 'SHIFT CAPS', outchar: 'Û' }, + { actionId: 'A_6', key: 'K_U', behaviour: '1', modifier: 'CAPS', outchar: 'Û' }, + { actionId: 'A_9', key: 'K_A', behaviour: '0', modifier: 'NCAPS', outchar: 'â' } + ]; + + [[b1_keycode_arr, b1_modifierKey_arr], + [[{ keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '0', modifier: '0', outchar: 'ˆ' }], [{ actionId: 'A_0', key: 'K_SPACE', behaviour: '0', modifier: 'NCAPS', outchar: 'ˆ' }]], + [[{ keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '0', modifier: '', outchar: 'ˆ' }], [{ actionId: 'A_0', key: 'K_SPACE', behaviour: '0', modifier: 'NCAPS', outchar: 'ˆ' }]], + [[{ keyCode: '49', key: 'K_SPACE', actionId: '', behaviour: '0', modifier: '0', outchar: 'ˆ' }], [{ actionId: '', key: 'K_SPACE', behaviour: '0', modifier: 'NCAPS', outchar: 'ˆ' }]], + [[{ keyCode: '49', key: '', actionId: 'A_0', behaviour: '0', modifier: '0', outchar: 'ˆ' }], [{ actionId: 'A_0', key: '', behaviour: '0', modifier: 'NCAPS', outchar: 'ˆ' }]], + [[{ keyCode: '', key: 'K_SPACE', actionId: 'A_0', behaviour: '0', modifier: '0', outchar: 'ˆ' }], [{ actionId: 'A_0', key: 'K_SPACE', behaviour: '0', modifier: 'NCAPS', outchar: 'ˆ' }]], + [[{ keyCode: '', key: '', actionId: '', behaviour: '0', modifier: '', outchar: '' }], [{ actionId: '', key: '', behaviour: '0', modifier: 'NCAPS', outchar: '' }]], + ].forEach(function (values) { + const isCaps_used = true; + const string_in = "get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(['" + "', '" + "', '" + values[0][0].keyCode + "', '" + values[0][0].key + "', '" + values[0][0].actionId + "', '" + values[0][0].modifier + "', '" + values[0][0].outchar + "'])"; + const string_out = "['" + "', '" + "', '" + values[1][0].key + "', '" + values[1][0].actionId + "', '" + "', '" + values[1][0].modifier + "', '" + values[1][0].outchar + "']"; + + it((JSON.stringify(values[1]).length > 60) ? 'an array of objects should return an array of objects' : + string_in.padEnd(74, " ") + ' should return ' + string_out, async function () { + const result = sut.get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(read, values[0], isCaps_used); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); + + [[{ keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '0', modifier: '0', outchar: 'ˆ' }, { actionId: 'A_0', key: 'K_SPACE', behaviour: '0', modifier: '', outchar: 'ˆ' }], + [{ keyCode: '', key: 'K_SPACE', actionId: 'A_0', behaviour: '0', modifier: '0', outchar: 'ˆ' }, { actionId: 'A_0', key: 'K_SPACE', behaviour: '0', modifier: '', outchar: 'ˆ' }], + [{ keyCode: '', key: '', actionId: '', behaviour: '0', modifier: '', outchar: '' }, { actionId: '', key: '', behaviour: '0', modifier: '', outchar: '' }], + ].forEach(function (values) { + const isCaps_used = false; + const string_in = "get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array([ '" + values[0].keyCode + "', '" + values[0].key + "', '" + values[0].actionId + "', '" + values[0].modifier + "', '" + values[0].outchar + "'])"; + const string_out = "['" + values[1].actionId + "', '" + "', '" + values[1].modifier + "', '" + values[1].key + "', '" + values[1].outchar + "']"; + + it(string_in.padEnd(74, " ") + ' should return ' + string_out, async function () { + const result = sut.get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(read, [values[0]], isCaps_used); + assert.equal(JSON.stringify(result), JSON.stringify([values[1]])); + }); + }); + + [[[], []], + [undefined, []], + [null, []], + ].forEach(function (values) { + const isCaps = true; + it(("get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array([" + values[0] + "])").padEnd(74, " ") + ' should return ' + "[" + values[1] + "]", async function () { + const result = sut.get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(read, values[0], isCaps); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); + }); + describe('get_ActionStateOutput_array__From__ActionState ', function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sut_r = new KeylayoutFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/Test.keylayout'); + const read = sut_r.read(inputFilename); + + [['1', [ + { "id": "A_0", "state": "1", "output": "ˆ" }, + { "id": "A_1", "state": "1", "output": "Â" }, + { "id": "A_10", "state": "1", "output": "ê" }, + { "id": "A_11", "state": "1", "output": "î" }, + { "id": "A_13", "state": "1", "output": "ô" }, + { "id": "A_14", "state": "1", "output": "û" }, + { "id": "A_2", "state": "1", "output": "Ê" }, + { "id": "A_3", "state": "1", "output": "Î" }, + { "id": "A_5", "state": "1", "output": "Ô" }, + { "id": "A_6", "state": "1", "output": "Û" }, + { "id": "A_9", "state": "1", "output": "â" } + ],], + ['2', [ + { "id": "A_0", "state": "2", "output": "`" }, + { "id": "A_1", "state": "2", "output": "À" }, + { "id": "A_10", "state": "2", "output": "è" }, + { "id": "A_11", "state": "2", "output": "ì" }, + { "id": "A_13", "state": "2", "output": "ò" }, + { "id": "A_14", "state": "2", "output": "ù" }, + { "id": "A_2", "state": "2", "output": "È" }, + { "id": "A_3", "state": "2", "output": "Ì" }, + { "id": "A_5", "state": "2", "output": "Ò" }, + { "id": "A_6", "state": "2", "output": "Ù" }, + { "id": "A_9", "state": "2", "output": "à" } + ],], + ['789', [],], + ['', [],], + [' ', [],], + [123, [],], + [null, [],], + [undefined, [],], + ].forEach(function (values) { + it((JSON.stringify(values[1]).length > 30) ? + ("get_ActionStateOutput_array__From__ActionState('" + values[0] + "')").padEnd(60, " ") + ' should return an array of objects' : + ("get_ActionStateOutput_array__From__ActionState('" + values[0] + "')").padEnd(60, " ") + ' should return ' + "'" + JSON.stringify(values[1]) + "'", async function () { + const result = sut.get_ActionStateOutput_array__From__ActionState(read, String(values[0])); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); + }); + describe('get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput ', function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sut_r = new KeylayoutFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/Test.keylayout'); + const read = sut_r.read(inputFilename); + const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); + + [ + ['A_1', 'A', true, + [{ "outchar": "A", "actionId": "A_1", "behaviour": "1", "key": "K_A", "modifier": "CAPS" }, + { "outchar": "A", "actionId": "A_1", "behaviour": "2", "key": "K_A", "modifier": "NCAPS SHIFT" }, + { "outchar": "A", "actionId": "A_1", "behaviour": "2", "key": "K_A", "modifier": "SHIFT CAPS" }] + ], + ['A_1', 'A', false, + [{ "outchar": "A", "actionId": "A_1", "behaviour": "1", "key": "K_A", "modifier": "CAPS" }, + { "outchar": "A", "actionId": "A_1", "behaviour": "2", "key": "K_A", "modifier": "SHIFT" }, + { "outchar": "A", "actionId": "A_1", "behaviour": "2", "key": "K_A", "modifier": "SHIFT CAPS" }] + ], + ['A_9', 'a', true, [{ "outchar": "a", "actionId": "A_9", "behaviour": "0", "key": "K_A", "modifier": "NCAPS" }]], + ['A_9', 'a', false, [{ "outchar": "a", "actionId": "A_9", "behaviour": "0", "key": "K_A", "modifier": "" }]], + ['A_9', 'a', , [{ "outchar": "a", "actionId": "A_9", "behaviour": "0", "key": "K_A", "modifier": "" }]], + ['A_9', '', true, [{ "outchar": "", "actionId": "A_9", "behaviour": "0", "key": "K_A", "modifier": "NCAPS" }]], + ['A_9', '', false, [{ "outchar": "", "actionId": "A_9", "behaviour": "0", "key": "K_A", "modifier": "" }]], + ['', 'a', true, []], + ['', 'a', false, []], + ['', '', , []], + + ].forEach(function (values) { + it((JSON.stringify(values[3]).length > 35) ? + ("get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput('" + values[0] + "', '" + values[1] + "', " + values[2] + ")").padEnd(67, " ") + ' should return an array of objects' : + ("get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput('" + values[0] + "', '" + values[1] + "', " + values[2] + ")").padEnd(67, " ") + ' should return ' + "'" + JSON.stringify(values[3]) + "'", async function () { + const result = sut.get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput(read, converted.arrayOf_Modifiers, String(values[0]), String(values[1]), Boolean(values[2])); + assert.equal(JSON.stringify(result), JSON.stringify(values[3])); + }); + }); + }); + describe('get_KeyActionOutput_array__From__ActionStateOutput_array ', function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sut_r = new KeylayoutFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/Test.keylayout'); + const read = sut_r.read(inputFilename); + + const b6_actionId_arr: idStateOutput_object[] = [ + { "id": "A_0", "state": "1", "output": "ˆ" }, + { "id": "A_1", "state": "1", "output": "Â" }, + { "id": "A_10", "state": "1", "output": "ê" }, + { "id": "A_11", "state": "1", "output": "î" }, + { "id": "A_13", "state": "1", "output": "ô" }, + { "id": "A_14", "state": "1", "output": "û" }, + { "id": "A_2", "state": "1", "output": "Ê" }, + { "id": "A_3", "state": "1", "output": "Î" }, + { "id": "A_5", "state": "1", "output": "Ô" }, + { "id": "A_6", "state": "1", "output": "Û" }, + { "id": "A_9", "state": "1", "output": "â" } + ]; + + const b1_keycode_arr: allArrayContents_object[] = [ + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '0', outchar: 'ˆ' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '1', outchar: 'ˆ' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '2', outchar: 'ˆ' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '3', outchar: 'ˆ' }, + { keyCode: '6', key: 'K_Z', actionId: 'A_0', behaviour: '4', outchar: 'ˆ' }, + { keyCode: '25', key: 'K_9', actionId: 'A_0', behaviour: '4', outchar: 'ˆ' }, + { keyCode: '43', key: 'K_COMMA', actionId: 'A_0', behaviour: '4', outchar: 'ˆ' }, + { keyCode: '0', key: 'K_A', actionId: 'A_1', behaviour: '1', outchar: 'Â' }, + { keyCode: '0', key: 'K_A', actionId: 'A_1', behaviour: '2', outchar: 'Â' }, + { keyCode: '14', key: 'K_E', actionId: 'A_10', behaviour: '0', outchar: 'ê' }, + { keyCode: '34', key: 'K_I', actionId: 'A_11', behaviour: '0', outchar: 'î' }, + { keyCode: '31', key: 'K_O', actionId: 'A_13', behaviour: '0', outchar: 'ô' }, + { keyCode: '32', key: 'K_U', actionId: 'A_14', behaviour: '0', outchar: 'û' }, + { keyCode: '14', key: 'K_E', actionId: 'A_2', behaviour: '1', outchar: 'Ê' }, + { keyCode: '14', key: 'K_E', actionId: 'A_2', behaviour: '2', outchar: 'Ê' }, + { keyCode: '34', key: 'K_I', actionId: 'A_3', behaviour: '1', outchar: 'Î' }, + { keyCode: '34', key: 'K_I', actionId: 'A_3', behaviour: '2', outchar: 'Î' }, + { keyCode: '31', key: 'K_O', actionId: 'A_5', behaviour: '1', outchar: 'Ô' }, + { keyCode: '31', key: 'K_O', actionId: 'A_5', behaviour: '2', outchar: 'Ô' }, + { keyCode: '32', key: 'K_U', actionId: 'A_6', behaviour: '1', outchar: 'Û' }, + { keyCode: '32', key: 'K_U', actionId: 'A_6', behaviour: '2', outchar: 'Û' }, + { keyCode: '0', key: 'K_A', actionId: 'A_9', behaviour: '0', outchar: 'â' } + ]; + + [[b6_actionId_arr, b1_keycode_arr], + ].forEach(function (values) { + it(("get_KeyActionOutput_array__From__ActionStateOutput_array([['" + JSON.stringify(values[0]) + "'],..])").padEnd(73, " ") + '1 should return an array of objects', async function () { + const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0] as idStateOutput_object[]); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); + + const oneEntryResult = [ + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '0', outchar: 'ˆ' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '1', outchar: 'ˆ' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '2', outchar: 'ˆ' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '3', outchar: 'ˆ' }, + { keyCode: '6', key: 'K_Z', actionId: 'A_0', behaviour: '4', outchar: 'ˆ' }, + { keyCode: '25', key: 'K_9', actionId: 'A_0', behaviour: '4', outchar: 'ˆ' }, + { keyCode: '43', key: 'K_COMMA', actionId: 'A_0', behaviour: '4', outchar: 'ˆ' } + ]; + + const oneEntryResultNoOutput = [ + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '0', outchar: '' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '1', outchar: '' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '2', outchar: '' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '3', outchar: '' }, + { keyCode: '6', key: 'K_Z', actionId: 'A_0', behaviour: '4', outchar: '' }, + { keyCode: '25', key: 'K_9', actionId: 'A_0', behaviour: '4', outchar: '' }, + { keyCode: '43', key: 'K_COMMA', actionId: 'A_0', behaviour: '4', outchar: '' }, + ]; + + [[[{ "id": "A_0", "state": "1", "output": "ˆ" }], oneEntryResult], + [[{ "id": "A_0", "state": "1", "output": "" }], oneEntryResultNoOutput], + [[{ "id": "A_0", "state": "", "output": "ˆ" }], oneEntryResult], + ].forEach(function (values) { + it(("get_KeyActionOutput_array__From__ActionStateOutput_array(['" + JSON.stringify(values[0]) + "'])").padEnd(73, " ") + ' should return an array of objects', async function () { + const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0] as idStateOutput_object[]); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); + + [[[{ "id": "", "state": "1", "output": "ˆ" }], []], + [[{ "id": "", "state": "", "output": "" }], []], + [[{ "id": " ", "state": " ", "output": "" }], []], + + ].forEach(function (values) { + it(("get_KeyActionOutput_array__From__ActionStateOutput_array(" + JSON.stringify(values[0]) + ")").padEnd(73, " ") + ' should return ' + "'[" + JSON.stringify(values[1]) + "]'", async function () { + const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0] as idStateOutput_object[]); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); + + [[, []], + [undefined, []], + [null, []], + ].forEach(function (values) { + it(("get_KeyActionOutput_array__From__ActionStateOutput_array(" + JSON.stringify(values[0]) + ")").padEnd(73, " ") + ' should return ' + "'[" + JSON.stringify(values[1]) + "]'", async function () { + const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0] as idStateOutput_object[]); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); + }); -}); +}); \ No newline at end of file diff --git a/developer/src/kmc-convert/test/kmn-file-reader.tests.ts b/developer/src/kmc-convert/test/kmn-file-reader.tests.ts index 0229b487eb6..95f4c9de13a 100644 --- a/developer/src/kmc-convert/test/kmn-file-reader.tests.ts +++ b/developer/src/kmc-convert/test/kmn-file-reader.tests.ts @@ -9,9 +9,9 @@ import 'mocha'; import { assert } from 'chai'; +import { KeylayoutXMLSourceFile } from "@keymanapp/developer-utils" import { compilerTestCallbacks, makePathToFixture } from './helpers/index.js'; import { KeylayoutFileReader } from '../src/keylayout-to-kmn/keylayout-file-reader.js'; -import { KeylayoutXMLSourceFile } from "@keymanapp/developer-utils" describe('KeylayoutFileReader', function () { diff --git a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts index 65fbaf5029d..ad8a177bc27 100644 --- a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts +++ b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts @@ -10,11 +10,11 @@ import 'mocha'; import { assert } from 'chai'; import { util } from '@keymanapp/common-types'; +import KEYMAN_VERSION from "@keymanapp/keyman-version"; import { compilerTestCallbacks, compilerTestOptions, makePathToFixture } from './helpers/index.js'; import { KeylayoutToKmnConverter } from '../src/keylayout-to-kmn/keylayout-to-kmn-converter.js'; import { KmnFileWriter } from '../src/keylayout-to-kmn/kmn-file-writer.js'; import { KeylayoutFileReader } from '../src/keylayout-to-kmn/keylayout-file-reader.js'; -import KEYMAN_VERSION from "@keymanapp/keyman-version"; describe('KmnFileWriter', function () { From b729638216e6bd239b96b06cc3f2719d64b4ac6b Mon Sep 17 00:00:00 2001 From: Sabine Date: Sat, 9 Aug 2025 19:50:19 +0200 Subject: [PATCH 160/251] feat(developer): test for NCAPS-> NCAPS --- .../src/keylayout-to-kmn/keylayout-to-kmn-converter.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 8d335c5e652..08f782ac96c 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -117,7 +117,7 @@ export class KeylayoutToKmnConverter { outputFilename = outputFilename ?? inputFilename.replace(/\.keylayout$/, '.kmn'); const outArray: convert_object = await this.convert(jsonO, outputFilename); - if (!outArray) { + if (outArray.arrayOf_Rules.length === 0) { this.callbacks.reportMessage(ConverterMessages.Error_UnableToConvert({ inputFilename })); return null; } @@ -625,7 +625,7 @@ export class KeylayoutToKmnConverter { else if (!isCAPSused && (modifier_state[i].toUpperCase().includes('CAPS?'))) { add_modifier = ""; } - else if (modifier_state[i].toUpperCase().includes('CAPS')) { + else if ((modifier_state[i].toUpperCase().includes('CAPS') && (!(modifier_state[i].toUpperCase().includes('NCAPS'))))) { add_modifier = "CAPS "; } else if (isCAPSused && (modifier_state[i].toUpperCase().includes('NCAPS'))) { From 84ac9c01a3b5ee85004510de50afb493e1ea2a15 Mon Sep 17 00:00:00 2001 From: Sabine Date: Tue, 12 Aug 2025 20:13:10 +0200 Subject: [PATCH 161/251] feat(developer): tests for kmn-file-writer --- .../src/keylayout-to-kmn/kmn-file-writer.ts | 51 ++-- .../kmc-convert/test/data/Test_C2.keylayout | 4 +- .../kmc-convert/test/data/Test_C3.keylayout | 34 ++- .../test/data/Test_C3_several.keylayout | 54 +--- .../test/data/Test_maxKeyCode.keylayout | 1 + .../test/keylayout-to-kmn-converter.tests.ts | 2 + .../kmc-convert/test/kmn-file-writer.tests.ts | 246 +++++++++++++++++- 7 files changed, 300 insertions(+), 92 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts index e43db3d426e..c99e1dbdd08 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts @@ -460,13 +460,6 @@ export class KmnFileWriter { + "] > dk(A" + rule[index].id_prev_deadkey + ") ) : "; - - warningTextArray[2] = "unavailable superior rule ( [" - + rule[index].modifier_deadkey + " " - + rule[index].deadkey - + "] > dk(A" - + rule[index].id_deadkey - + ") ) : "; } if (!keylayoutKmnConverter.isAcceptableKeymanModifier(rule[index].modifier_deadkey)) { @@ -474,7 +467,7 @@ export class KmnFileWriter { warningTextArray[2] = "unavailable superior rule ( [" + rule[index].modifier_deadkey + " " + rule[index].deadkey - + "] > dk(A" + + "] > dk(B" + rule[index].id_deadkey + ") ) : "; } @@ -500,7 +493,6 @@ export class KmnFileWriter { && new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output) && idx < index ); - // 1-1: + [CAPS K_N] > 'N' <-> + [CAPS K_N] > 'N' const dup_1_1 = rule.filter((curr, idx) => (curr.rule_type === "C0" || curr.rule_type === "C1") @@ -730,23 +722,27 @@ export class KmnFileWriter { ); // 5-5 dk(C1) + [SHIFT CAPS K_A] > dk(C2) <-> dk(C1) + [SHIFT CAPS K_A] > dk(C3) - const amb_5_5 = rule.filter((curr, idx) => + const amb_5_5 = rule.filter((curr, idx) => ( (curr.rule_type === "C3") - && curr.modifier_key === rule[index].modifier_key - && curr.key === rule[index].key - && curr.id_deadkey === rule[index].id_deadkey - && (new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output)) + && curr.id_prev_deadkey === rule[index].id_prev_deadkey + && curr.modifier_deadkey === rule[index].modifier_deadkey + && curr.deadkey === rule[index].deadkey + && curr.id_deadkey === rule[index].id_deadkey) && idx < index + && (rule[index].unique_deadkey !== 0 || rule[index].unique_prev_deadkey !== 0) ); // 5-5 dk(C1) + [SHIFT CAPS K_A] > dk(C2) <-> dk(C1) + [SHIFT CAPS K_A] > dk(C2) const dup_5_5 = rule.filter((curr, idx) => (curr.rule_type === "C3") + && curr.id_prev_deadkey === rule[index].id_prev_deadkey + && curr.modifier_prev_deadkey === rule[index].modifier_prev_deadkey + && curr.prev_deadkey === rule[index].prev_deadkey && curr.modifier_deadkey === rule[index].modifier_deadkey && curr.deadkey === rule[index].deadkey - && curr.id_prev_deadkey === rule[index].id_prev_deadkey && curr.id_deadkey === rule[index].id_deadkey && rule[index].unique_deadkey === 0 + && idx < index ); // 6-6 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'B' @@ -760,14 +756,15 @@ export class KmnFileWriter { ); // 6-6 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'Ã' - const dup_6_6 = rule.filter((curr, idx) => - (curr.rule_type === "C3") - && curr.id_deadkey === rule[index].id_deadkey - && curr.modifier_key === rule[index].modifier_key - && curr.key === rule[index].key - && (new TextDecoder().decode(curr.output) === new TextDecoder().decode(rule[index].output)) - && idx < index - ); + const dup_6_6 = + rule.filter((curr, idx) => + (curr.rule_type === "C3") + && curr.id_deadkey === rule[index].id_deadkey + && curr.modifier_key === rule[index].modifier_key + && curr.key === rule[index].key + && (new TextDecoder().decode(curr.output) === new TextDecoder().decode(rule[index].output)) + && idx < index + ); if (amb_2_4.length > 0) { warningTextArray[0] = warningTextArray[0] @@ -880,7 +877,13 @@ export class KmnFileWriter { + "\' "); } } - // In rare cases a rule might not be written out therefore we need to inform the user + // In rare cases a rule might not be written out therefore we need to inform the user: + // usually we write the first occurance of an ambiguous C0/C1 rule and comment out the later + // assuming that if several C0/C1 rules are ambiguous the user prefers to use the first C0/C1 rule + // for C2/C3 rules we write the last occurance of an ambiguous rule and comment out the earlier + // assuming that if a C0/C1 and a C2/C3 rule is ambiguous the user prefers to use the C2/C3 rule over the C0/C1 rule + // if both happens, nothing would be written, therefore this messsage + const extra_warning = "PLEASE CHECK THE FOLLOWING RULE AS IT WILL NOT BE WRITTEN ! "; if (warningTextArray[0] !== "") { diff --git a/developer/src/kmc-convert/test/data/Test_C2.keylayout b/developer/src/kmc-convert/test/data/Test_C2.keylayout index ca6c1940a9d..aa6b60997bc 100644 --- a/developer/src/kmc-convert/test/data/Test_C2.keylayout +++ b/developer/src/kmc-convert/test/data/Test_C2.keylayout @@ -18,12 +18,12 @@ - + - + diff --git a/developer/src/kmc-convert/test/data/Test_C3.keylayout b/developer/src/kmc-convert/test/data/Test_C3.keylayout index 32c294256d9..6275a230bbf 100644 --- a/developer/src/kmc-convert/test/data/Test_C3.keylayout +++ b/developer/src/kmc-convert/test/data/Test_C3.keylayout @@ -12,43 +12,41 @@ + + + + - - - - + - + - - + + - - - + + - - - - + - - + + - - + + + diff --git a/developer/src/kmc-convert/test/data/Test_C3_several.keylayout b/developer/src/kmc-convert/test/data/Test_C3_several.keylayout index 1d3384be84f..bdacf29ac5c 100644 --- a/developer/src/kmc-convert/test/data/Test_C3_several.keylayout +++ b/developer/src/kmc-convert/test/data/Test_C3_several.keylayout @@ -6,38 +6,9 @@ Generated by S. Schmitt - tests multiple C3 rules - -This example will produce the following rules - character â will be produced by the several combinations: -+ [SHIFT CAPS K_A] >'A' -+ [CAPS K_A] >'A' -+ [CAPS RALT K_A] >'A' -+ [NCAPS K_U] >'u' -+ [CAPS K_8] >dk(A5) dk(A5) + [SHIFT CAPS K_8] >dk(B1) dk(B1) + [NCAPS K_A] >'â' -+ [CAPS K_8] >dk(A5) dk(A5) + [SHIFT CAPS K_U] >dk(B2) dk(B2) + [NCAPS K_A] >'â' -+ [CAPS K_8] >dk(A5) dk(A5) + [NCAPS RALT K_8] >dk(B6) dk(B6) + [NCAPS K_A] >'â' -+ [CAPS K_8] >dk(A5) dk(A5) + [NCAPS RALT K_U] >dk(B4) dk(B4) + [NCAPS K_A] >'â' -+ [NCAPS RALT K_8] >dk(A6) dk(A6) + [SHIFT CAPS K_8] >dk(B1) dk(B1) + [NCAPS K_A] >'â' -+ [CAPS RALT K_8] >dk(A7) dk(A7) + [SHIFT CAPS K_8] >dk(B1) dk(B1) + [NCAPS K_A] >'â' - - -In kmn files duplicates would not be written therefore it will be (for readability not each rule in a seperate line here): -+ [SHIFT CAPS K_A] >'A' -+ [CAPS K_A] >'A' -+ [CAPS RALT K_A] >'A' -+ [NCAPS K_U] >'u' -+ [CAPS K_8] >dk(A5) dk(A5) + [SHIFT CAPS K_8] >dk(B1) dk(B1) + [NCAPS K_A] >'â' - dk(A5) + [SHIFT CAPS K_U] >dk(B2) dk(B2) + [NCAPS K_A] >'â' - dk(A5) + [NCAPS RALT K_8] >dk(B6) dk(B6) + [NCAPS K_A] >'â' - dk(A5) + [NCAPS RALT K_U] >dk(B4) dk(B4) + [NCAPS K_A] >'â' -+ [NCAPS RALT K_8] >dk(A6) dk(A6) + [SHIFT CAPS K_8] >dk(B1) -+ [CAPS RALT K_8] >dk(A7) dk(A7) + [SHIFT CAPS K_8] >dk(B1) - - - + tests C3 rules --> - - + @@ -45,39 +16,25 @@ In kmn files duplicates would not be written therefore it will be (for readabili - - - - - - - - - - - + - - - - @@ -87,11 +44,14 @@ In kmn files duplicates would not be written therefore it will be (for readabili - + + + + diff --git a/developer/src/kmc-convert/test/data/Test_maxKeyCode.keylayout b/developer/src/kmc-convert/test/data/Test_maxKeyCode.keylayout index 60ff92dd425..a5f9e178b99 100644 --- a/developer/src/kmc-convert/test/data/Test_maxKeyCode.keylayout +++ b/developer/src/kmc-convert/test/data/Test_maxKeyCode.keylayout @@ -24,6 +24,7 @@ + diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index 9ce3a7768c5..f89c8a302a0 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -55,6 +55,8 @@ describe('KeylayoutToKmnConverter', function () { [makePathToFixture('../data/Test_C0_C1_C2_C3.keylayout')], [makePathToFixture('../data/Test_maxKeyCode.keylayout')], [makePathToFixture('../data/Test_messages.keylayout')], + [makePathToFixture('../data/Test_messages_superior_C2.keylayout')], + [makePathToFixture('../data/Test_messages_superior_C3.keylayout')], [makePathToFixture('../data/Test_duplicate_missing_keycode.keylayout')], [makePathToFixture('../data/Test_modifier.keylayout')], [makePathToFixture('../data/Test_modifierNoCaps.keylayout')], diff --git a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts index ad8a177bc27..bf7acd4b648 100644 --- a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts +++ b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts @@ -12,7 +12,7 @@ import { assert } from 'chai'; import { util } from '@keymanapp/common-types'; import KEYMAN_VERSION from "@keymanapp/keyman-version"; import { compilerTestCallbacks, compilerTestOptions, makePathToFixture } from './helpers/index.js'; -import { KeylayoutToKmnConverter } from '../src/keylayout-to-kmn/keylayout-to-kmn-converter.js'; +import { KeylayoutToKmnConverter, Rule } from '../src/keylayout-to-kmn/keylayout-to-kmn-converter.js'; import { KmnFileWriter } from '../src/keylayout-to-kmn/kmn-file-writer.js'; import { KeylayoutFileReader } from '../src/keylayout-to-kmn/keylayout-file-reader.js'; @@ -261,4 +261,248 @@ describe('KmnFileWriter', function () { }); }); }); + + describe('reviewRules messages', function () { + const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); + + [ + [[new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'UNAVAILABLE', 'K_A', new TextEncoder().encode('A'))], + [''], + [''], + ['c WARNING: unavailable modifier : here: ']], + + [[new Rule("C1", '', '', 0, 0, 'CAPS', 'K_EQUAL', 0, 0, 'UNAVAILABLE', 'K_B', new TextEncoder().encode('B'))], + [''], + [''], + ['c WARNING: unavailable modifier : here: ']], + + [[new Rule("C2", '', '', 0, 0, 'CAPS', 'K_EQUAL', 0, 0, 'UNAVAILABLE', 'K_C', new TextEncoder().encode('C'),)], + [''], + [''], + ['c WARNING: unavailable modifier : here: ']], + + [[new Rule("C2", '', '', 0, 0, 'UNAVAILABLE_dk', 'K_EQUAL', 0, 0, 'UNAVAILABLE', 'K_C', new TextEncoder().encode('C'),)], + [''], + ['c WARNING: unavailable modifier : here: '], + ['c WARNING: unavailable modifier : here: ']], + + [[new Rule("C3", 'UNAVAILABLE_prev_dk', 'K_D', 0, 0, 'UNAVAILABLE_dk', 'K_EQUAL', 0, 0, 'SHIFT', 'K_C', new TextEncoder().encode('D'),)], + ['c WARNING: unavailable modifier : here: '], + ['c WARNING: unavailable modifier : here: '], + ['c WARNING: unavailable superior rule ( [UNAVAILABLE_dk K_EQUAL] > dk(B0) ) : here: ']], + + [[new Rule("C3", 'UNAVAILABLE_prev_dk', 'K_D', 0, 0, 'UNAVAILABLE_dk', 'K_EQUAL', 0, 0, 'UNAVAIL', 'K_C', new TextEncoder().encode('D'),)], + ['c WARNING: unavailable modifier : here: '], + ['c WARNING: unavailable modifier : here: '], + ['c WARNING: unavailable modifier : here: ']], + + [[new Rule("C3", 'CAPS', 'K_D', 0, 0, 'RALT', 'K_EQUAL', 0, 0, 'SHIFT', 'K_C', new TextEncoder().encode('D'),)], + [''], + [''], + ['']], + + [[new Rule("C3", 'X', 'K_X', 0, 0, 'Y', 'K_Y', 0, 0, 'SHIFT', 'K_Z', new TextEncoder().encode('D'),)], + ['c WARNING: unavailable modifier : here: '], + ['c WARNING: unavailable modifier : here: '], + ['c WARNING: unavailable superior rule ( [Y K_Y] > dk(B0) ) : here: ']], + + ].forEach(function (values: any, index: number) { + it(('rule " ' + values[0][0].rule_type + ' "') + 'should create "' + values[1] + ' | ' + values[2] + ' | ' + values[3] + '"', async function () { + const result: string[] = sut_w.reviewRules(values[0], 0); + assert.equal(result[0], values[1][0]); + assert.equal(result[1], values[2][0]); + assert.equal(result[2], values[3][0]); + }); + }); + }); + + describe('reviewRules messages duplicate and ambiguous', function () { + + const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); + [ + //all + [[ + new Rule("C3", 'LALT', 'K_A', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), + new Rule("C3", 'LALT', 'K_A', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')),], + ['c WARNING: duplicate rule: earlier: [LALT K_A] > dk(C0) here: '], + ["c WARNING: duplicate rule: earlier: dk(B0) + [SHIFT K_B] > dk(B0) here: "], + ["c WARNING: duplicate rule: earlier: dk(B0) + [CAPS K_C] > 'X' here: "]], + + //6-6 dup + [[ + new Rule("C3", 'LALT', 'K_A', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), + new Rule("C3", 'CTRL', 'K_D', 0, 0, 'NCAPS', 'K_E', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')),], + [''], + [""], + ["c WARNING: duplicate rule: earlier: dk(B0) + [CAPS K_C] > 'X' here: "]], + + //6-6 amb + [[ + new Rule("C3", 'LALT', 'K_A', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), + new Rule("C3", 'CTRL', 'K_D', 0, 0, 'NCAPS', 'K_E', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('Y')),], + [''], + [""], + ["c WARNING: ambiguous rule: earlier: dk(B0) + [CAPS K_C] > 'X' here: "]], + + // 5-5 amb + [[ + new Rule("C3", 'LALT', 'K_A', 0, 0, 'NCAPS', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), + new Rule("C3", 'LALT', 'K_A', 0, 0, 'NCAPS', 'K_B', 0, 1, 'RALT', 'K_F', new TextEncoder().encode('X')),], + ['c WARNING: duplicate rule: earlier: [LALT K_A] > dk(C0) here: '], + ["c WARNING: ambiguous rule: earlier: dk(B0) + [NCAPS K_B] > dk(B0) here: "], [''], + ], + + // 5-5 dup + [[ + new Rule("C3", 'LALT', 'K_A', 0, 0, 'NCAPS', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), + new Rule("C3", 'LALT', 'K_A', 0, 0, 'NCAPS', 'K_B', 0, 0, 'RALT', 'K_F', new TextEncoder().encode('X')),], + ['c WARNING: duplicate rule: earlier: [LALT K_A] > dk(C0) here: '], + ["c WARNING: duplicate rule: earlier: dk(B0) + [NCAPS K_B] > dk(B0) here: "], + ['']], + + // 4-2 amb + [[ + new Rule("C3", 'LALT', 'K_A', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), + new Rule("C2", '', '', 0, 0, 'LALT', 'K_A', 0, 0, 'RALT', 'K_F', new TextEncoder().encode('X')),], + ['c WARNING: ambiguous rule: later: [LALT K_A] > dk(C0) here: '], + [''], + ['']], + + // 4-4 amb + [[ + new Rule("C3", 'LALT', 'K_A', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), + new Rule("C3", 'LALT', 'K_A', 1, 1, 'NCAPS', 'K_E', 0, 0, 'RALT', 'K_F', new TextEncoder().encode('Y')),], + ['c WARNING: ambiguous rule: earlier: [LALT K_A] > dk(C0) here: '], + [""], + [''],], + + // 4-4 dup + [[ + new Rule("C3", 'LALT', 'K_A', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), + new Rule("C3", 'LALT', 'K_A', 0, 0, 'NCAPS', 'K_E', 0, 0, 'RALT', 'K_F', new TextEncoder().encode('X')),], + ['c WARNING: duplicate rule: earlier: [LALT K_A] > dk(C0) here: '], + [''], + ['']], + + // 4-2 amb + [[ + new Rule("C3", 'LALT', 'K_A', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), + new Rule("C2", '', '', 0, 0, 'LALT', 'K_A', 0, 0, 'RALT', 'K_F', new TextEncoder().encode('Y')),], + ['c WARNING: ambiguous rule: later: [LALT K_A] > dk(C0) here: '], + [''], + ['']], + + // 6-3 dup + [[ + new Rule("C2", '', '', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), + new Rule("C3", 'CTRL', 'K_D', 0, 0, 'NCAPS', 'K_E', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')),], + [''], + ["c WARNING: duplicate rule: earlier: dk(C0) + [CAPS K_C] > 'X' here: "], + [''],], + + // 6-3 amb + [[ + new Rule("C2", '', '', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), + new Rule("C3", 'CTRL', 'K_D', 0, 0, 'NCAPS', 'K_E', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('Y')),], + [''], + ["c WARNING: ambiguous rule: earlier: dk(C0) + [CAPS K_C] > 'X' here: "], + [''],], + + // 2-4 amb + [[ + new Rule("C2", '', '', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), + new Rule("C3", 'SHIFT', 'K_B', 0, 0, 'NCAPS', 'K_E', 0, 0, 'RALT', 'K_F', new TextEncoder().encode('Y')),], + ['c WARNING: ambiguous rule: earlier: [SHIFT K_B] > dk(A0) here: '], + [''], + ['']], + + //2-2 amb + [[ + new Rule("C2", '', '', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), + new Rule("C2", '', '', 0, 0, 'SHIFT', 'K_B', 1, 1, 'RALT', 'K_F', new TextEncoder().encode('Y')),], + [''], + ['c WARNING: ambiguous rule: earlier: [SHIFT K_B] > dk(C0) here: '], + ['']], + + // 2-2 dup + [[ + new Rule("C2", '', '', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), + new Rule("C2", '', '', 0, 0, 'SHIFT', 'K_B', 0, 0, 'RALT', 'K_F', new TextEncoder().encode('Y')),], + [''], + ['c WARNING: duplicate rule: earlier: [SHIFT K_B] > dk(C0) here: '], + ['']], + + // 3-3 dup + [[ + new Rule("C2", '', '', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), + new Rule("C2", '', '', 0, 0, 'NCAPS', 'K_E', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')),], + [''], + [''], + ["c WARNING: duplicate rule: earlier: dk(A0) + [CAPS K_C] > 'X' here: "]], + + // 3-3 amb + [[ + new Rule("C2", '', '', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), + new Rule("C2", '', '', 0, 0, 'NCAPS', 'K_E', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('Y')),], + [''], + [''], + ["c WARNING: ambiguous rule: earlier: dk(A0) + [CAPS K_C] > 'X' here: "]], + + // 2-1 amb + [[ + new Rule("C2", '', '', 0, 0, 'RALT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), + new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'RALT', 'K_B', new TextEncoder().encode('Y'))], + [''], + [''], + ['c WARNING: ambiguous rule: later: [RALT K_B] > dk(A0) here: ']], + + // 1-1 amb + [[ + new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), + new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('Y'))], + [''], + [''], + ["c WARNING: ambiguous rule: earlier: [CAPS K_C] > 'X' here: "]], + + // 1-1 amb + [[ + new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), + new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X'))], + [''], + [''], + ["c WARNING: duplicate rule: earlier: [CAPS K_C] > 'X' here: "]], + + ].forEach(function (values: any, index: number) { + it('rule ' + values[0][0].rule_type + ' should create " ' + ' "' + values[1] + ' | ' + values[2] + ' | ' + values[3] + '"', async function () { + const result: string[] = sut_w.reviewRules(values[0], 1); + assert.equal(result[0], values[1][0]); + assert.equal(result[1], values[2][0]); + assert.equal(result[2], values[3][0]); + }); + }); + }); + + describe('reviewRules messages duplicate and ambiguous with Extra warning', function () { + const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); + [[[ + new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'RALT', 'K_B', new TextEncoder().encode('X')), + new Rule("C2", '', '', 0, 0, 'RALT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('Y')), + new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'RALT', 'K_B', new TextEncoder().encode('Z')) + ], + [''], + [''], + ["c WARNING: ambiguous rule: later: [RALT K_B] > dk(A0) ambiguous rule: earlier: [RALT K_B] > 'X' here: PLEASE CHECK THE FOLLOWING RULE AS IT WILL NOT BE WRITTEN ! "]], + ].forEach(function (values: any, index: number) { + it(('rule ' + values[0][0].rule_type + ' should create " ' + ' "') + values[1] + ' | ' + values[2] + ' | ' + values[3] + '"', async function () { + const result: string[] = sut_w.reviewRules(values[0], 2); + assert.equal(result[0], values[1][0]); + assert.equal(result[1], values[2][0]); + assert.equal(result[2], values[3][0]); + }); + }); + }); + + + + }); From 73a0e481766a2882ddd75f21d2505a493d682e26 Mon Sep 17 00:00:00 2001 From: Sabine Date: Tue, 12 Aug 2025 21:57:05 +0200 Subject: [PATCH 162/251] feat(developer): add testfiles --- .../data/Test_messages_superior_C2.keylayout | 72 +++++++++++++++++++ .../data/Test_messages_superior_C3.keylayout | 59 +++++++++++++++ 2 files changed, 131 insertions(+) create mode 100644 developer/src/kmc-convert/test/data/Test_messages_superior_C2.keylayout create mode 100644 developer/src/kmc-convert/test/data/Test_messages_superior_C3.keylayout diff --git a/developer/src/kmc-convert/test/data/Test_messages_superior_C2.keylayout b/developer/src/kmc-convert/test/data/Test_messages_superior_C2.keylayout new file mode 100644 index 00000000000..3416bb5e8ff --- /dev/null +++ b/developer/src/kmc-convert/test/data/Test_messages_superior_C2.keylayout @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/Test_messages_superior_C3.keylayout b/developer/src/kmc-convert/test/data/Test_messages_superior_C3.keylayout new file mode 100644 index 00000000000..f95afe40db5 --- /dev/null +++ b/developer/src/kmc-convert/test/data/Test_messages_superior_C3.keylayout @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 0291997f03363c25cf5549c2b627c84d6b97105a Mon Sep 17 00:00:00 2001 From: Sabine Date: Tue, 12 Aug 2025 21:57:05 +0200 Subject: [PATCH 163/251] feat(developer):output of message re control character in C2, C3 rules --- .../src/keylayout-to-kmn/kmn-file-writer.ts | 8 +-- .../test/data/Test_C0_C1_C2_C3.keylayout | 26 +++---- .../Test_messages_controlCharacter.keylayout | 57 +++++++++++++++ .../data/Test_messages_superior_C2.keylayout | 72 +++++++++++++++++++ .../data/Test_messages_superior_C3.keylayout | 59 +++++++++++++++ .../test/keylayout-to-kmn-converter.tests.ts | 1 + 6 files changed, 206 insertions(+), 17 deletions(-) create mode 100644 developer/src/kmc-convert/test/data/Test_messages_controlCharacter.keylayout create mode 100644 developer/src/kmc-convert/test/data/Test_messages_superior_C2.keylayout create mode 100644 developer/src/kmc-convert/test/data/Test_messages_superior_C3.keylayout diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts index c99e1dbdd08..459231e085b 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts @@ -244,9 +244,9 @@ export class KmnFileWriter { if ((output_Unicode_Character !== undefined) && (output_Unicode_CodePoint !== undefined)) { // if we are about to print a unicode codepoint instead of a single character we need to check if it is a control character - if (Number("0x" + output_Unicode_Character.substring(2, output_Unicode_Character.length)) < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER) { + if (Number("0x" + output_Unicode_CodePoint.substring(2, output_Unicode_CodePoint.length)) < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER) { version_output_character = output_Unicode_CodePoint; - if (output_Unicode_Character.length > 1) { + if (output_Unicode_CodePoint.length > 1) { if (warn_text[2] == "") { warn_text[2] = warn_text[2] + "c WARNING: use of a control character "; } @@ -330,11 +330,11 @@ export class KmnFileWriter { if ((output_Unicode_Character !== undefined) && (output_Unicode_CodePoint !== undefined)) { // if we are about to print a unicode codepoint instead of a single character we need to check if a control character is to be used - if (Number("0x" + output_Unicode_Character.substring(2, output_Unicode_Character.length)) < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER) { + if (Number("0x" + output_Unicode_CodePoint.substring(2, output_Unicode_CodePoint.length)) < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER) { version_output_character = output_Unicode_CodePoint; - if (output_Unicode_Character.length > 1) { + if (output_Unicode_CodePoint.length > 1) { if (warn_text[2] == "") { warn_text[2] = warn_text[2] + "c WARNING: use of a control character "; } diff --git a/developer/src/kmc-convert/test/data/Test_C0_C1_C2_C3.keylayout b/developer/src/kmc-convert/test/data/Test_C0_C1_C2_C3.keylayout index f5e7ab06468..f1f3ebab1e5 100644 --- a/developer/src/kmc-convert/test/data/Test_C0_C1_C2_C3.keylayout +++ b/developer/src/kmc-convert/test/data/Test_C0_C1_C2_C3.keylayout @@ -23,33 +23,33 @@ - - - - + + + + - - - + + + - + - - + + - + - + - + diff --git a/developer/src/kmc-convert/test/data/Test_messages_controlCharacter.keylayout b/developer/src/kmc-convert/test/data/Test_messages_controlCharacter.keylayout new file mode 100644 index 00000000000..f97abb984d2 --- /dev/null +++ b/developer/src/kmc-convert/test/data/Test_messages_controlCharacter.keylayout @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/Test_messages_superior_C2.keylayout b/developer/src/kmc-convert/test/data/Test_messages_superior_C2.keylayout new file mode 100644 index 00000000000..3416bb5e8ff --- /dev/null +++ b/developer/src/kmc-convert/test/data/Test_messages_superior_C2.keylayout @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/Test_messages_superior_C3.keylayout b/developer/src/kmc-convert/test/data/Test_messages_superior_C3.keylayout new file mode 100644 index 00000000000..f95afe40db5 --- /dev/null +++ b/developer/src/kmc-convert/test/data/Test_messages_superior_C3.keylayout @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index f89c8a302a0..26cb6adf46d 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -55,6 +55,7 @@ describe('KeylayoutToKmnConverter', function () { [makePathToFixture('../data/Test_C0_C1_C2_C3.keylayout')], [makePathToFixture('../data/Test_maxKeyCode.keylayout')], [makePathToFixture('../data/Test_messages.keylayout')], + [makePathToFixture('../data/Test_messages_controlCharacter.keylayout')], [makePathToFixture('../data/Test_messages_superior_C2.keylayout')], [makePathToFixture('../data/Test_messages_superior_C3.keylayout')], [makePathToFixture('../data/Test_duplicate_missing_keycode.keylayout')], From ff9b70ba0ab6b0b9c2beb924d304b69f036fe834 Mon Sep 17 00:00:00 2001 From: Sabine Date: Wed, 13 Aug 2025 12:46:04 +0200 Subject: [PATCH 164/251] feat(developer): kmc-convert nits from review: typo and Layout of ErrorMessages --- .../src/kmc-convert/src/converter-messages.ts | 24 ++++++++++++++----- .../kmc-convert/test/kmn-file-writer.tests.ts | 2 +- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/developer/src/kmc-convert/src/converter-messages.ts b/developer/src/kmc-convert/src/converter-messages.ts index 42b3bb825e0..f717f4dfdec 100644 --- a/developer/src/kmc-convert/src/converter-messages.ts +++ b/developer/src/kmc-convert/src/converter-messages.ts @@ -23,26 +23,38 @@ export class ConverterMessages { static ERROR_NoConverterFound = SevError | 0x0002; static Error_NoConverterFound = (o: { inputFilename: string, outputFilename: string; }) => m( - this.ERROR_NoConverterFound, `No converter is available that can convert from '${def(o.inputFilename)}' to '${def(o.outputFilename)}'.`); + this.ERROR_NoConverterFound, + `No converter is available that can convert from '${def(o.inputFilename)}' to '${def(o.outputFilename)}'.`, + ); static ERROR_FileNotFound = SevError | 0x0003; static Error_FileNotFound = (o: { inputFilename: string; }) => m( - this.ERROR_FileNotFound, `Input filename '${def(o.inputFilename)} ' does not exist or could not be loaded.`); + this.ERROR_FileNotFound, + `Input filename '${def(o.inputFilename)} ' does not exist or could not be loaded.`, + ); static ERROR_UnableToRead = SevError | 0x0004; static Error_UnableToRead = (o: { inputFilename: string; }) => m( - this.ERROR_UnableToRead, `Input file '${def(o.inputFilename)} ' could not be read.`); + this.ERROR_UnableToRead, + `Input file '${def(o.inputFilename)} ' could not be read.`, + ); static ERROR_UnableToConvert = SevError | 0x0005; static Error_UnableToConvert = (o: { inputFilename: string; }) => m( - this.ERROR_UnableToConvert, `Input file '${def(o.inputFilename)} ' could not be converted.`); + this.ERROR_UnableToConvert, + `Input file '${def(o.inputFilename)} ' could not be converted.`, + ); static ERROR_UnableToWrite = SevError | 0x0006; static Error_UnableToWrite = (o: { outputFilename: string; }) => m( - this.ERROR_UnableToWrite, `Output file for '${def(o.outputFilename)} ' could not be written.`); + this.ERROR_UnableToWrite, + `Output file for '${def(o.outputFilename)} ' could not be written.`, + ); static ERROR_UnsupportedCharactersDetected = SevError | 0x0007; static Error_UnsupportedCharactersDetected = (o: { inputFilename: string, keymap_index: string, key: string, output: string; }) => m( - this.ERROR_UnsupportedCharactersDetected, `Input file ${def(o.inputFilename)} contains unsupported character ('${def(o.output)}') on key (${def(o.key)}) at keyMap index ${def(o.keymap_index)}`); + this.ERROR_UnsupportedCharactersDetected, + `Input file ${def(o.inputFilename)} contains unsupported character ('${def(o.output)}') on key ( ${def(o.key)}) at keyMap index ${def(o.keymap_index)}`, + ); } diff --git a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts index 72113a17ae2..64dc832448d 100644 --- a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts +++ b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts @@ -22,7 +22,7 @@ describe('KmnFileWriter', function () { compilerTestCallbacks.clear(); }); - describe("writeToFile()() ", function () { + describe("writeToFile() ", function () { const inputFilename = makePathToFixture('../data/Test.keylayout'); const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); From 12b17e45ee6e352cc9f7cf14f6931627e482619b Mon Sep 17 00:00:00 2001 From: Sabine Date: Thu, 14 Aug 2025 13:38:07 +0200 Subject: [PATCH 165/251] feat(developer): add tests for lower-level functions --- .../src/kmc-convert/src/converter-messages.ts | 10 +- .../keylayout-to-kmn-converter.ts | 176 +++++++++--------- .../src/keylayout-to-kmn/kmn-file-writer.ts | 12 +- .../test/data/Test_C3_several.keylayout | 2 +- .../test/keylayout-to-kmn-converter.tests.ts | 110 +++++++++-- .../kmc-convert/test/kmn-file-writer.tests.ts | 118 +++++++++++- 6 files changed, 305 insertions(+), 123 deletions(-) diff --git a/developer/src/kmc-convert/src/converter-messages.ts b/developer/src/kmc-convert/src/converter-messages.ts index 460704c41bc..8e22f4d49ec 100644 --- a/developer/src/kmc-convert/src/converter-messages.ts +++ b/developer/src/kmc-convert/src/converter-messages.ts @@ -52,13 +52,13 @@ export class ConverterMessages { ' could not be written.` ); - static ERROR_InvalidFile = SevError | 0x0008; - static Error_InvalidFile = (o: { errorText: string; }) => m( - this.ERROR_InvalidFile, `The source file has an invalid structure: ${def(o.errorText)}` - ); - static INFO_UnsupportedCharactersDetected = SevInfo | 0x0007; static Info_UnsupportedCharactersDetected = (o: { inputFilename: string, keymap_index: string, key: string,KeyName:string, output: string; }) => m( this.INFO_UnsupportedCharactersDetected, `INFO: Input file ${def(o.inputFilename)} contains unsupported character '${def(o.output)}' at keyMap index ${def(o.keymap_index)} on Keycode ${def(o.key)} (${def(o.KeyName)})` ); + + static ERROR_InvalidFile = SevError | 0x0008; + static Error_InvalidFile = (o: { errorText: string; }) => m( + this.ERROR_InvalidFile, `The source file has an invalid structure: ${def(o.errorText)}` + ); } diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 08f782ac96c..49be9e039ef 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -20,14 +20,14 @@ import { KeylayoutXMLSourceFile } from '@keymanapp/developer-utils'; * It contains input and output filenames, an array of all used modifiers * and all preprocessed key rules for up to 3 key/modifier combinations. */ -export interface convert_object { +export interface ProcesData { keylayout_filename: string, kmn_filename: string, arrayOf_Modifiers: string[][], arrayOf_Rules: Rule[], }; -export interface allArrayContents_object { +export interface KeylayoutFileData { actionId?: string, keyCode?: string, key?: string, @@ -36,7 +36,7 @@ export interface allArrayContents_object { outchar?: string; }; -export interface idStateOutput_object { +export interface ActionStateOutput { id: string, state: string, output: string, @@ -45,19 +45,18 @@ export interface idStateOutput_object { /** * @brief member function to find the number of keys defined in a .keykayout file. * We process 'MAX_KEY_COUNT' keys at maximum. In case a keylayout has fewer keys defined, we use that smaller number of keys (USE_KEY_COUNT) - * @param data data read from keylayout file - * @return static variable USE_KEY_COUNT holding the number of keys used in a .keykayout file. + * @param data data read from keylayout file + * @param pos the nth keyMap to be examined + * @return usedKeyCount holding the number of keys of a certain keyMap used in a .keykayout file. */ export function find_usedKeysCount(data: any, pos: number): number { - let USE_KEY_COUNT = KeylayoutToKmnConverter.MAX_KEY_COUNT; - for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { - //if (data.keyboard.keyMapSet[0].keyMap[i].key.length < USE_KEY_COUNT) { - if ((i === pos) && (data.keyboard.keyMapSet[0].keyMap[i].key.length < USE_KEY_COUNT)) { - // set the max to n-1 (use key 0 -> nth-1) - USE_KEY_COUNT = data.keyboard.keyMapSet[0].keyMap[i].key.length - 1; - } + + let usedKeyCount = KeylayoutToKmnConverter.MAX_KEY_COUNT; + if (data.keyboard.keyMapSet[0].keyMap[pos].key.length < usedKeyCount ) { + // set the max to n-1 (keys are zero indexed ) + usedKeyCount = data.keyboard.keyMapSet[0].keyMap[pos].key.length - 1; } - return USE_KEY_COUNT; + return usedKeyCount ; } export class KeylayoutToKmnConverter { @@ -116,7 +115,7 @@ export class KeylayoutToKmnConverter { outputFilename = outputFilename ?? inputFilename.replace(/\.keylayout$/, '.kmn'); - const outArray: convert_object = await this.convert(jsonO, outputFilename); + const outArray: ProcesData = await this.convert(jsonO, outputFilename); if (outArray.arrayOf_Rules.length === 0) { this.callbacks.reportMessage(ConverterMessages.Error_UnableToConvert({ inputFilename })); return null; @@ -135,22 +134,23 @@ export class KeylayoutToKmnConverter { /** - * @brief member function to read filename and behaviour of a json object into a convert_object + * @brief member function to read filename and behaviour of a json object into a ProcesData * @param jsonObj containing filename, behaviour and rules of a json object - * @return an convert_object containing all data ready to print out + * @return an ProcesData containing all data ready to print out */ - private convert(jsonObj: any, outputfilename: string): convert_object { + private convert(jsonObj: any, outputfilename: string): ProcesData { const modifierBehavior: string[][] = []; // modifier for each behaviour const rules: Rule[] = []; // an array of data for a kmn rule - const data_object: convert_object = { + const data_object: ProcesData = { keylayout_filename: "", kmn_filename: "", arrayOf_Modifiers: [], arrayOf_Rules: [] }; - +//_S2 do I need to "validate again here?" if ((jsonObj !== null) && (jsonObj.hasOwnProperty("keyboard"))) { + //if ((jsonObj !== null) ) { data_object.keylayout_filename = outputfilename.replace(/\.kmn$/, '.keylayout'); data_object.kmn_filename = outputfilename; @@ -176,12 +176,12 @@ export class KeylayoutToKmnConverter { } /** - * @brief member function to read the rules contained in a json object and add array of Rules[] to an convert_object + * @brief member function to read the rules contained in a json object and add array of Rules[] to an ProcesData * @param data_ukelele: an object containing the name of the input file, an array of behaviours and an (empty) array of Rules * @param jsonObj: json Object containing all data read from a keylayout file * @return an object containing the name of the input file, an array of behaviours and a populated array of Rules[] */ - public createRuleData(data_ukelele: convert_object, jsonObj: any): convert_object { + public createRuleData(data_ukelele: ProcesData, jsonObj: any): ProcesData { const object_array: Rule[] = []; let dk_counter_C3: number = 0; @@ -270,26 +270,26 @@ export class KeylayoutToKmnConverter { const outputchar: string = this.get_Output__From__ActionId_None(jsonObj, action_id); - const b1_modifierKey_obj: allArrayContents_object[] = + const b1_modifierKey_obj: KeylayoutFileData[] = this.get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput(jsonObj, data_ukelele.arrayOf_Modifiers, action_id, outputchar, isCapsused); for (let m = 0; m < b1_modifierKey_obj.length; m++) { rule_obj = new Rule( - /* rule_type */ "C1", + /* rule_type */ "C1", - /* modifier_prev_deadkey*/ "", - /* prev_deadkey */ "", - /* id_prev_deadkey */ 0, - /* unique A */ 0, + /* modifier_prev_deadkey*/ "", + /* prev_deadkey */ "", + /* id_prev_deadkey */ 0, + /* unique A */ 0, - /* modifier_deadkey */ "", - /* deadkey */ "", - /* dk for C2*/ 0, - /* unique B */ 0, + /* modifier_deadkey */ "", + /* deadkey */ "", + /* dk for C2*/ 0, + /* unique B */ 0, - /* modifier_key*/ b1_modifierKey_obj[m].modifier, - /* key */ b1_modifierKey_obj[m].key, - /* output */ new TextEncoder().encode(outputchar) + /* modifier_key*/ b1_modifierKey_obj[m].modifier, + /* key */ b1_modifierKey_obj[m].key, + /* output */ new TextEncoder().encode(outputchar) ); if ((outputchar !== undefined) && (outputchar !== "undefined") && (outputchar !== "")) { object_array.push(rule_obj); @@ -323,21 +323,21 @@ export class KeylayoutToKmnConverter { // Data of Block Nr 4 ..................................................................................................................................................................... // with present action_id (a18) find all keycode-behaviour-pairs that use this action (a18) => (keymapIndex 0/keycode 24 and keymapIndex 3/keycode 24) .................................... // from these create an array of modifier combinations e.g. [['','caps?'], ['Caps']] ..................................................................................................... - /* eg: [['24', 0], ['24', 3]] */ const b4_deadkey_obj: allArrayContents_object[] = this.get_KeyModifier_array__From__ActionID(jsonObj, action_id); + /* eg: [['24', 0], ['24', 3]] */ const b4_deadkey_obj: KeylayoutFileData[] = this.get_KeyModifier_array__From__ActionID(jsonObj, action_id); /* e.g. [['','caps?'], ['Caps']]*/ const b4_deadkeyModifier_obj: string[] = this.get_Modifier_array__From__KeyModifier_array(data_ukelele.arrayOf_Modifiers, b4_deadkey_obj); // ........................................................................................................................................................................................ // Data of Block Nr 6 ..................................................................................................................................................................... // create an array[action id,state,output] from all state-output-pairs that use state = b5_value_next (e.g. use 1 in ) ...................................... - /* eg: [ 'a9','1','â'] */ const b6_actionId_obj: idStateOutput_object[] = this.get_ActionStateOutput_array__From__ActionState(jsonObj, b5_value_next); + /* eg: [ 'a9','1','â'] */ const b6_actionId_obj: ActionStateOutput[] = this.get_ActionStateOutput_array__From__ActionState(jsonObj, b5_value_next); // ........................................................................................................................................................................................ // Data of Block Nr 1 .................................................................................................................................................................... // create array[Keycode,Keyname,action id,actionIndex,output] and array[Keyname,action id,behaviour,modifier,output] ...................................................................... - /* eg: ['0','K_A','a9','0','â'] */ const b1_keycode_obj: allArrayContents_object[] = this.get_KeyActionOutput_array__From__ActionStateOutput_array(jsonObj, b6_actionId_obj); - /* eg: ['K_A','a9','0','NCAPS','â']*/ const b1_modifierKey_obj: allArrayContents_object[] = this.get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(jsonObj, b1_keycode_obj, isCapsused); + /* eg: ['0','K_A','a9','0','â'] */ const b1_keycode_obj: KeylayoutFileData[] = this.get_KeyActionOutput_array__From__ActionStateOutput_array(jsonObj, b6_actionId_obj); + /* eg: ['K_A','a9','0','NCAPS','â']*/ const b1_modifierKey_obj: KeylayoutFileData[] = this.get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(jsonObj, b1_keycode_obj, isCapsused); // ....................................................................................................................................................................................... for (let n1 = 0; n1 < b4_deadkeyModifier_obj.length; n1++) { @@ -346,21 +346,21 @@ export class KeylayoutToKmnConverter { for (let n4 = 0; n4 < b1_modifierKey_obj.length; n4++) { rule_obj = new Rule( - /* rule_type */ "C2", + /* rule_type */ "C2", - /* modifier_prev_deadkey*/ "", - /* prev_deadkey */ "", - /* id_prev_deadkey */ 0, - /* unique A */ 0, + /* modifier_prev_deadkey*/ "", + /* prev_deadkey */ "", + /* id_prev_deadkey */ 0, + /* unique A */ 0, - /* modifier_deadkey */ this.create_kmn_modifier(b4_deadkeyModifier_obj[n1][n2], isCapsused), - /* deadkey */ this.map_UkeleleKC_To_VK(Number(b4_deadkey_obj[n3].key)), - /* dk for C2*/ dk_counter_C2++, - /* unique B */ 0, + /* modifier_deadkey */ this.create_kmn_modifier(b4_deadkeyModifier_obj[n1][n2], isCapsused), + /* deadkey */ this.map_UkeleleKC_To_VK(Number(b4_deadkey_obj[n3].key)), + /* dk for C2*/ dk_counter_C2++, + /* unique B */ 0, - /* modifier_key*/ b1_modifierKey_obj[n4].modifier, - /* key */ b1_modifierKey_obj[n4].key, - /* output */ new TextEncoder().encode(b1_modifierKey_obj[n4].outchar), + /* modifier_key*/ b1_modifierKey_obj[n4].modifier, + /* key */ b1_modifierKey_obj[n4].key, + /* output */ new TextEncoder().encode(b1_modifierKey_obj[n4].outchar), ); if ((b1_modifierKey_obj[n4].outchar !== undefined) && (b1_modifierKey_obj[n4].outchar !== "undefined") @@ -400,7 +400,7 @@ export class KeylayoutToKmnConverter { // Data of Block Nr 4 ........................................................................................................................................................................ // with present action_id (a16) find all keycode-behaviour-pairs that use this action (a16) => (keymapIndex 3/keycode 32) .................................................................... // from these create an array of modifier combinations e.g. [ [ 'anyOption', 'Caps' ] ] ..................................................................................................... - /* e.g. [['32', 3]] */ const b4_deadkey_obj: allArrayContents_object[] = this.get_KeyModifier_array__From__ActionID(jsonObj, action_id); + /* e.g. [['32', 3]] */ const b4_deadkey_obj: KeylayoutFileData[] = this.get_KeyModifier_array__From__ActionID(jsonObj, action_id); /* e.g. [ [ 'anyOption', 'Caps' ] ]*/ const b4_deadkeyModifier_obj: string[] = this.get_Modifier_array__From__KeyModifier_array(data_ukelele.arrayOf_Modifiers, b4_deadkey_obj); // ........................................................................................................................................................................................... @@ -412,18 +412,18 @@ export class KeylayoutToKmnConverter { // Data of Block Nr 2 ....................................................................................................................................................................... // with present action_id (a17) find all key names and behaviours that use this action (a17) => (keymapIndex 3/keycode 28) .................................................................... // from these create an array of modifier combinations e.g. [ [ 'anyOption', 'Caps' ] ] ..................................................................................................... - /* eg: index=3 */ const b2_prev_deadkey_obj: allArrayContents_object[] = this.get_KeyModifier_array__From__ActionID(jsonObj, b3_actionId); + /* eg: index=3 */ const b2_prev_deadkey_obj: KeylayoutFileData[] = this.get_KeyModifier_array__From__ActionID(jsonObj, b3_actionId); /* e.g. [ [ 'anyOption', 'Caps' ] ] */ const b2_prev_deadkeyModifier_obj: string[] = this.get_Modifier_array__From__KeyModifier_array(data_ukelele.arrayOf_Modifiers, b2_prev_deadkey_obj); // ........................................................................................................................................................................................... // Data of Block Nr 6 ........................................................................................................................................................................ // create an array[action id,state,output] from all state-output-pairs that use state = b5_value_next (e.g. use 1 in ) ......................................... - /* eg:[ [ 'a9','1','â'] ]*/ const b6_actionId_obj: idStateOutput_object[] = this.get_ActionStateOutput_array__From__ActionState(jsonObj, b5_value_next); /* eg:[ [ 'a9','1','â'] ]*/ + /* eg:[ [ 'a9','1','â'] ]*/ const b6_actionId_obj: ActionStateOutput[] = this.get_ActionStateOutput_array__From__ActionState(jsonObj, b5_value_next); /* eg:[ [ 'a9','1','â'] ]*/ // ........................................................................................................................................................................................... // Data of Block Nr 1 ....................................................................................................................................................................... // create array[Keycode,Keyname,action id,actionIndex,output] and array[Keyname,action id,behaviour,modifier,output] ......................................................................... - /* eg: ['49','K_SPACE','a0','0','Â'] */ const b1_keycode_obj: allArrayContents_object[] = this.get_KeyActionOutput_array__From__ActionStateOutput_array(jsonObj, b6_actionId_obj); - /* eg: ['K_SPACE','a0','0','NCAPS','Â'] */ const b1_modifierKey_obj: allArrayContents_object[] = this.get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(jsonObj, b1_keycode_obj, isCapsused); + /* eg: ['49','K_SPACE','a0','0','Â'] */ const b1_keycode_obj: KeylayoutFileData[] = this.get_KeyActionOutput_array__From__ActionStateOutput_array(jsonObj, b6_actionId_obj); + /* eg: ['K_SPACE','a0','0','NCAPS','Â'] */ const b1_modifierKey_obj: KeylayoutFileData[] = this.get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(jsonObj, b1_keycode_obj, isCapsused); // ........................................................................................................................................................................................... for (let n1 = 0; n1 < b2_prev_deadkeyModifier_obj.length; n1++) { @@ -435,20 +435,20 @@ export class KeylayoutToKmnConverter { for (let n7 = 0; n7 < b1_modifierKey_obj.length; n7++) { rule_obj = new Rule( - /* rule_type */ "C3", - /* modifier_prev_deadkey*/ this.create_kmn_modifier(b2_prev_deadkeyModifier_obj[n1][n2], isCapsused), - /* prev_deadkey */ this.map_UkeleleKC_To_VK(Number(b2_prev_deadkey_obj[n3].key)), - /* id_prev_deadkey */ dk_counter_C3++, - /* unique A */ 0, - - /* modifier_deadkey */ this.create_kmn_modifier(b4_deadkeyModifier_obj[n4][n5], isCapsused), - /* deadkey */ this.map_UkeleleKC_To_VK(Number(b4_deadkey_obj[n6].key)), - /* dk for C2*/ 0, - /* unique B */ 0, - - /* modifier_key*/ b1_modifierKey_obj[n7].modifier, - /* key */ b1_modifierKey_obj[n7].key, - /* output */ new TextEncoder().encode(b1_modifierKey_obj[n7].outchar), + /* rule_type */ "C3", + /* modifier_prev_deadkey*/ this.create_kmn_modifier(b2_prev_deadkeyModifier_obj[n1][n2], isCapsused), + /* prev_deadkey */ this.map_UkeleleKC_To_VK(Number(b2_prev_deadkey_obj[n3].key)), + /* id_prev_deadkey */ dk_counter_C3++, + /* unique A */ 0, + + /* modifier_deadkey */ this.create_kmn_modifier(b4_deadkeyModifier_obj[n4][n5], isCapsused), + /* deadkey */ this.map_UkeleleKC_To_VK(Number(b4_deadkey_obj[n6].key)), + /* dk for C2*/ 0, + /* unique B */ 0, + + /* modifier_key*/ b1_modifierKey_obj[n7].modifier, + /* key */ b1_modifierKey_obj[n7].key, + /* output */ new TextEncoder().encode(b1_modifierKey_obj[n7].outchar), ); if ((b1_modifierKey_obj[n7].outchar !== undefined) && (b1_modifierKey_obj[n7].outchar !== "undefined") @@ -486,7 +486,7 @@ export class KeylayoutToKmnConverter { * @param data_ukelele: an object containing the name of the input file, an array of behaviours and an array of Rules * @return an object containing the name of the input file, an array of behaviours and the revised array of Rules[] */ - public reviewRuleInputData(data_ukelele: convert_object): convert_object { + public reviewRuleInputData(data_ukelele: ProcesData): ProcesData { // check for duplicate C2 and C3 rules in object_array (e.g. [NCAPS RALT K_8] > dk(C12) ): create a separate array of unique rules, // then compare to object_array and mark first occurrence of a rule in object_array @@ -822,10 +822,10 @@ export class KeylayoutToKmnConverter { /** * @brief member function to create an array of (modifier) behaviours for a given keycode in [{keycode,modifier}] * @param data : any - an object containing all data read from a .keylayout file - * @param search : allArrayContents_object[] - an array[{keycode,modifier}] to be found + * @param search : KeylayoutFileData[] - an array[{keycode,modifier}] to be found * @return an array: string[] containing modifiers */ - public get_Modifier_array__From__KeyModifier_array(data: any, search: allArrayContents_object[]): string[] { + public get_Modifier_array__From__KeyModifier_array(data: any, search: KeylayoutFileData[]): string[] { const returnString1D: string[] = []; for (let i = 0; i < search.length; i++) { returnString1D.push(data[search[i].behaviour]); @@ -860,15 +860,15 @@ export class KeylayoutToKmnConverter { * @brief member function to return array of [Keycode,Keyname,actionId,actionIDIndex, output] for a given actionID in of [ actionID,state,output] * @param data :any - an object containing all data read from a .keylayout file * @param search :idStateOutput_object[] - array of [{ actionID,state,output }] - * @return a allArrayContents_object[] containing [{Keycode,Keyname,actionId,actionID, output}] + * @return a KeylayoutFileData[] containing [{Keycode,Keyname,actionId,actionID, output}] */ - public get_KeyActionOutput_array__From__ActionStateOutput_array(data: any, search: idStateOutput_object[]): allArrayContents_object[] { + public get_KeyActionOutput_array__From__ActionStateOutput_array(data: any, search: ActionStateOutput[]): KeylayoutFileData[] { if ((search === undefined) || (search === null)) return []; const returnObjarray1D = []; - let returnObject: allArrayContents_object; + let returnObject: KeylayoutFileData; for (let k = 0; k < search.length; k++) { for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { @@ -896,9 +896,9 @@ export class KeylayoutToKmnConverter { * @param search : string a 'state' to be found * @return an array: idStateOutput_object[] containing all [{actionId, state, output}] for a certain state */ - public get_ActionStateOutput_array__From__ActionState(data: any, search: string): idStateOutput_object[] { - const returnObjarray1D: idStateOutput_object[] = []; - let returnObject: idStateOutput_object; + public get_ActionStateOutput_array__From__ActionState(data: any, search: string): ActionStateOutput[] { + const returnObjarray1D: ActionStateOutput[] = []; + let returnObject: ActionStateOutput; for (let i = 0; i < data.keyboard.actions.action.length; i++) { for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { @@ -922,11 +922,11 @@ export class KeylayoutToKmnConverter { * @param data : any an object containing all data read from a .keylayout file * @param search : array of [{keycode,keyname,actionId,behaviour,output}] to be found * @param isCAPSused : boolean flag to indicate if CAPS is used in a keylayout file or not - * @return an array: allArrayContents_object[] containing [{KeyName,actionId,behaviour,modifier,output}] + * @return an array: KeylayoutFileData[] containing [{KeyName,actionId,behaviour,modifier,output}] */ - public get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(data: any, search: allArrayContents_object[], isCAPSused: boolean): allArrayContents_object[] { + public get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array(data: any, search: KeylayoutFileData[], isCAPSused: boolean): KeylayoutFileData[] { const returnObjarray1D = []; - let returnObject: allArrayContents_object; + let returnObject: KeylayoutFileData; if (!((search === undefined) || (search === null) || (search.length === 0))) { for (let i = 0; i < search.length; i++) { @@ -967,11 +967,11 @@ export class KeylayoutToKmnConverter { * @param search : string - an actionId to be found * @param outchar : string - the output character * @param isCAPSused : boolean - flag to indicate if CAPS is used in a keylayout file or not - * @return an array: allArrayContents_object[] containing [{actionID,output,actionID, behaviour,keyname,modifier}] + * @return an array: KeylayoutFileData[] containing [{actionID,output, behaviour,keyname,modifier}] */ - public get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput(data: any, modi: string[][], search: string, outchar: string, isCapsused: boolean): allArrayContents_object[] { + public get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput(data: any, modi: string[][], search: string, outchar: string, isCapsused: boolean): KeylayoutFileData[] { const returnObjarray1D = []; - let returnObject: allArrayContents_object; + let returnObject: KeylayoutFileData; if ((search === "") || (search === undefined) || !((isCapsused === true) || (isCapsused === false))) { return []; @@ -1018,11 +1018,11 @@ export class KeylayoutToKmnConverter { * @brief member function to create an array of [{keycode,behaviour}] for a given actionId * @param data : any - an object containing all data read from a .keylayout file * @param search : string - an actionId to be found - * @return an array: allArrayContents_object[] containing [{keycode,behaviour}] + * @return an array: KeylayoutFileData[] containing [{keycode,behaviour}] */ - public get_KeyModifier_array__From__ActionID(data: any, search: string): allArrayContents_object[] { - let returnObject: allArrayContents_object; - const mapIndexObject1D: allArrayContents_object[] = []; + public get_KeyModifier_array__From__ActionID(data: any, search: string): KeylayoutFileData[] { + let returnObject: KeylayoutFileData; + const mapIndexObject1D: KeylayoutFileData[] = []; for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] === search) { diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts index 459231e085b..c00330e5d16 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts @@ -8,7 +8,7 @@ */ import { CompilerCallbacks, CompilerOptions } from "@keymanapp/developer-utils"; -import { KeylayoutToKmnConverter, convert_object, Rule } from './keylayout-to-kmn-converter.js'; +import { KeylayoutToKmnConverter, ProcesData, Rule } from './keylayout-to-kmn-converter.js'; import { util } from '@keymanapp/common-types'; import { ConverterMessages } from '../converter-messages.js'; import KEYMAN_VERSION from "@keymanapp/keyman-version"; @@ -23,7 +23,7 @@ export class KmnFileWriter { * @param outputfilename the file that will be written; if no outputfilename is given an outputfilename will be created from data_ukelele.keylayout_filename * @return true if data has been written; false if not */ - public write(data_ukelele: convert_object): boolean { + public write(data_ukelele: ProcesData): boolean { let data: string = "\n"; @@ -42,7 +42,7 @@ export class KmnFileWriter { } } - public writeToString(data_ukelele: convert_object): string { + public writeToString(data_ukelele: ProcesData): string { let data: string = "\n"; // add top part of kmn file: STORES @@ -59,7 +59,7 @@ export class KmnFileWriter { } } - public writeToUint8Array(data_ukelele: convert_object): Uint8Array { + public writeToUint8Array(data_ukelele: ProcesData): Uint8Array { let data: string = "\n"; // add top part of kmn file: STORES @@ -81,7 +81,7 @@ export class KmnFileWriter { * @param data_ukelele an object containing all data read from a .keylayout file * @return string - all stores to be printed */ - public writeData_Stores(data_ukelele: convert_object): string { + public writeData_Stores(data_ukelele: ProcesData): string { let data: string = ""; @@ -108,7 +108,7 @@ export class KmnFileWriter { * @param data_ukelele an object containing all data read from a .keylayout file * @return string - all rules to be printed */ - public writeData_Rules(data_ukelele: convert_object): string { + public writeData_Rules(data_ukelele: ProcesData): string { const keylayoutKmnConverter = new KeylayoutToKmnConverter(this.callbacks, this.options); let data: string = ""; diff --git a/developer/src/kmc-convert/test/data/Test_C3_several.keylayout b/developer/src/kmc-convert/test/data/Test_C3_several.keylayout index bdacf29ac5c..7fff380f2cc 100644 --- a/developer/src/kmc-convert/test/data/Test_C3_several.keylayout +++ b/developer/src/kmc-convert/test/data/Test_C3_several.keylayout @@ -28,7 +28,7 @@ - + diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index 26cb6adf46d..897fe4e935b 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -12,7 +12,7 @@ import { assert } from 'chai'; import * as NodeAssert from 'node:assert'; import { CompilerErrorNamespace, CompilerErrorSeverity } from '@keymanapp/developer-utils'; import { compilerTestCallbacks, compilerTestOptions, makePathToFixture } from './helpers/index.js'; -import { idStateOutput_object, allArrayContents_object, KeylayoutToKmnConverter } from '../src/keylayout-to-kmn/keylayout-to-kmn-converter.js'; +import { ActionStateOutput, KeylayoutFileData, KeylayoutToKmnConverter, Rule } from '../src/keylayout-to-kmn/keylayout-to-kmn-converter.js'; import { KeylayoutFileReader } from '../src/keylayout-to-kmn/keylayout-file-reader.js'; import { ConverterMessages } from '../src/converter-messages.js'; @@ -22,6 +22,27 @@ describe('KeylayoutToKmnConverter', function () { compilerTestCallbacks.clear(); }); + // todo remove + describe('RunAllFiles', function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + [ + [makePathToFixture('../data/Italian.keylayout')], + [makePathToFixture('../data/Italian_command.keylayout')], + [makePathToFixture('../data/Swiss_French.keylayout')], + [makePathToFixture('../data/Spanish.keylayout')], + [makePathToFixture('../data/Swiss_German.keylayout')], + [makePathToFixture('../data/US.keylayout')], + [makePathToFixture('../data/Polish.keylayout')], + [makePathToFixture('../data/French.keylayout')], + [makePathToFixture('../data/Latin_American.keylayout')], + // [makePathToFixture('../data/German_complete.keylayout')], + [makePathToFixture('../data/German_complete_reduced.keylayout')], + // [makePathToFixture('../data/German_Standard.keylayout')], + ].forEach(function (files_) { + sut.run(files_[0]); + assert.isTrue(true); + }); + }); describe('RunTestFiles resulting in errors ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); [ @@ -161,12 +182,12 @@ describe('KeylayoutToKmnConverter', function () { const read = sut_r.read(inputFilename); const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); - // convert_object from unavailable file name + // ProcesData from unavailable file name const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); const read_unavailable = sut_r.read(inputFilename_unavailable); const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); - // convert_object from empty filename + // ProcesData from empty filename const inputFilename_empty = makePathToFixture(''); const read_empty = sut_r.read(inputFilename_empty); const converted_empty = sut.convert_bound.convert(read_empty, inputFilename_empty); @@ -209,7 +230,7 @@ describe('KeylayoutToKmnConverter', function () { && converted_rule.arrayOf_Rules.length === 0)); }); - it('should return empty array of rukes on null input', async function () { + it('should return empty array of rules on null input', async function () { const converted_rule = sut.convert_bound.convert(null, 'ABC.kmn'); assert.isTrue(converted_rule.arrayOf_Rules.length === 0); }); @@ -343,7 +364,7 @@ describe('KeylayoutToKmnConverter', function () { it((values[1] !== null) ? ("get_Modifier_array__From__KeyModifier_array('" + JSON.stringify(values[0]) + "')").padEnd(68, " ") + " should return '" + JSON.stringify(values[1]) + "'" : ("get_Modifier_array__From__KeyModifier_array('" + JSON.stringify(values[0]) + "')").padEnd(68, " ") + " should return '" + "null" + "'", async function () { - const result = sut.get_Modifier_array__From__KeyModifier_array(converted.arrayOf_Modifiers, values[0] as allArrayContents_object[]); + const result = sut.get_Modifier_array__From__KeyModifier_array(converted.arrayOf_Modifiers, values[0] as KeylayoutFileData[]); assert.deepStrictEqual(JSON.stringify(result), JSON.stringify(values[1])); }); }); @@ -461,7 +482,7 @@ describe('KeylayoutToKmnConverter', function () { const inputFilename = makePathToFixture('../data/Test.keylayout'); const read = sut_r.read(inputFilename); - const b1_keycode_arr: allArrayContents_object[] = [ + const b1_keycode_arr: KeylayoutFileData[] = [ { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '0', outchar: 'ˆ' }, { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '1', outchar: 'ˆ' }, { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '2', outchar: 'ˆ' }, @@ -486,7 +507,7 @@ describe('KeylayoutToKmnConverter', function () { { keyCode: '0', key: 'K_A', actionId: 'A_9', behaviour: '0', outchar: 'â' } ]; - const b1_modifierKey_arr: allArrayContents_object[] = [ + const b1_modifierKey_arr: KeylayoutFileData[] = [ { actionId: 'A_0', key: 'K_SPACE', behaviour: '0', modifier: 'NCAPS', outchar: 'ˆ' }, { actionId: 'A_0', key: 'K_SPACE', behaviour: '1', modifier: 'CAPS', outchar: 'ˆ' }, { actionId: 'A_0', key: 'K_SPACE', behaviour: '2', modifier: 'NCAPS SHIFT', outchar: 'ˆ' }, @@ -651,7 +672,7 @@ describe('KeylayoutToKmnConverter', function () { const inputFilename = makePathToFixture('../data/Test.keylayout'); const read = sut_r.read(inputFilename); - const b6_actionId_arr: idStateOutput_object[] = [ + const b6_actionId_arr: ActionStateOutput[] = [ { "id": "A_0", "state": "1", "output": "ˆ" }, { "id": "A_1", "state": "1", "output": "Â" }, { "id": "A_10", "state": "1", "output": "ê" }, @@ -665,7 +686,7 @@ describe('KeylayoutToKmnConverter', function () { { "id": "A_9", "state": "1", "output": "â" } ]; - const b1_keycode_arr: allArrayContents_object[] = [ + const b1_keycode_arr: KeylayoutFileData[] = [ { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '0', outchar: 'ˆ' }, { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '1', outchar: 'ˆ' }, { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behaviour: '2', outchar: 'ˆ' }, @@ -693,7 +714,7 @@ describe('KeylayoutToKmnConverter', function () { [[b6_actionId_arr, b1_keycode_arr], ].forEach(function (values) { it(("get_KeyActionOutput_array__From__ActionStateOutput_array([['" + JSON.stringify(values[0]) + "'],..])").padEnd(73, " ") + '1 should return an array of objects', async function () { - const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0] as idStateOutput_object[]); + const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0] as ActionStateOutput[]); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); @@ -723,7 +744,7 @@ describe('KeylayoutToKmnConverter', function () { [[{ "id": "A_0", "state": "", "output": "ˆ" }], oneEntryResult], ].forEach(function (values) { it(("get_KeyActionOutput_array__From__ActionStateOutput_array(['" + JSON.stringify(values[0]) + "'])").padEnd(73, " ") + ' should return an array of objects', async function () { - const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0] as idStateOutput_object[]); + const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0] as ActionStateOutput[]); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); @@ -734,7 +755,7 @@ describe('KeylayoutToKmnConverter', function () { ].forEach(function (values) { it(("get_KeyActionOutput_array__From__ActionStateOutput_array(" + JSON.stringify(values[0]) + ")").padEnd(73, " ") + ' should return ' + "'[" + JSON.stringify(values[1]) + "]'", async function () { - const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0] as idStateOutput_object[]); + const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0] as ActionStateOutput[]); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); @@ -744,10 +765,71 @@ describe('KeylayoutToKmnConverter', function () { [null, []], ].forEach(function (values) { it(("get_KeyActionOutput_array__From__ActionStateOutput_array(" + JSON.stringify(values[0]) + ")").padEnd(73, " ") + ' should return ' + "'[" + JSON.stringify(values[1]) + "]'", async function () { - const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0] as idStateOutput_object[]); + const result = sut.get_KeyActionOutput_array__From__ActionStateOutput_array(read, values[0] as ActionStateOutput[]); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); }); -}); \ No newline at end of file + describe('createRuleData ', function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sut_r = new KeylayoutFileReader(compilerTestCallbacks); + + [ + [ + ['../data/Test_C0.keylayout'], + [new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_A', new TextEncoder().encode('a')), + new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_A', new TextEncoder().encode('A')), + new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_S', new TextEncoder().encode('s')), + new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_D', new TextEncoder().encode('d'))] + ], + [ + ['../data/Test_C1.keylayout'], + [new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_S', new TextEncoder().encode('s')), + new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_S', new TextEncoder().encode('S'))] + ], + [ + ['../data/Test_C2.keylayout'], + [new Rule("C2", '', '', 0, 0, 'NCAPS', 'K_U', 1, 1, 'CAPS', 'K_A', new TextEncoder().encode('Â'))], + ], + [ + ['../data/Test_C3.keylayout'], + [new Rule("C3", 'NCAPS SHIFT', 'K_D', 2, 1, 'NCAPS', 'K_U', 1, 2, 'CAPS', 'K_A', new TextEncoder().encode('Â'))] + ], + + [ + ['../data/Test_C3_several.keylayout'], + [new Rule("C3", 'NCAPS RALT', 'K_8', 3, 1, 'CAPS', 'K_U', 1, 3, 'NCAPS', 'K_A', new TextEncoder().encode('â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 3, 0, 'CAPS', 'K_U', 1, 0, 'NCAPS RALT', 'K_A', new TextEncoder().encode('â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 3, 0, 'NCAPS RALT', 'K_U', 2, 2, 'NCAPS', 'K_A', new TextEncoder().encode('â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 3, 0, 'NCAPS RALT', 'K_U', 2, 0, 'NCAPS RALT', 'K_A', new TextEncoder().encode('â'))] + ], + [ + ['../data/Test_C0_C1_C2_C3.keylayout'], + [new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_A', new TextEncoder().encode('A')), + new Rule("C2", '', '', 0, 0, 'NCAPS RALT', 'K_EQUAL', 1, 1, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_S', new TextEncoder().encode('S')), + new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'NCAPS RALT', 'K_U', new TextEncoder().encode('S')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 1, 'CAPS', 'K_S', 2, 6, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'CAPS', 'K_U', 3, 3, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'NCAPS RALT', 'K_S', 4, 4, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'NCAPS RALT', 'K_U', 5, 5, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_S', new TextEncoder().encode('S')), + new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'NCAPS RALT', 'K_U', new TextEncoder().encode('S')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'CAPS', 'K_S', 2, 0, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'CAPS', 'K_U', 3, 0, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'NCAPS RALT', 'K_S', 4, 0, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'NCAPS RALT', 'K_U', 5, 0, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_U', new TextEncoder().encode('U')),] + ], + ].forEach(function (values: any) { + it('data of \'' + values[0] + "' passed into createRuleData() " + 'should create an array of rules', async function () { + const inputFilename = makePathToFixture(values[0][0]); + const read = sut_r.read(inputFilename); + const outArray = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); + assert.deepEqual(outArray.arrayOf_Rules[0], values[1][0]); + }); + }); + }); + +}); diff --git a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts index bf7acd4b648..a7ea37b70f5 100644 --- a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts +++ b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts @@ -12,7 +12,7 @@ import { assert } from 'chai'; import { util } from '@keymanapp/common-types'; import KEYMAN_VERSION from "@keymanapp/keyman-version"; import { compilerTestCallbacks, compilerTestOptions, makePathToFixture } from './helpers/index.js'; -import { KeylayoutToKmnConverter, Rule } from '../src/keylayout-to-kmn/keylayout-to-kmn-converter.js'; +import { KeylayoutToKmnConverter, ProcesData, Rule } from '../src/keylayout-to-kmn/keylayout-to-kmn-converter.js'; import { KmnFileWriter } from '../src/keylayout-to-kmn/kmn-file-writer.js'; import { KeylayoutFileReader } from '../src/keylayout-to-kmn/keylayout-file-reader.js'; @@ -30,7 +30,7 @@ describe('KmnFileWriter', function () { const read = sut_r.read(inputFilename); const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); - // empty convert_object from unavailable file name + // empty ProcesData from unavailable file name const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); const read_unavailable = sut_r.read(inputFilename_unavailable); const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); @@ -70,7 +70,7 @@ describe('KmnFileWriter', function () { + "group(main) using keys\n\n" + "\n"; - // empty convert_object from unavailable file name + // empty ProcesData from unavailable file name const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); const read_unavailable = sut_r.read(inputFilename_unavailable); const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); @@ -111,7 +111,7 @@ describe('KmnFileWriter', function () { + "\n"; - // empty convert_object from unavailable file name + // empty ProcesData from unavailable file name const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); const read_unavailable = sut_r.read(inputFilename_unavailable); const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); @@ -134,7 +134,7 @@ describe('KmnFileWriter', function () { const read = sut_r.read(inputFilename); const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); - // empty convert_object from unavailable file name + // empty ProcesData from unavailable file name const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); const read_unavailable = sut_r.read(inputFilename_unavailable); const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); @@ -159,12 +159,12 @@ describe('KmnFileWriter', function () { const read = sut_r.read(inputFilename); const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); - // empty convert_object from unavailable file name + // empty ProcesData from unavailable file name const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); const read_unavailable = sut_r.read(inputFilename_unavailable); const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); - // empty convert_object from empty filename + // empty ProcesData from empty filename const inputFilename_empty = makePathToFixture(''); const read_empty = sut_r.read(inputFilename_empty); const converted_empty = sut.convert_bound.convert(read_empty, inputFilename_empty); @@ -502,7 +502,107 @@ describe('KmnFileWriter', function () { }); }); - - + describe('write form intermediate data array', function () { + const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); + [ + [ + [ /* see ../data/Test_C0.keylayout */ + new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_A', new TextEncoder().encode('a')), + new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_A', new TextEncoder().encode('A')), + new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_S', new TextEncoder().encode('s')), + new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_D', new TextEncoder().encode('d')) + ], + ["+ [NCAPS K_A] > 'a'\n" + + "+ [CAPS K_A] > 'A'\n\n" + + "+ [NCAPS K_S] > 's'\n\n" + + "+ [NCAPS K_D] > 'd'\n"] + ], + [ + [ /* see ../data/Test_C1.keylayout */ + new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_S', new TextEncoder().encode('s')), + new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_S', new TextEncoder().encode('S')) + ], + ["+ [NCAPS K_S] > 's'\n" + + "+ [CAPS K_S] > 'S'\n"] + ], + [ + [ /* see ../data/Test_C2.keylayout */ + new Rule("C2", '', '', 0, 0, 'NCAPS', 'K_U', 1, 1, 'CAPS', 'K_A', new TextEncoder().encode('Â')) + ], + ["+ [NCAPS K_U] > dk(A1)\n" + + "dk(A1) + [CAPS K_A] > 'Â'\n\n"] + ], + [ + [ /* see ../data/Test_C3.keylayout */ + new Rule("C3", 'NCAPS SHIFT', 'K_D', 2, 1, 'NCAPS', 'K_U', 1, 2, 'CAPS', 'K_A', new TextEncoder().encode('Â')) + ], + ["+ [NCAPS SHIFT K_D] > dk(A2)\n" + + "dk(A2) + [NCAPS K_U] > dk(B1)\n" + + "dk(B1) + [CAPS K_A] > 'Â'\n\n" + ] + ], + [ + [ /* see ../data/Test_C0_C1_C2_C3.keylayout */ + new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_A', new TextEncoder().encode('A')), + new Rule("C2", '', '', 0, 0, 'NCAPS RALT', 'K_EQUAL', 1, 1, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_S', new TextEncoder().encode('S')), + new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'NCAPS RALT', 'K_U', new TextEncoder().encode('S')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 1, 'CAPS', 'K_S', 2, 6, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'CAPS', 'K_U', 3, 3, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'NCAPS RALT', 'K_S', 4, 4, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'NCAPS RALT', 'K_U', 5, 5, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_S', new TextEncoder().encode('S')), + new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'NCAPS RALT', 'K_U', new TextEncoder().encode('S')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'CAPS', 'K_S', 2, 0, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'CAPS', 'K_U', 3, 0, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'NCAPS RALT', 'K_S', 4, 0, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'NCAPS RALT', 'K_U', 5, 0, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_U', new TextEncoder().encode('U')), + ], + ["+ [CAPS K_A] > 'A'\n" + + "+ [CAPS K_S] > 'S'\n\n" + + "+ [NCAPS RALT K_U] > 'S'\n" + + "+ [CAPS K_U] > 'U'\n" + + "+ [NCAPS RALT K_EQUAL] > dk(A1)\n" + + "dk(A1) + [CAPS K_D] > 'Â'\n\n" + + "+ [NCAPS RALT K_8] > dk(A6)\n" + + "dk(A6) + [CAPS K_S] > dk(B2)\n" + + "dk(B2) + [CAPS K_D] > 'Â'\n\n" + + "dk(A6) + [CAPS K_U] > dk(B3)\n" + + "dk(B3) + [CAPS K_D] > 'Â'\n\n" + + "dk(A6) + [NCAPS RALT K_S] > dk(B4)\n" + + "dk(B4) + [CAPS K_D] > 'Â'\n\n" + + "dk(A6) + [NCAPS RALT K_U] > dk(B5)\n" + + "dk(B5) + [CAPS K_D] > 'Â'\n\n"] + ], + [ + [ /* see ../data/Test_C3_several.keylayout */ + new Rule("C3", 'NCAPS RALT', 'K_8', 3, 1, 'CAPS', 'K_U', 1, 3, 'NCAPS', 'K_A', new TextEncoder().encode('â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 3, 0, 'CAPS', 'K_U', 1, 0, 'NCAPS RALT', 'K_A', new TextEncoder().encode('â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 3, 0, 'NCAPS RALT', 'K_U', 2, 2, 'NCAPS', 'K_A', new TextEncoder().encode('â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 3, 0, 'NCAPS RALT', 'K_U', 2, 0, 'NCAPS RALT', 'K_A', new TextEncoder().encode('â')) + ], + ["+ [NCAPS RALT K_8] > dk(A3)\n" + + "dk(A3) + [CAPS K_U] > dk(B1)\n" + + "dk(B1) + [NCAPS K_A] > 'â'\n\n" + + "dk(B1) + [NCAPS RALT K_A] > 'â'\n\n" + + "dk(A3) + [NCAPS RALT K_U] > dk(B2)\n" + + "dk(B2) + [NCAPS K_A] > 'â'\n\n" + + "dk(B2) + [NCAPS RALT K_A] > 'â'\n\n" + ] + ], + ].forEach(function (values: any) { + it(('an array of Rules should create a set of kmn rules '), async function () { + const data: ProcesData = { + keylayout_filename: "", + kmn_filename: "", + arrayOf_Modifiers: [[]], + arrayOf_Rules: values[0] + }; + const result1 = sut_w.writeData_Rules(data); + assert.isTrue(result1 === values[1][0]); + }); + }); + }); }); From 406391c16e7be535d3e14b1cb9ba343fe2f545fa Mon Sep 17 00:00:00 2001 From: Sabine Date: Fri, 15 Aug 2025 13:35:29 +0200 Subject: [PATCH 166/251] feat(developer): rename writeData_Stores() -> write_KmnFileHeader() --- .../src/keylayout-to-kmn/kmn-file-writer.ts | 14 +++++++++----- .../src/kmc-convert/test/kmn-file-writer.tests.ts | 14 +++++++------- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts index f5044192209..b78f69fbcc3 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts @@ -28,7 +28,7 @@ export class KmnFileWriter { let data: string = "\n"; // add top part of kmn file: STORES - data += this.writeData_Stores(data_ukelele); + data += this.write_KmnFileHeader(data_ukelele); // add bottom part of kmn file: RULES data += this.writeData_Rules(data_ukelele); @@ -46,7 +46,7 @@ export class KmnFileWriter { let data: string = "\n"; // add top part of kmn file: STORES - data += this.writeData_Stores(data_ukelele); + data += this.write_KmnFileHeader(data_ukelele); // add bottom part of kmn file: RULES data += this.writeData_Rules(data_ukelele); @@ -63,7 +63,7 @@ export class KmnFileWriter { let data: string = "\n"; // add top part of kmn file: STORES - data += this.writeData_Stores(data_ukelele); + data += this.write_KmnFileHeader(data_ukelele); // add bottom part of kmn file: RULES data += this.writeData_Rules(data_ukelele); @@ -81,7 +81,7 @@ export class KmnFileWriter { * @param data_ukelele an object containing all data read from a .keylayout file * @return string - all stores to be printed */ - public writeData_Stores(data_ukelele: convert_object): string { + public write_KmnFileHeader(data_ukelele: convert_object): string { let data: string = ""; @@ -114,6 +114,9 @@ export class KmnFileWriter { let data: string = ""; // filter array of all rules and remove duplicates + // during the process of creating Rule[], duplicate rules might occur + // (e.g. when in a keylayout file the same modifiers occur in several behaviors thus producing the same rules). + // This is to filter out those duplicate Rule objects const unique_data_Rules: Rule[] = data_ukelele.arrayOf_Rules.filter((curr) => { return (!(curr.output === new TextEncoder().encode("") || curr.output === undefined) && (curr.key !== "") @@ -394,7 +397,8 @@ export class KmnFileWriter { /** * @brief member function to review rules for acceptable modifiers, duplicate or ambiguous rules and return an array containing possible warnings. - * Definition of comparisons e.g. 1-1, 2-4, 6-6 + * Keyman can not handle duplicate rules so we need to make sure a rule is written only once by either omitting a duplicate rule or commenting out an ambiguous rule. + * Omitting rules and definition of comparisons e.g. 1-1, 2-4, 6-6 * see https://docs.google.com/document/d/12J3NGO6RxIthCpZDTR8FYSRjiMgXJDLwPY2z9xqKzJ0/edit?tab=t.0#heading=h.pcz8rjyrl5ug * @param rule : Rule[] - an array of all rules * @param index the index of a rule in array[rule] diff --git a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts index 9afaae5b7b8..9474abc36ce 100644 --- a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts +++ b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts @@ -152,7 +152,7 @@ describe('KmnFileWriter', function () { }); - describe("writeData_Stores() ", function () { + describe("write_KmnFileHeader() ", function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); @@ -187,18 +187,18 @@ describe('KmnFileWriter', function () { + "group(main) using keys\n\n" + "\n"; - it(('writeData_Stores should return store text with filename ').padEnd(62, " ") + 'on correct input', async function () { - const written_correctName = sut_w.writeData_Stores(converted); + it(('write_KmnFileHeader should return store text with filename ').padEnd(62, " ") + 'on correct input', async function () { + const written_correctName = sut_w.write_KmnFileHeader(converted); assert.equal(written_correctName, (out_expected_first + converted.keylayout_filename + out_expected_last)); }); - it(('writeData_Stores should return store text without filename ').padEnd(62, " ") + 'on empty input', async function () { - const written_emptyName = sut_w.writeData_Stores(converted_empty); + it(('write_KmnFileHeader should return store text without filename ').padEnd(62, " ") + 'on empty input', async function () { + const written_emptyName = sut_w.write_KmnFileHeader(converted_empty); assert.equal(written_emptyName, (out_expected_first + out_expected_last)); }); - it(('writeData_Stores should return store text without filename ').padEnd(62, " ") + 'on only filename as input', async function () { - const written_onlyName = sut_w.writeData_Stores(converted_unavailable); + it(('write_KmnFileHeader should return store text without filename ').padEnd(62, " ") + 'on only filename as input', async function () { + const written_onlyName = sut_w.write_KmnFileHeader(converted_unavailable); assert.equal(written_onlyName, (out_expected_first + converted_unavailable.keylayout_filename + out_expected_last)); }); }); From d8be6966f5c63beb9c2b0928a7632ae2e64cde57 Mon Sep 17 00:00:00 2001 From: Sabine Date: Tue, 19 Aug 2025 17:35:03 +0200 Subject: [PATCH 167/251] feat(developer): import KeylayoutXMLSourceFile --- developer/src/kmc-convert/src/converter-messages.ts | 4 ++++ .../src/keylayout-to-kmn/keylayout-to-kmn-converter.ts | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/developer/src/kmc-convert/src/converter-messages.ts b/developer/src/kmc-convert/src/converter-messages.ts index 56045b42729..115315cc035 100644 --- a/developer/src/kmc-convert/src/converter-messages.ts +++ b/developer/src/kmc-convert/src/converter-messages.ts @@ -57,4 +57,8 @@ export class ConverterMessages { this.ERROR_UnsupportedCharactersDetected, `Input file ${def(o.inputFilename)} contains unsupported character ('${def(o.output)}') on key ( ${def(o.key)}) at keyMap index ${def(o.keymap_index)}`, ); + + static ERROR_InvalidFile = SevError | 0x0008; + static Error_InvalidFile = (o: { errorText: string; }) => m( + this.ERROR_InvalidFile, `The source file has an invalid structure: ${def(o.errorText)}`); } diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 92bdb6a93d4..4e18cbc17b6 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -12,7 +12,9 @@ import { KmnFileWriter } from './kmn-file-writer.js'; import { KeylayoutFileReader } from './keylayout-file-reader.js'; import { ConverterMessages } from '../converter-messages.js'; import { ConverterArtifacts } from "../converter-artifacts.js"; -import { ConverterToKmnArtifacts } from "../converter-artifacts.js"; +import { ConverterToKmnArtifacts } from "../converter-artifacts.js" +import { KeylayoutXMLSourceFile } from '../../../common/web/utils/src/types/keylayout/keylayout-xml.js'; + export interface ConverterResult extends KeymanCompilerResult { /** From ff4e7c98f3a608c5fdfd636cb593157e49066456 Mon Sep 17 00:00:00 2001 From: Sabine Date: Mon, 25 Aug 2025 10:37:08 +0200 Subject: [PATCH 168/251] feat(developer): solve merge conflicts --- .../src/kmc-convert/src/converter-messages.ts | 9 +- developer/src/kmc-convert/src/converter.ts | 4 +- .../keylayout-to-kmn-converter.ts | 65 +++++++----- .../src/keylayout-to-kmn/kmn-file-writer.ts | 44 ++++----- .../kmc-convert/test/kmn-file-writer.tests.ts | 98 ++++--------------- 5 files changed, 84 insertions(+), 136 deletions(-) diff --git a/developer/src/kmc-convert/src/converter-messages.ts b/developer/src/kmc-convert/src/converter-messages.ts index 8e22f4d49ec..bc411300cc2 100644 --- a/developer/src/kmc-convert/src/converter-messages.ts +++ b/developer/src/kmc-convert/src/converter-messages.ts @@ -6,7 +6,7 @@ import { CompilerErrorNamespace, CompilerErrorSeverity, CompilerMessageSpec as m, CompilerMessageDef as def } from '@keymanapp/developer-utils'; const Namespace = CompilerErrorNamespace.Converter; - const SevInfo = CompilerErrorSeverity.Info | Namespace; +const SevInfo = CompilerErrorSeverity.Info | Namespace; // const SevHint = CompilerErrorSeverity.Hint | Namespace; // const SevWarn = CompilerErrorSeverity.Warn | Namespace; const SevError = CompilerErrorSeverity.Error | Namespace; @@ -53,8 +53,11 @@ export class ConverterMessages { ); static INFO_UnsupportedCharactersDetected = SevInfo | 0x0007; - static Info_UnsupportedCharactersDetected = (o: { inputFilename: string, keymap_index: string, key: string,KeyName:string, output: string; }) => m( - this.INFO_UnsupportedCharactersDetected, `INFO: Input file ${def(o.inputFilename)} contains unsupported character '${def(o.output)}' at keyMap index ${def(o.keymap_index)} on Keycode ${def(o.key)} (${def(o.KeyName)})` + static Info_UnsupportedCharactersDetected = (o: { inputFilename: string, keymap_index: string, key: string, KeyName: string, output: string; }) => m( + this.INFO_UnsupportedCharactersDetected, `INFO: Input file ${def(o.inputFilename)} + contains unsupported character '${def(o.output)} + ' at keyMap index ${def(o.keymap_index)} + on Keycode ${def(o.key)} (${def(o.KeyName)})` ); static ERROR_InvalidFile = SevError | 0x0008; diff --git a/developer/src/kmc-convert/src/converter.ts b/developer/src/kmc-convert/src/converter.ts index 2e9911073a0..646d0de15f8 100644 --- a/developer/src/kmc-convert/src/converter.ts +++ b/developer/src/kmc-convert/src/converter.ts @@ -81,9 +81,9 @@ export class Converter implements KeymanCompiler { } const converter = new ConverterClass(this.callbacks, converterOptions); - const artifacts = await converter.run(inputFilename, outputFilename); + const result = await converter.run(inputFilename, outputFilename); // Note: any subsequent errors in conversion will have been reported by the converter - return artifacts ? { artifacts } : null; + return result ? result : null; } /** diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 49be9e039ef..8463b1a2a84 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -7,19 +7,34 @@ * */ -import { CompilerCallbacks, CompilerOptions } from "@keymanapp/developer-utils"; -import { ConverterToKmnArtifacts } from "../converter-artifacts.js"; +import { CompilerCallbacks, CompilerOptions, KeymanCompilerResult, } from "@keymanapp/developer-utils"; import { KmnFileWriter } from './kmn-file-writer.js'; import { KeylayoutFileReader } from './keylayout-file-reader.js'; import { ConverterMessages } from '../converter-messages.js'; -import { KeylayoutXMLSourceFile } from '@keymanapp/developer-utils'; +import { ConverterArtifacts } from "../converter-artifacts.js"; +import { ConverterToKmnArtifacts } from "../converter-artifacts.js"; +import { KeylayoutXMLSourceFile } from '../../../common/web/utils/src/types/keylayout/keylayout-xml.js'; + + +export interface ConverterResult extends KeymanCompilerResult { + /** + * Internal in-memory build artifacts from a successful compilation. Caller + * can write these to disk with {@link Converter.write} + */ + artifacts: ConverterArtifacts; +}; + +export interface ConverterToKmnResult extends ConverterResult { + /** + * Internal in-memory build artifacts from a successful compilation. Caller + * can write these to disk with {@link Converter.write} + */ + artifacts: ConverterToKmnArtifacts; +}; + + + -/** - * Object holding all important data for the conversion between - * input (*.keylayout) format and output (*.kmn) format. - * It contains input and output filenames, an array of all used modifiers - * and all preprocessed key rules for up to 3 key/modifier combinations. - */ export interface ProcesData { keylayout_filename: string, kmn_filename: string, @@ -51,12 +66,12 @@ export interface ActionStateOutput { */ export function find_usedKeysCount(data: any, pos: number): number { - let usedKeyCount = KeylayoutToKmnConverter.MAX_KEY_COUNT; - if (data.keyboard.keyMapSet[0].keyMap[pos].key.length < usedKeyCount ) { - // set the max to n-1 (keys are zero indexed ) - usedKeyCount = data.keyboard.keyMapSet[0].keyMap[pos].key.length - 1; + let usedKeyCount = KeylayoutToKmnConverter.MAX_KEY_COUNT; + if (data.keyboard.keyMapSet[0].keyMap[pos].key.length < usedKeyCount) { + // set max to n-1 (keys are zero indexed ) + usedKeyCount = data.keyboard.keyMapSet[0].keyMap[pos].key.length - 1; } - return usedKeyCount ; + return usedKeyCount; } export class KeylayoutToKmnConverter { @@ -83,8 +98,7 @@ export class KeylayoutToKmnConverter { * @param outputFilename the resulting keyman .kmn-file * @return null on success */ - async run(inputFilename: string, outputFilename?: string): Promise { - + async run(inputFilename: string, outputFilename?: string): Promise { if (!inputFilename) { this.callbacks.reportMessage(ConverterMessages.Error_FileNotFound({ inputFilename })); @@ -123,16 +137,21 @@ export class KeylayoutToKmnConverter { const kmnFileWriter = new KmnFileWriter(this.callbacks, this.options); - const out_text_ok: boolean = kmnFileWriter.write(outArray); - if (!out_text_ok) { + // write to object/ConverterToKmnResult + const out_Uint8: Uint8Array = kmnFileWriter.write(outArray); + const Result_toBeReturned: ConverterToKmnResult = { + artifacts: { + kmn: { data: out_Uint8, filename: outputFilename } + } + }; + + if (!out_Uint8) { this.callbacks.reportMessage(ConverterMessages.Error_UnableToWrite({ outputFilename })); return null; } - - return null; + return Result_toBeReturned; } - /** * @brief member function to read filename and behaviour of a json object into a ProcesData * @param jsonObj containing filename, behaviour and rules of a json object @@ -148,10 +167,8 @@ export class KeylayoutToKmnConverter { arrayOf_Modifiers: [], arrayOf_Rules: [] }; -//_S2 do I need to "validate again here?" - if ((jsonObj !== null) && (jsonObj.hasOwnProperty("keyboard"))) { - //if ((jsonObj !== null) ) { + if ((jsonObj !== null) && (jsonObj.hasOwnProperty("keyboard"))) { data_object.keylayout_filename = outputfilename.replace(/\.kmn$/, '.keylayout'); data_object.kmn_filename = outputfilename; data_object.arrayOf_Modifiers = modifierBehavior; // ukelele uses behaviours e.g. 18 modifiersCombinations in 8 KeyMapSelect(behaviors) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts index c00330e5d16..31ea2fdc857 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts @@ -23,12 +23,12 @@ export class KmnFileWriter { * @param outputfilename the file that will be written; if no outputfilename is given an outputfilename will be created from data_ukelele.keylayout_filename * @return true if data has been written; false if not */ - public write(data_ukelele: ProcesData): boolean { + public writeToFile(data_ukelele: ProcesData): boolean { let data: string = "\n"; // add top part of kmn file: STORES - data += this.writeData_Stores(data_ukelele); + data += this.write_KmnFileHeader(data_ukelele); // add bottom part of kmn file: RULES data += this.writeData_Rules(data_ukelele); @@ -37,33 +37,21 @@ export class KmnFileWriter { this.callbacks.fs.writeFileSync(data_ukelele.kmn_filename, new TextEncoder().encode(data)); return true; } catch (err) { - this.callbacks.reportMessage(ConverterMessages.Error_OutputFilenameIsRequired()); + this.callbacks.reportMessage(ConverterMessages.Error_UnableToWrite({outputFilename: data_ukelele.kmn_filename})); return false; } } - public writeToString(data_ukelele: ProcesData): string { - let data: string = "\n"; - - // add top part of kmn file: STORES - data += this.writeData_Stores(data_ukelele); - - // add bottom part of kmn file: RULES - data += this.writeData_Rules(data_ukelele); - - try { - return data; - } catch (err) { - this.callbacks.reportMessage(ConverterMessages.Error_OutputFilenameIsRequired()); - return null; - } - } - - public writeToUint8Array(data_ukelele: ProcesData): Uint8Array { + /** + * @brief member function to write data from object to a Uint8Array + * @param data_ukelele the array holding all keyboard data + * @return a Uint8Array holding data + */ + public write(data_ukelele: ProcesData): Uint8Array { let data: string = "\n"; // add top part of kmn file: STORES - data += this.writeData_Stores(data_ukelele); + data += this.write_KmnFileHeader(data_ukelele); // add bottom part of kmn file: RULES data += this.writeData_Rules(data_ukelele); @@ -71,17 +59,17 @@ export class KmnFileWriter { try { return new TextEncoder().encode(data); } catch (err) { - this.callbacks.reportMessage(ConverterMessages.Error_OutputFilenameIsRequired()); + this.callbacks.reportMessage(ConverterMessages.Error_UnableToWrite({outputFilename: data_ukelele.kmn_filename})); return null; } } /** - * @brief member function to create data for stores that will be printed to the resulting kmn file + * @brief member function to create data for the header (stores) that will be printed to the resulting kmn file * @param data_ukelele an object containing all data read from a .keylayout file * @return string - all stores to be printed */ - public writeData_Stores(data_ukelele: ProcesData): string { + public write_KmnFileHeader(data_ukelele: ProcesData): string { let data: string = ""; @@ -114,6 +102,9 @@ export class KmnFileWriter { let data: string = ""; // filter array of all rules and remove duplicates + // during the process of creating Rule[], duplicate rules might occur + // (e.g. when in a keylayout file the same modifiers occur in several behaviors thus producing the same rules). + // This is to filter out those duplicate Rule objects const unique_data_Rules: Rule[] = data_ukelele.arrayOf_Rules.filter((curr) => { return (!(curr.output === new TextEncoder().encode("") || curr.output === undefined) && (curr.key !== "") @@ -416,7 +407,8 @@ export class KmnFileWriter { /** * @brief member function to review rules for acceptable modifiers, duplicate or ambiguous rules and return an array containing possible warnings. - * Definition of comparisons e.g. 1-1, 2-4, 6-6 + * Keyman can not handle duplicate rules so we need to make sure a rule is written only once by either omitting a duplicate rule or commenting out an ambiguous rule. + * Omitting rules and definition of comparisons e.g. 1-1, 2-4, 6-6 * see https://docs.google.com/document/d/12J3NGO6RxIthCpZDTR8FYSRjiMgXJDLwPY2z9xqKzJ0/edit?tab=t.0#heading=h.pcz8rjyrl5ug * @param rule : Rule[] - an array of all rules * @param index the index of a rule in array[rule] diff --git a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts index a7ea37b70f5..806558cb57a 100644 --- a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts +++ b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts @@ -22,71 +22,8 @@ describe('KmnFileWriter', function () { compilerTestCallbacks.clear(); }); - describe("write() ", function () { - const inputFilename = makePathToFixture('../data/Test.keylayout'); - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); - const read = sut_r.read(inputFilename); - const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); - - // empty ProcesData from unavailable file name - const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); - const read_unavailable = sut_r.read(inputFilename_unavailable); - const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); - - it('write() should return true (no error) if written', async function () { - const result = sut_w.write(converted); - assert.isTrue(result); - }); - - it('write() should return false if no inputfile', async function () { - const result = sut_w.write(converted_unavailable); - assert.isFalse(result); - }); - - }); - - describe("writeToString() ", function () { - const inputFilename = makePathToFixture('../data/Test.keylayout'); - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); - const read = sut_r.read(inputFilename); - const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); - - const out_expected_first: string = "c ..................................................................................................................\n" - + "c ..................................................................................................................\n" - + "c Keyman keyboard generated by kmn-convert version: " + KEYMAN_VERSION.VERSION + "\n" - + "c from Ukelele file: "; - const out_expected_last: string = "\n" - + "c ..................................................................................................................\n" - + "c ..................................................................................................................\n" - + "\n" - + "store(&TARGETS) 'desktop'\n" - + "\n" - + "begin Unicode > use(main)\n\n" - + "group(main) using keys\n\n" - + "\n"; - - // empty ProcesData from unavailable file name - const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); - const read_unavailable = sut_r.read(inputFilename_unavailable); - const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); - - it('writeToString() should return result', async function () { - const result = sut_w.writeToString(converted); - assert.isNotNull(result); - }); - - it('writeToString() should return header in case of missing inputfile', async function () { - const result = sut_w.writeToString(converted_unavailable); - assert.equal(result, ("\n" + out_expected_first + out_expected_last)); - }); - }); - - describe("writeToUint8Array() ", function () { + describe("write() ", function () { const inputFilename = makePathToFixture('../data/Test.keylayout'); const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); @@ -94,13 +31,12 @@ describe('KmnFileWriter', function () { const read = sut_r.read(inputFilename); const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); - const out_expected_first: string = + const out_expected: string = "c ..................................................................................................................\n" + "c ..................................................................................................................\n" + "c Keyman keyboard generated by kmn-convert version: " + KEYMAN_VERSION.VERSION + "\n" - + "c from Ukelele file: "; - - const out_expected_last: string = "\n" + + "c from Ukelele file: " + + "\n" + "c ..................................................................................................................\n" + "c ..................................................................................................................\n" + "\n" @@ -115,13 +51,13 @@ describe('KmnFileWriter', function () { const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); const read_unavailable = sut_r.read(inputFilename_unavailable); const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); - it('writeToUint8Array() should return header in case of missing inputfile', async function () { - const result = sut_w.writeToUint8Array(converted_unavailable); - assert.equal(new TextDecoder().decode(result), ("\n" + out_expected_first + out_expected_last)); + it('write() should return header in case of missing inputfile', async function () { + const result = sut_w.write(converted_unavailable); + assert.equal(new TextDecoder().decode(result), ("\n" + out_expected)); }); - it('writeToUint8Array() should return result', async function () { - const result = sut_w.writeToUint8Array(converted); + it('write() should return result', async function () { + const result = sut_w.write(converted); assert.isNotNull(result); }); }); @@ -151,7 +87,7 @@ describe('KmnFileWriter', function () { }); - describe("writeData_Stores() ", function () { + describe("write_KmnFileHeader() ", function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); @@ -186,18 +122,18 @@ describe('KmnFileWriter', function () { + "group(main) using keys\n\n" + "\n"; - it(('writeData_Stores should return store text with filename ').padEnd(62, " ") + 'on correct input', async function () { - const written_correctName = sut_w.writeData_Stores(converted); + it(('write_KmnFileHeader should return store text with filename ').padEnd(62, " ") + 'on correct input', async function () { + const written_correctName = sut_w.write_KmnFileHeader(converted); assert.equal(written_correctName, (out_expected_first + converted.keylayout_filename + out_expected_last)); }); - it(('writeData_Stores should return store text without filename ').padEnd(62, " ") + 'on empty input', async function () { - const written_emptyName = sut_w.writeData_Stores(converted_empty); + it(('write_KmnFileHeader should return store text without filename ').padEnd(62, " ") + 'on empty input', async function () { + const written_emptyName = sut_w.write_KmnFileHeader(converted_empty); assert.equal(written_emptyName, (out_expected_first + out_expected_last)); }); - it(('writeData_Stores should return store text without filename ').padEnd(62, " ") + 'on only filename as input', async function () { - const written_onlyName = sut_w.writeData_Stores(converted_unavailable); + it(('write_KmnFileHeader should return store text without filename ').padEnd(62, " ") + 'on only filename as input', async function () { + const written_onlyName = sut_w.write_KmnFileHeader(converted_unavailable); assert.equal(written_onlyName, (out_expected_first + converted_unavailable.keylayout_filename + out_expected_last)); }); }); @@ -502,7 +438,7 @@ describe('KmnFileWriter', function () { }); }); - describe('write form intermediate data array', function () { + describe('write from intermediate data array', function () { const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); [ [ From 57c01ae0386db61d7fcbf7ad9553e1bdcabbf995 Mon Sep 17 00:00:00 2001 From: Sabine Date: Mon, 25 Aug 2025 10:41:02 +0200 Subject: [PATCH 169/251] remove unused function --- .../src/keylayout-to-kmn/kmn-file-writer.ts | 25 ------------------- 1 file changed, 25 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts index 31ea2fdc857..b27734db3de 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts @@ -17,31 +17,6 @@ export class KmnFileWriter { constructor(private callbacks: CompilerCallbacks, private options: CompilerOptions) { }; - /** - * @brief member function to write data from object to a kmn file - * @param data_ukelele the array holding all keyboard data - * @param outputfilename the file that will be written; if no outputfilename is given an outputfilename will be created from data_ukelele.keylayout_filename - * @return true if data has been written; false if not - */ - public writeToFile(data_ukelele: ProcesData): boolean { - - let data: string = "\n"; - - // add top part of kmn file: STORES - data += this.write_KmnFileHeader(data_ukelele); - - // add bottom part of kmn file: RULES - data += this.writeData_Rules(data_ukelele); - - try { - this.callbacks.fs.writeFileSync(data_ukelele.kmn_filename, new TextEncoder().encode(data)); - return true; - } catch (err) { - this.callbacks.reportMessage(ConverterMessages.Error_UnableToWrite({outputFilename: data_ukelele.kmn_filename})); - return false; - } - } - /** * @brief member function to write data from object to a Uint8Array * @param data_ukelele the array holding all keyboard data From d5996b9b4f755bedf7220a66c92742bd303dd70d Mon Sep 17 00:00:00 2001 From: Sabine Date: Mon, 25 Aug 2025 10:57:38 +0200 Subject: [PATCH 170/251] feat(developer): layout of error-msg --- .../src/kmc-convert/src/converter-messages.ts | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/developer/src/kmc-convert/src/converter-messages.ts b/developer/src/kmc-convert/src/converter-messages.ts index bc411300cc2..6a9b78082d2 100644 --- a/developer/src/kmc-convert/src/converter-messages.ts +++ b/developer/src/kmc-convert/src/converter-messages.ts @@ -29,39 +29,39 @@ export class ConverterMessages { ); static ERROR_FileNotFound = SevError | 0x0003; - static Error_FileNotFound = (o: { inputFilename: string; }) => m( - this.ERROR_FileNotFound, `Input filename '${def(o.inputFilename)} - ' does not exist or could not be loaded.` - ); + static Error_FileNotFound = + (o: { inputFilename: string; }) => m( + this.ERROR_FileNotFound, + `Input filename '${def(o.inputFilename)} ' does not exist or could not be loaded.` + ); static ERROR_UnableToRead = SevError | 0x0004; static Error_UnableToRead = (o: { inputFilename: string; }) => m( - this.ERROR_UnableToRead, `Input file '${def(o.inputFilename)} - ' could not be read.` + this.ERROR_UnableToRead, + `Input file '${def(o.inputFilename)} ' could not be read.` ); static ERROR_UnableToConvert = SevError | 0x0005; static Error_UnableToConvert = (o: { inputFilename: string; }) => m( - this.ERROR_UnableToConvert, `Input file '${def(o.inputFilename)} - ' could not be converted.` + this.ERROR_UnableToConvert, + `Input file '${def(o.inputFilename)} ' could not be converted.` ); static ERROR_UnableToWrite = SevError | 0x0006; static Error_UnableToWrite = (o: { outputFilename: string; }) => m( - this.ERROR_UnableToWrite, `Output file for '${def(o.outputFilename)} - ' could not be written.` + this.ERROR_UnableToWrite, + `Output file for '${def(o.outputFilename)} ' could not be written.` ); static INFO_UnsupportedCharactersDetected = SevInfo | 0x0007; static Info_UnsupportedCharactersDetected = (o: { inputFilename: string, keymap_index: string, key: string, KeyName: string, output: string; }) => m( - this.INFO_UnsupportedCharactersDetected, `INFO: Input file ${def(o.inputFilename)} - contains unsupported character '${def(o.output)} - ' at keyMap index ${def(o.keymap_index)} - on Keycode ${def(o.key)} (${def(o.KeyName)})` + this.INFO_UnsupportedCharactersDetected, + `INFO: Input file ${def(o.inputFilename)} contains unsupported character '${def(o.output)} ' at keyMap index ${def(o.keymap_index)} on Keycode ${def(o.key)} (${def(o.KeyName)})` ); static ERROR_InvalidFile = SevError | 0x0008; static Error_InvalidFile = (o: { errorText: string; }) => m( - this.ERROR_InvalidFile, `The source file has an invalid structure: ${def(o.errorText)}` + this.ERROR_InvalidFile, + `The source file has an invalid structure: ${def(o.errorText)}` ); } From b94c3367961c7290f472c8dd36e7ae4929ea734d Mon Sep 17 00:00:00 2001 From: Sabine Date: Mon, 25 Aug 2025 15:24:49 +0200 Subject: [PATCH 171/251] feat(developer): move callbacks.reportMessage --- .../keylayout-to-kmn/keylayout-file-reader.ts | 10 ++--- .../keylayout-to-kmn-converter.ts | 42 +++++++------------ .../src/keylayout-to-kmn/kmn-file-writer.ts | 2 +- .../test/keylayout-to-kmn-converter.tests.ts | 27 ++---------- 4 files changed, 25 insertions(+), 56 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts index 9d69218bb77..bd7dd4761c4 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts @@ -39,8 +39,8 @@ export class KeylayoutFileReader { /** * If object contains attribute #text it will be removed. - * @param o Object with possible property #text - * @return objects that do not contain property #text + * @param o Object with possible property #text containing whitespaces + * @return objects that do not contain property #text */ public remove_whitespace(o: any): void { if (o['#text']) { @@ -50,7 +50,7 @@ export class KeylayoutFileReader { /** * @brief wrapper to remove whitespace and box single-entry objects into arrays - * @param o Object with property to box/remove whitespace from + * @param o Object with property to box/remove whitespaces from * @param x Name of element to box * @return objects that contain only boxed arrays */ @@ -63,7 +63,7 @@ export class KeylayoutFileReader { /** * @brief member function to box single-entry objects into arrays * @param source the object to be changed - * @return objects that contain only boxed arrays + * @return object that contain only boxed arrays */ public boxArray(source: any) { @@ -101,7 +101,7 @@ export class KeylayoutFileReader { } /** - * @brief member function to parse data from a .keylayout-file and store to a json object + * @brief member function to parse data from a .keylayout-file and store in a json object * we need to be able to ignore an output character of "", process an output character of " " (space) and allow surrounding whitespace in #text (which will be removed later) * @param inputFilename the ukelele .keylayout-file to be parsed * @return in case of success: json object containing data of the .keylayout file; else null diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 8463b1a2a84..82bb26d9e1b 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -78,7 +78,7 @@ export class KeylayoutToKmnConverter { static readonly INPUT_FILE_EXTENSION = '.keylayout'; static readonly OUTPUT_FILE_EXTENSION = '.kmn'; static readonly SKIP_COMMENTED_LINES = false; - static readonly MAX_CTRL_CHARACTER = 32; + static readonly MAX_CTRL_CHARACTER = 0x20; // the hightest control character we print out as a Unicode CodePoint static readonly MAX_KEY_COUNT = 49; // At most we use key Nr 0 (A) -> key Nr 49 (Space) static USE_KEY_COUNT = KeylayoutToKmnConverter.MAX_KEY_COUNT; // we use key Nr 0 (A) -> highest available key of .keylayout file @@ -122,34 +122,20 @@ export class KeylayoutToKmnConverter { return null; } - if (!jsonO) { - this.callbacks.reportMessage(ConverterMessages.Error_UnableToRead({ inputFilename })); - return null; - } - outputFilename = outputFilename ?? inputFilename.replace(/\.keylayout$/, '.kmn'); const outArray: ProcesData = await this.convert(jsonO, outputFilename); - if (outArray.arrayOf_Rules.length === 0) { - this.callbacks.reportMessage(ConverterMessages.Error_UnableToConvert({ inputFilename })); - return null; - } const kmnFileWriter = new KmnFileWriter(this.callbacks, this.options); // write to object/ConverterToKmnResult const out_Uint8: Uint8Array = kmnFileWriter.write(outArray); - const Result_toBeReturned: ConverterToKmnResult = { + const result: ConverterToKmnResult = { artifacts: { kmn: { data: out_Uint8, filename: outputFilename } } }; - - if (!out_Uint8) { - this.callbacks.reportMessage(ConverterMessages.Error_UnableToWrite({ outputFilename })); - return null; - } - return Result_toBeReturned; + return result; } /** @@ -189,12 +175,16 @@ export class KeylayoutToKmnConverter { // fill rules into arrayOf_Rules of data_object return this.createRuleData(data_object, jsonObj); } - return data_object; + else { + const inputFilename = data_object.keylayout_filename; + this.callbacks.reportMessage(ConverterMessages.Error_UnableToConvert({ inputFilename })); + return data_object; + } } /** * @brief member function to read the rules contained in a json object and add array of Rules[] to an ProcesData - * @param data_ukelele: an object containing the name of the input file, an array of behaviours and an (empty) array of Rules + * @param data_ukelele: an object containing the name of the in/output file, an array of behaviours and an (empty) array of Rules * @param jsonObj: json Object containing all data read from a keylayout file * @return an object containing the name of the input file, an array of behaviours and a populated array of Rules[] */ @@ -215,8 +205,6 @@ export class KeylayoutToKmnConverter { this.callbacks.reportMessage(ConverterMessages.Error_InvalidFile({ errorText })); } - // loop keys 0-49 (= all keys we use) - //for (let j = 0; j <= KeylayoutToKmnConverter.MAX_KEY_COUNT; j++) { for (let j = 0; j <= KeylayoutToKmnConverter.MAX_KEY_COUNT; j++) { // loop behaviors (in ukelele it is possible to define multiple modifier combinations that behave in the same way) @@ -500,7 +488,7 @@ export class KeylayoutToKmnConverter { /** * @brief member function to review data in array of Rules[] of data_ukelele: remove duplicate rules and mark first occurance of a rule in object_array - * @param data_ukelele: an object containing the name of the input file, an array of behaviours and an array of Rules + * @param data_ukelele: an object containing the name of the in/output file, an array of behaviours and an array of Rules * @return an object containing the name of the input file, an array of behaviours and the revised array of Rules[] */ public reviewRuleInputData(data_ukelele: ProcesData): ProcesData { @@ -697,14 +685,14 @@ export class KeylayoutToKmnConverter { /** * @brief member function to check if CAPS is used throughout a keylayout file or not * @param keylayout_modifier the modifier string used in the .keylayout-file - * @return kmn_modifier the modifier string used in the .kmn-file + * @return kmn_modifier: the modifier string used in the .kmn-file */ public checkIfCapsIsUsed(keylayout_modifier: string[][]): boolean { return JSON.stringify(keylayout_modifier).toUpperCase().includes("CAPS"); } /** - * @brief member function to check if a modifier can be used in keyman + * @brief member function to check if a modifier can be used in Keyman * @param keylayout_modifier the modifier string used in the .keylayout-file * @return true if the modifier can be used in keyman; false if not */ @@ -739,7 +727,7 @@ export class KeylayoutToKmnConverter { /** * @brief member function to map Ukelele keycodes to Windows Keycodes * @param pos Ukelele (=mac) keycodes - * @return keycode on a Windows Keyboard + * @return VK */ public map_UkeleleKC_To_VK(pos: number): string { const vk = [ @@ -821,7 +809,7 @@ export class KeylayoutToKmnConverter { * @brief member function to find the actionID of a certain state-next pair * @param data :any an object containing all data read from a .keylayout file * @param search :string value 'next' to be found - * @return a string containing the actionId of a certain state-next pair + * @return a string containing the actionId of a certain state(none)-next pair */ public get_ActionID__From__ActionNext(data: any, search: string): string { if (search !== "none") { @@ -840,7 +828,7 @@ export class KeylayoutToKmnConverter { * @brief member function to create an array of (modifier) behaviours for a given keycode in [{keycode,modifier}] * @param data : any - an object containing all data read from a .keylayout file * @param search : KeylayoutFileData[] - an array[{keycode,modifier}] to be found - * @return an array: string[] containing modifiers + * @return a string[] containing modifiers */ public get_Modifier_array__From__KeyModifier_array(data: any, search: KeylayoutFileData[]): string[] { const returnString1D: string[] = []; diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts index b27734db3de..84c1276128b 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts @@ -386,7 +386,7 @@ export class KmnFileWriter { * Omitting rules and definition of comparisons e.g. 1-1, 2-4, 6-6 * see https://docs.google.com/document/d/12J3NGO6RxIthCpZDTR8FYSRjiMgXJDLwPY2z9xqKzJ0/edit?tab=t.0#heading=h.pcz8rjyrl5ug * @param rule : Rule[] - an array of all rules - * @param index the index of a rule in array[rule] + * @param index the index of a rule in Rule[] * @return a string[] containing possible warnings for a rule */ public reviewRules(rule: Rule[], index: number): string[] { diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index 897fe4e935b..a546b20b522 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -22,27 +22,6 @@ describe('KeylayoutToKmnConverter', function () { compilerTestCallbacks.clear(); }); - // todo remove - describe('RunAllFiles', function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - [ - [makePathToFixture('../data/Italian.keylayout')], - [makePathToFixture('../data/Italian_command.keylayout')], - [makePathToFixture('../data/Swiss_French.keylayout')], - [makePathToFixture('../data/Spanish.keylayout')], - [makePathToFixture('../data/Swiss_German.keylayout')], - [makePathToFixture('../data/US.keylayout')], - [makePathToFixture('../data/Polish.keylayout')], - [makePathToFixture('../data/French.keylayout')], - [makePathToFixture('../data/Latin_American.keylayout')], - // [makePathToFixture('../data/German_complete.keylayout')], - [makePathToFixture('../data/German_complete_reduced.keylayout')], - // [makePathToFixture('../data/German_Standard.keylayout')], - ].forEach(function (files_) { - sut.run(files_[0]); - assert.isTrue(true); - }); - }); describe('RunTestFiles resulting in errors ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); [ @@ -178,16 +157,18 @@ describe('KeylayoutToKmnConverter', function () { describe('convert() ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); + + // ProcesData from usable file const inputFilename = makePathToFixture('../data/Test.keylayout'); const read = sut_r.read(inputFilename); const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); - // ProcesData from unavailable file name + // ProcesData from unavailable file const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); const read_unavailable = sut_r.read(inputFilename_unavailable); const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); - // ProcesData from empty filename + // ProcesData from empty file const inputFilename_empty = makePathToFixture(''); const read_empty = sut_r.read(inputFilename_empty); const converted_empty = sut.convert_bound.convert(read_empty, inputFilename_empty); From 3d60a6cd6c02683264936e326af2f1f488993135 Mon Sep 17 00:00:00 2001 From: Sabine Date: Fri, 29 Aug 2025 09:54:33 +0200 Subject: [PATCH 172/251] chore(developer): update kmc-convert create_keylayout_schema.sh with new builder-basic.inc.sh --- resources/standards-data/keylayout/create_keylayout_schema.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/standards-data/keylayout/create_keylayout_schema.sh b/resources/standards-data/keylayout/create_keylayout_schema.sh index a782fba4a65..92815832f6c 100755 --- a/resources/standards-data/keylayout/create_keylayout_schema.sh +++ b/resources/standards-data/keylayout/create_keylayout_schema.sh @@ -11,7 +11,7 @@ set -eu ## START STANDARD BUILD SCRIPT INCLUDE # adjust relative paths as necessary THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" -. "${THIS_SCRIPT%/*}/../../../resources/build/build-utils.sh" +. "${THIS_SCRIPT%/*}/../../../resources/build/builder-basic.inc.sh" ## END STANDARD BUILD SCRIPT INCLUDE . "$KEYMAN_ROOT/resources/build/jq.inc.sh" From bfcff5c0b8f76b0b423a0ea2b7cc00c552cae993 Mon Sep 17 00:00:00 2001 From: Sabine Date: Tue, 2 Sep 2025 16:15:31 +0200 Subject: [PATCH 173/251] feat(developer): move kmcConvert-util functions from util to kmn-file-writer.ts --- common/web/types/src/util/util.ts | 100 ------------------ .../src/keylayout-to-kmn/kmn-file-writer.ts | 100 ++++++++++++++++-- 2 files changed, 92 insertions(+), 108 deletions(-) diff --git a/common/web/types/src/util/util.ts b/common/web/types/src/util/util.ts index e9d4060ed0a..546a35cd795 100644 --- a/common/web/types/src/util/util.ts +++ b/common/web/types/src/util/util.ts @@ -207,106 +207,6 @@ export function describeCodepoint(ch: number): string { return `${s} (U+${Number(ch).toString(16).toUpperCase()})`; } -/** - * @brief function to convert a Html-Entity Hex value to a unicode character e.g. c -> c; 😎 -> 😎 - * @param hex_Entity the value that will converted - * @return a unicode character or undefined if in_str is not recognized - */ -export function decodeHexEntity(hex_Entity: string) { - const hex = hex_Entity.replace('&#x', '').replace(';', ''); - if (hex_Entity.length > 9) - return undefined; - else - return String.fromCodePoint(parseInt(hex, 16)); -} - -/** - * @brief function to convert a Html-Entity decimal value value to a unicode character e.g. c -> c; 😎 -> 😎 - * @param dec_Entity the value that will converted - * @return a unicode character or undefined if in_str is not recognized - */ -export function decodeDecEntity(dec_Entity: string) { - const dec = dec_Entity.replace('&#', '').replace(';', ''); - if (dec_Entity.length > 9) - return undefined; - else - return String.fromCodePoint(parseInt(dec, 10)); -} - -/** - * @brief function to convert a unicode hex value to a unicode character e.g. U+0063 -> c; U+1F60E; -> 😎 - * @param Uni_Val the value that will converted - * @return a unicode character or undefined if in_str is not recognized - */ -export function decodeUniHexValue(Uni_Val: string): any { - const hexval = Uni_Val.replace('U+', '0x'); - if (Uni_Val.length > 8) - return undefined; - else - return String.fromCodePoint(parseInt(hexval, 16)); -} - -/** - * @brief function to convert a numeric character reference or a unicode value to a unicode character e.g. c -> c; U+1F60E -> 😎 - * @param in_str the value that will converted - * @return a unicode character like 'c', 'ሴ', '😎' or undefined if in_str is not recognized - */ -export function convertToUnicodeCharacter(in_str: string): string { - - if ((in_str === null) || (in_str === undefined)) { - return undefined; - } - - else if (in_str.substring(0, 3) === "&#x") { - return decodeHexEntity(in_str); - } - - else if (in_str.substring(0, 2) === "&#") { - return decodeDecEntity(in_str); - } - - else if (in_str.substring(0, 1) === "&") { - return undefined; - } - - else if (in_str.substring(0, 2) === "U+") { - return decodeUniHexValue(in_str); - } - - else if ([...new Intl.Segmenter().segment(in_str)].length <= 1) { - return in_str; - } - else { - return undefined; - } -} -/** - * @brief function to convert a numeric character reference to a unicode Code Point e.g. ሴ -> U+1234; 􏘁 -> U+1F60E - * @param instr the value that will converted - * @return returns a unicode Code Point like U+0063, U+1234, U+1F60E; returns the input character if a non-numeric reference is used or returns 'undefined' if instr is not recognized - */ -export function convertToUnicodeCodePoint(instr: string): string { - - if ((instr === null) || (instr === undefined)) { - return undefined; - } - - if (instr.substring(0, 3) === "&#x") { - const num_length = instr.length - instr.indexOf("x") - 1; - const num_str = instr.substring(instr.indexOf("x") + 1, instr.length - 1); - return ("U+" + num_str.slice(-num_length).padStart(4, "0")); - } - - // if not hex: convert to hex - if ((instr.substring(0, 2) === "&#")) { - const num_length = instr.length - instr.indexOf("#") - 1; - const num_str = instr.substring(instr.indexOf("#") + 1, instr.length - 1); - return "U+" + Number(num_str.slice(-num_length)).toString(16).slice(-6).toUpperCase().padStart(4, "0"); - } - else - return instr; -} - export enum BadStringType { pua = 'PUA', unassigned = 'Unassigned', diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts index 84c1276128b..34e57a11c8f 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts @@ -9,7 +9,6 @@ import { CompilerCallbacks, CompilerOptions } from "@keymanapp/developer-utils"; import { KeylayoutToKmnConverter, ProcesData, Rule } from './keylayout-to-kmn-converter.js'; -import { util } from '@keymanapp/common-types'; import { ConverterMessages } from '../converter-messages.js'; import KEYMAN_VERSION from "@keymanapp/keyman-version"; @@ -34,7 +33,7 @@ export class KmnFileWriter { try { return new TextEncoder().encode(data); } catch (err) { - this.callbacks.reportMessage(ConverterMessages.Error_UnableToWrite({outputFilename: data_ukelele.kmn_filename})); + this.callbacks.reportMessage(ConverterMessages.Error_UnableToWrite({ outputFilename: data_ukelele.kmn_filename })); return null; } } @@ -140,8 +139,10 @@ export class KmnFileWriter { const warn_text = this.reviewRules(unique_data_Rules, k); const output_character = new TextDecoder().decode(unique_data_Rules[k].output); - const output_Unicode_Character = util.convertToUnicodeCharacter(output_character); - const output_Unicode_CodePoint = util.convertToUnicodeCodePoint(output_character); + // const output_Unicode_Character = util.convertToUnicodeCharacter(output_character); + // const output_Unicode_CodePoint = util.convertToUnicodeCodePoint(output_character); + const output_Unicode_Character = this.convertToUnicodeCharacter(output_character); + const output_Unicode_CodePoint = this.convertToUnicodeCodePoint(output_character); if ((output_Unicode_Character !== undefined) && (output_Unicode_CodePoint !== undefined)) { @@ -205,8 +206,10 @@ export class KmnFileWriter { const warn_text = this.reviewRules(unique_data_Rules, k); const output_character = new TextDecoder().decode(unique_data_Rules[k].output); - const output_Unicode_Character = util.convertToUnicodeCharacter(output_character); - const output_Unicode_CodePoint = util.convertToUnicodeCodePoint(output_character); + // const output_Unicode_Character = util.convertToUnicodeCharacter(output_character); + // const output_Unicode_CodePoint = util.convertToUnicodeCodePoint(output_character); + const output_Unicode_Character = this.convertToUnicodeCharacter(output_character); + const output_Unicode_CodePoint = this.convertToUnicodeCodePoint(output_character); if ((output_Unicode_Character !== undefined) && (output_Unicode_CodePoint !== undefined)) { // if we are about to print a unicode codepoint instead of a single character we need to check if it is a control character @@ -291,8 +294,10 @@ export class KmnFileWriter { const warn_text = this.reviewRules(unique_data_Rules, k); const output_character = new TextDecoder().decode(unique_data_Rules[k].output); - const output_Unicode_Character = util.convertToUnicodeCharacter(output_character); - const output_Unicode_CodePoint = util.convertToUnicodeCodePoint(output_character); + //const output_Unicode_Character = util.convertToUnicodeCharacter(output_character); + //const output_Unicode_CodePoint = util.convertToUnicodeCodePoint(output_character); + const output_Unicode_Character = this.convertToUnicodeCharacter(output_character); + const output_Unicode_CodePoint = this.convertToUnicodeCodePoint(output_character); if ((output_Unicode_Character !== undefined) && (output_Unicode_CodePoint !== undefined)) { // if we are about to print a unicode codepoint instead of a single character we need to check if a control character is to be used @@ -877,4 +882,83 @@ export class KmnFileWriter { } return warningTextArray; } + + + /** + * @brief function to convert a numeric character reference or a unicode value to a unicode character e.g. c -> c; U+1F60E -> 😎 + * @param inputString the value that will converted + * @return a unicode character like 'c', 'ሴ', '😎' or undefined if inputString is not recognized + */ + public convertToUnicodeCharacter(inputString: string): string { + + if ((inputString === null) || (inputString === undefined)) { + return undefined; + } + + // e.g. U+0061 U+1234 U+1F60E + else if (inputString.match(/^U\+([0-9a-f]{2,6})$/i)) { + return String.fromCodePoint(parseInt((inputString.match(/^U\+([0-9a-f]{2,6})$/i))[1], 16)); + } + + // e.g. a ሴ 😎 + else if (inputString.match(/^&#x([0-9a-f]{2,6});$/i)) { + return String.fromCodePoint(parseInt((inputString.match(/^&#x([0-9a-f]{2,6});$/i))[1], 16)); + } + + // e.g. a ሴ 😆 + else if (inputString.match(/^&#([0-9a-f]{2,6});$/i)) { + return String.fromCodePoint(parseInt((inputString.match(/^&#([0-9a-f]{2,6});$/i))[1], 10)); + } + + // e.g. > " + else if (inputString.match(/^&([a-z]{1,4});$/i)) { + if (inputString === '>') { return '>'; } + else if (inputString === '<') { return '<'; } + else if (inputString === '&') { return '&'; } + else if (inputString === ''') { return "'"; } + else if (inputString === '"') { return '"'; } + else return undefined; + } + + // 'A' or "B" have length=1 and segment-length=1 and will be used. + // "ẘ" or "😎" have length=2 but segment-length=1 and will be used. + // "ab" has length=2 and segment-length=2 and will not be used. + else if ([...new Intl.Segmenter().segment(inputString)].length <= 1) { + return inputString; + } + else { + return undefined; + } + } + + /** + * @brief function to convert a numeric character reference to a unicode Code Point e.g. ሴ -> U+1234; 􏘁 -> U+1F60E + * @param instr the value that will converted + * @return returns a unicode Code Point like U+0063, U+1234, U+1F60E; returns the input character if a non-numeric reference is used or returns 'undefined' if instr is not recognized + */ + public convertToUnicodeCodePoint(instr: string): string { + + if ((instr === null) || (instr === undefined)) { + return undefined; + } + + if (instr.substring(0, 3) === "&#x") { + const num_length = instr.length - instr.indexOf("x") - 1; + const num_str = instr.substring(instr.indexOf("x") + 1, instr.length - 1); + return ("U+" + num_str.slice(-num_length).padStart(4, "0")); + } + + // if not hex: convert to hex + if ((instr.substring(0, 2) === "&#")) { + const num_length = instr.length - instr.indexOf("#") - 1; + const num_str = instr.substring(instr.indexOf("#") + 1, instr.length - 1); + return "U+" + Number(num_str.slice(-num_length)).toString(16).slice(-6).toUpperCase().padStart(4, "0"); + } + else + return instr; + } + + + + } From 754343b2a71de8a5c0dd9874de394a1d85e9aa2f Mon Sep 17 00:00:00 2001 From: Sabine Date: Tue, 2 Sep 2025 17:52:05 +0200 Subject: [PATCH 174/251] feat(developer): use convertToUnicodeCodePoint,convertToUnicodeCharacter from kmn-file-writer.ts --- .../src/kmc-convert/test/kmn-file-writer.tests.ts | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts index 806558cb57a..c2555f2bcd7 100644 --- a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts +++ b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts @@ -9,7 +9,6 @@ import 'mocha'; import { assert } from 'chai'; -import { util } from '@keymanapp/common-types'; import KEYMAN_VERSION from "@keymanapp/keyman-version"; import { compilerTestCallbacks, compilerTestOptions, makePathToFixture } from './helpers/index.js'; import { KeylayoutToKmnConverter, ProcesData, Rule } from '../src/keylayout-to-kmn/keylayout-to-kmn-converter.js'; @@ -139,6 +138,7 @@ describe('KmnFileWriter', function () { }); describe('convertToUnicodeCodePoint ', function () { + const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); [ ["􏘁", 'U+10F601'], ["😁", 'U+1F601'], @@ -161,13 +161,14 @@ describe('KmnFileWriter', function () { [' ;', ' ;'] ].forEach(function (values) { it(('should convert "' + values[0] + '"').padEnd(25, " ") + 'to "' + values[1] + '"', async function () { - const result = util.convertToUnicodeCodePoint(values[0] as string); + const result = sut_w.convertToUnicodeCodePoint(values[0] as string); assert.equal(result, values[1]); }); }); }); describe('convertToUnicodeCharacter ', function () { + const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); [ ["a", 'a'], ["ሴ", 'ሴ'], @@ -177,8 +178,8 @@ describe('KmnFileWriter', function () { ["ሴ", 'ሴ'], ["😆", '😆'], ["󴉀", undefined], - ["U+0061;", 'a'], - ["U+1234;", 'ሴ'], + ["U+0061", 'a'], + ["U+1234", 'ሴ'], ["U+1F60E", '😎'], ["U+1000000;", undefined], ["@", undefined], @@ -192,7 +193,7 @@ describe('KmnFileWriter', function () { [null, undefined] ].forEach(function (values) { it(('should convert "' + values[0] + '"').padEnd(25, " ") + 'to "' + values[1] + '"', async function () { - const result = util.convertToUnicodeCharacter(values[0] as string); + const result = sut_w.convertToUnicodeCharacter(values[0] as string); assert.equal(result, values[1]); }); }); From ad1d30af679786b630f26d7c9804e7b46e37cdbc Mon Sep 17 00:00:00 2001 From: Sabine Date: Thu, 8 Jan 2026 11:34:06 +0100 Subject: [PATCH 175/251] feat(developer): add ameliorated version of new file convert-utils.ts --- .../src/kmc-convert/src/convert-utils.ts | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 developer/src/kmc-convert/src/convert-utils.ts diff --git a/developer/src/kmc-convert/src/convert-utils.ts b/developer/src/kmc-convert/src/convert-utils.ts new file mode 100644 index 00000000000..7d086b80ed7 --- /dev/null +++ b/developer/src/kmc-convert/src/convert-utils.ts @@ -0,0 +1,85 @@ + +/* + * Keyman is 2025 copyright (C) SIL International. MIT License. + * + * Created by S. Schmitt on 2025-08-24 + * + * functions for kmc-convert utils + * + */ + +/** + * @brief function to convert a numeric character reference or a unicode value to a unicode character e.g. c -> c; U+1F60E -> 😎 + * @param inputString the value that will converted + * @return a unicode character like 'c', 'ሴ', '😎' or undefined if inputString is not recognized + */ +export function convertToUnicodeCharacter(inputString: string): string | undefined { + + let m: RegExpMatchArray | null; + + if ((inputString === null) || (inputString === undefined)) { + return undefined; + } + + // e.g. U+0061 U+1234 U+1F60E + m = inputString.match(/^U\+([0-9a-f]{2,6})$/i); + if (m) return String.fromCodePoint(parseInt(m[1], 16)); + + // e.g. a ሴ 😎 + m = inputString.match(/^&#x([0-9a-f]{2,6});$/i); + if (m) return String.fromCodePoint(parseInt(m[1], 16)); + + // e.g. a ሴ 😆 + m = inputString.match(/^&#([0-9]{2,6});$/); + if (m) return String.fromCodePoint(parseInt(m[1], 10)); + + // e.g. > " + m = inputString.match(/^&([a-z]{2,4});$/i); + if (m) { + switch (inputString) { + case '>': return '>'; + case '<': return '<'; + case '&': return '&'; + case ''': return "'"; + case '"': return '"'; + default: return undefined; + } + } + + // 'A' or "B" have length=1 and segment-length=1 and will be used. + // "ẘ" or "😎" have length=2 but segment-length=1 and will be used. + // "ab" has length=2 and segment-length=2 and will not be used. + else if ([...new Intl.Segmenter().segment(inputString)].length <= 1) { + return inputString; + } + else { + return undefined; + } +} + +/** + * @brief function to convert a numeric character reference to a unicode Code Point e.g. ሴ -> U+1234; 􏘁 -> U+1F60E + * @param instr the value that will converted + * @return returns a unicode Code Point like U+0063, U+1234, U+1F60E; returns the input character if a non-numeric reference is used or returns 'undefined' if instr is not recognized + */ +export function convertToUnicodeCodePoint(instr: string): string { + + if ((instr === null) || (instr === undefined)) { + return undefined; + } + if (instr.startsWith("&#x")) { + const numLength = instr.length - 3; + const numStr = instr.substring(3, instr.length - 1); + return ("U+" + numStr.slice(-numLength).padStart(4, "0")); + } + + // if not hex: convert to hex + if (instr.startsWith("&#")) { + const numLength = instr.length - 2; + const numStr = instr.substring(2, instr.length - 1); + return "U+" + Number(numStr.slice(-numLength)).toString(16).slice(-6).toUpperCase().padStart(4, "0"); + } + else + return instr; +} + From ead25520d16f24636b8e1e1d135b16868658d985 Mon Sep 17 00:00:00 2001 From: Sabine Date: Fri, 9 Jan 2026 08:26:36 +0100 Subject: [PATCH 176/251] feat(developer): add changed package-lock.json --- package-lock.json | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/package-lock.json b/package-lock.json index 26be02a4491..298a9b2f458 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2147,6 +2147,23 @@ "resolve": "~1.22.2" } }, + "node_modules/@microsoft/tsdoc-config/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", From cdca47c5f68cc0870974a899d14dfc221a37ce46 Mon Sep 17 00:00:00 2001 From: Sabine Date: Mon, 12 Jan 2026 09:36:28 +0100 Subject: [PATCH 177/251] feat(developer): add comment --- .../src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts index 34e57a11c8f..29e42bf5051 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts @@ -883,7 +883,7 @@ export class KmnFileWriter { return warningTextArray; } - +// TODO: move to util /** * @brief function to convert a numeric character reference or a unicode value to a unicode character e.g. c -> c; U+1F60E -> 😎 * @param inputString the value that will converted @@ -930,7 +930,7 @@ export class KmnFileWriter { return undefined; } } - +// TODO: move to util /** * @brief function to convert a numeric character reference to a unicode Code Point e.g. ሴ -> U+1234; 􏘁 -> U+1F60E * @param instr the value that will converted From fe516024aa03cfcd1fb75edc7fb97a90e86575a7 Mon Sep 17 00:00:00 2001 From: Sabine Date: Mon, 12 Jan 2026 09:36:28 +0100 Subject: [PATCH 178/251] feat(developer): comment out convertToUnicodeCharacter and convertToUnicodeCodePoint from utils for now and use same functions from kmn-file-writer.ts --- developer/src/kmc-convert/src/convert-utils.ts | 8 ++++---- .../kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/developer/src/kmc-convert/src/convert-utils.ts b/developer/src/kmc-convert/src/convert-utils.ts index 7d086b80ed7..9511b686eb0 100644 --- a/developer/src/kmc-convert/src/convert-utils.ts +++ b/developer/src/kmc-convert/src/convert-utils.ts @@ -13,7 +13,7 @@ * @param inputString the value that will converted * @return a unicode character like 'c', 'ሴ', '😎' or undefined if inputString is not recognized */ -export function convertToUnicodeCharacter(inputString: string): string | undefined { +/*export function convertToUnicodeCharacter(inputString: string): string | undefined { let m: RegExpMatchArray | null; @@ -55,14 +55,14 @@ export function convertToUnicodeCharacter(inputString: string): string | undefin else { return undefined; } -} +}*/ /** * @brief function to convert a numeric character reference to a unicode Code Point e.g. ሴ -> U+1234; 􏘁 -> U+1F60E * @param instr the value that will converted * @return returns a unicode Code Point like U+0063, U+1234, U+1F60E; returns the input character if a non-numeric reference is used or returns 'undefined' if instr is not recognized */ -export function convertToUnicodeCodePoint(instr: string): string { +/*export function convertToUnicodeCodePoint(instr: string): string { if ((instr === null) || (instr === undefined)) { return undefined; @@ -81,5 +81,5 @@ export function convertToUnicodeCodePoint(instr: string): string { } else return instr; -} +}*/ diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts index 34e57a11c8f..29e42bf5051 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts @@ -883,7 +883,7 @@ export class KmnFileWriter { return warningTextArray; } - +// TODO: move to util /** * @brief function to convert a numeric character reference or a unicode value to a unicode character e.g. c -> c; U+1F60E -> 😎 * @param inputString the value that will converted @@ -930,7 +930,7 @@ export class KmnFileWriter { return undefined; } } - +// TODO: move to util /** * @brief function to convert a numeric character reference to a unicode Code Point e.g. ሴ -> U+1234; 􏘁 -> U+1F60E * @param instr the value that will converted From b5cdae52ae0ade583db655d3ad3b47e6395969b9 Mon Sep 17 00:00:00 2001 From: Sabine Date: Tue, 13 Jan 2026 11:12:06 +0100 Subject: [PATCH 179/251] feat(developer): delete convert-utils.ts for convertToUnicodeCharacter and convertToUnicodeCodePoint --- .../src/kmc-convert/src/convert-utils.ts | 85 ------------------- 1 file changed, 85 deletions(-) delete mode 100644 developer/src/kmc-convert/src/convert-utils.ts diff --git a/developer/src/kmc-convert/src/convert-utils.ts b/developer/src/kmc-convert/src/convert-utils.ts deleted file mode 100644 index 9511b686eb0..00000000000 --- a/developer/src/kmc-convert/src/convert-utils.ts +++ /dev/null @@ -1,85 +0,0 @@ - -/* - * Keyman is 2025 copyright (C) SIL International. MIT License. - * - * Created by S. Schmitt on 2025-08-24 - * - * functions for kmc-convert utils - * - */ - -/** - * @brief function to convert a numeric character reference or a unicode value to a unicode character e.g. c -> c; U+1F60E -> 😎 - * @param inputString the value that will converted - * @return a unicode character like 'c', 'ሴ', '😎' or undefined if inputString is not recognized - */ -/*export function convertToUnicodeCharacter(inputString: string): string | undefined { - - let m: RegExpMatchArray | null; - - if ((inputString === null) || (inputString === undefined)) { - return undefined; - } - - // e.g. U+0061 U+1234 U+1F60E - m = inputString.match(/^U\+([0-9a-f]{2,6})$/i); - if (m) return String.fromCodePoint(parseInt(m[1], 16)); - - // e.g. a ሴ 😎 - m = inputString.match(/^&#x([0-9a-f]{2,6});$/i); - if (m) return String.fromCodePoint(parseInt(m[1], 16)); - - // e.g. a ሴ 😆 - m = inputString.match(/^&#([0-9]{2,6});$/); - if (m) return String.fromCodePoint(parseInt(m[1], 10)); - - // e.g. > " - m = inputString.match(/^&([a-z]{2,4});$/i); - if (m) { - switch (inputString) { - case '>': return '>'; - case '<': return '<'; - case '&': return '&'; - case ''': return "'"; - case '"': return '"'; - default: return undefined; - } - } - - // 'A' or "B" have length=1 and segment-length=1 and will be used. - // "ẘ" or "😎" have length=2 but segment-length=1 and will be used. - // "ab" has length=2 and segment-length=2 and will not be used. - else if ([...new Intl.Segmenter().segment(inputString)].length <= 1) { - return inputString; - } - else { - return undefined; - } -}*/ - -/** - * @brief function to convert a numeric character reference to a unicode Code Point e.g. ሴ -> U+1234; 􏘁 -> U+1F60E - * @param instr the value that will converted - * @return returns a unicode Code Point like U+0063, U+1234, U+1F60E; returns the input character if a non-numeric reference is used or returns 'undefined' if instr is not recognized - */ -/*export function convertToUnicodeCodePoint(instr: string): string { - - if ((instr === null) || (instr === undefined)) { - return undefined; - } - if (instr.startsWith("&#x")) { - const numLength = instr.length - 3; - const numStr = instr.substring(3, instr.length - 1); - return ("U+" + numStr.slice(-numLength).padStart(4, "0")); - } - - // if not hex: convert to hex - if (instr.startsWith("&#")) { - const numLength = instr.length - 2; - const numStr = instr.substring(2, instr.length - 1); - return "U+" + Number(numStr.slice(-numLength)).toString(16).slice(-6).toUpperCase().padStart(4, "0"); - } - else - return instr; -}*/ - From 17704a99d7dbdae3a951119da10a78e2c9af9886 Mon Sep 17 00:00:00 2001 From: Sabine Date: Tue, 13 Jan 2026 11:20:24 +0100 Subject: [PATCH 180/251] feat(developer): delete content of kmcconvertUtils.ts for convertToUnicodeCharacter and convertToUnicodeCodePoint --- common/web/types/src/util/kmcConvertUtil.ts | 0 developer/src/kmc-convert/src/convert-utils.ts | 0 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 common/web/types/src/util/kmcConvertUtil.ts create mode 100644 developer/src/kmc-convert/src/convert-utils.ts diff --git a/common/web/types/src/util/kmcConvertUtil.ts b/common/web/types/src/util/kmcConvertUtil.ts new file mode 100644 index 00000000000..e69de29bb2d diff --git a/developer/src/kmc-convert/src/convert-utils.ts b/developer/src/kmc-convert/src/convert-utils.ts new file mode 100644 index 00000000000..e69de29bb2d From 3888fe7a5474c23bb8d5c87a13c9ed6e89038501 Mon Sep 17 00:00:00 2001 From: Sabine Date: Mon, 16 Feb 2026 15:42:13 +0100 Subject: [PATCH 181/251] feat(developer): remove kmcConvertUtil.ts edit text: "copyright..." in header --- common/web/types/src/util/kmcConvertUtil.ts | 0 .../kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts | 2 +- .../src/keylayout-to-kmn/keylayout-to-kmn-converter.ts | 2 +- .../src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts | 2 +- developer/src/kmc-convert/test/data/keylayout.dtd | 2 +- .../src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts | 2 +- developer/src/kmc-convert/test/kmn-file-reader.tests.ts | 2 +- developer/src/kmc-convert/test/kmn-file-writer.tests.ts | 2 +- 8 files changed, 7 insertions(+), 7 deletions(-) delete mode 100644 common/web/types/src/util/kmcConvertUtil.ts diff --git a/common/web/types/src/util/kmcConvertUtil.ts b/common/web/types/src/util/kmcConvertUtil.ts deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts index bd7dd4761c4..06de1ca9ddb 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts @@ -1,5 +1,5 @@ /* - * Keyman is 2025 copyright (C) SIL International. MIT License. + * Keyman is copyright (C) SIL Global. MIT License. * * Created by S. Schmitt on 2025-05-12 * diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 82bb26d9e1b..7d0003fded3 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -1,5 +1,5 @@ /* - * Keyman is 2025 copyright (C) SIL International. MIT License. + * Keyman is copyright (C) SIL Global. MIT License. * * Created by S. Schmitt on 2025-05-12 * diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts index 29e42bf5051..2b278b22d61 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts @@ -1,5 +1,5 @@ /* - * Keyman is 2025 copyright (C) SIL International. MIT License. + * Keyman is copyright (C) SIL Global. MIT License. * * Created by S. Schmitt on 2025-05-12 * diff --git a/developer/src/kmc-convert/test/data/keylayout.dtd b/developer/src/kmc-convert/test/data/keylayout.dtd index a670078a447..e60fa8c51c5 100644 --- a/developer/src/kmc-convert/test/data/keylayout.dtd +++ b/developer/src/kmc-convert/test/data/keylayout.dtd @@ -1,5 +1,5 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index a1b7f7c7506..c87be4708a8 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -89,6 +89,19 @@ describe('KeylayoutToKmnConverter', function () { }); }); + describe('RunSpecialTestFiles - undefined action', function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + [ + [makePathToFixture('../data/Test_undefinedAction.keylayout')], + ].forEach(function (files) { + it(files + " should give Error: undefined action detected", async function () { + sut.run(files[0]); + assert.isTrue(compilerTestCallbacks.messages.length === 1); + assert.equal(compilerTestCallbacks.messages[0].code, 5292041); + }); + }); + }); + describe('run() ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); @@ -183,11 +196,11 @@ describe('KeylayoutToKmnConverter', function () { }); it('should return empty on empty input', async function () { - assert.isNull(convertedEmpty) + assert.isNull(convertedEmpty); }); it('should return empty on empty name as input', async function () { - assert.isNull(convertedUnavailable) + assert.isNull(convertedUnavailable); }); it('should return empty on only modifiers as input', async function () { @@ -196,7 +209,7 @@ describe('KeylayoutToKmnConverter', function () { modifiers: [['caps'], ['Shift'], ['command']], rules: [] }, ''); - assert.isNull(convertedMod) + assert.isNull(convertedMod); }); it('should return empty on only rules as input', async function () { @@ -205,12 +218,12 @@ describe('KeylayoutToKmnConverter', function () { modifiers: [], rules: [['C0', '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_A', 'A']] }, ''); - assert.isNull(convertedRule) + assert.isNull(convertedRule); }); it('should return empty array of rules on null input', async function () { const convertedRule = sut.convertBound.convert(null, 'ABC.kmn'); - assert.isNull(convertedRule) + assert.isNull(convertedRule); }); }); @@ -419,16 +432,16 @@ describe('KeylayoutToKmnConverter', function () { const read = sutR.read(inputFilename); [ - ['none', 0], + ['none', -1], ['A_16', 8], ['A_18', 10], ['A_19', 11], - ['0', 0], - ['', 0], - [' ', 0], - [null, 0], - [undefined, 0], - ['unknown', 0], + ['0', -1], + ['', -1], + [' ', -1], + [null, -1], + [undefined, -1], + ['unknown', -1], ].forEach(function (values) { it(("getActionIndexFromActionId('" + values[0] + "')").padEnd(50, " ") + ' should return ' + values[1], async function () { const result = sut.getActionIndexFromActionId(read, String(values[0])); From 5096644de6218325f76e021a6553ac54332fa716 Mon Sep 17 00:00:00 2001 From: Sabine Date: Wed, 18 Mar 2026 15:10:34 +0100 Subject: [PATCH 205/251] feat(developer): UnsupportedCharactersDetected as error + test --- .../src/kmc-convert/src/converter-messages.ts | 10 ++-- .../keylayout-to-kmn-converter.ts | 16 ++--- .../src/keylayout-to-kmn/kmn-file-writer.ts | 16 ++--- .../data/Test_unsupportedCharacters.keylayout | 58 +++++++++++++++++++ .../test/keylayout-to-kmn-converter.tests.ts | 7 ++- 5 files changed, 83 insertions(+), 24 deletions(-) create mode 100644 developer/src/kmc-convert/test/data/Test_unsupportedCharacters.keylayout diff --git a/developer/src/kmc-convert/src/converter-messages.ts b/developer/src/kmc-convert/src/converter-messages.ts index 10c559ccbf5..5fb0a44769d 100644 --- a/developer/src/kmc-convert/src/converter-messages.ts +++ b/developer/src/kmc-convert/src/converter-messages.ts @@ -6,7 +6,7 @@ import { CompilerErrorNamespace, CompilerErrorSeverity, CompilerMessageSpec as m, CompilerMessageDef as def } from '@keymanapp/developer-utils'; const Namespace = CompilerErrorNamespace.Converter; -const SevInfo = CompilerErrorSeverity.Info | Namespace; +//const SevInfo = CompilerErrorSeverity.Info | Namespace; // const SevHint = CompilerErrorSeverity.Hint | Namespace; // const SevWarn = CompilerErrorSeverity.Warn | Namespace; const SevError = CompilerErrorSeverity.Error | Namespace; @@ -52,10 +52,10 @@ export class ConverterMessages { `Output file for '${def(o.outputFilename)}' could not be written. ${def(o.errorText)}` ); - static INFO_UnsupportedCharactersDetected = SevInfo | 0x0007; - static Info_UnsupportedCharactersDetected = (o: { inputFilename: string, keymapIndex: string, key: string, KeyName: string, output: string; }) => m( - this.INFO_UnsupportedCharactersDetected, - `INFO: Input file ${def(o.inputFilename)} contains unsupported character '${def(o.output)}' at keyMap index ${def(o.keymapIndex)} on Keycode ${def(o.key)} (${def(o.KeyName)})` + static ERROR_UnsupportedCharactersDetected = SevError | 0x0007; + static Error_UnsupportedCharactersDetected = (o: { inputFilename: string, keymapIndex: string, key: string, KeyName: string, output: string; }) => m( + this.ERROR_UnsupportedCharactersDetected, + `Input file ${def(o.inputFilename)} contains unsupported character '${def(o.output)}' at keyMap index ${def(o.keymapIndex)} on Keycode ${def(o.key)} (${def(o.KeyName)})` ); static ERROR_UndefinedActionDetected = SevError | 0x0009; diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index b52f81fb7fa..5013219ef3c 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -228,6 +228,7 @@ export class KeylayoutToKmnConverter { if (jsonObj.keyboard.modifierMap?.keyMapSelect.length !== jsonObj.keyboard.keyMapSet[0].keyMap.length) { const errorText = dataUkelele.keylayoutFilename; this.callbacks.reportMessage(ConverterMessages.Error_InvalidFile({ errorText })); + return null; } for (let j = 0; j <= KeylayoutToKmnConverter.MAX_KEY_COUNT; j++) { @@ -243,7 +244,7 @@ export class KeylayoutToKmnConverter { let ruleObj: Rule; - if ((j < jsonObj.keyboard.keyMapSet[0].keyMap[i].key.length)) { + if (j < jsonObj.keyboard.keyMapSet[0].keyMap[i].key.length) { // ............................................................................................................................... // case C0: output ............................................................................................................... // C0 see: https://docs.google.com/document/d/12J3NGO6RxIthCpZDTR8FYSRjiMgXJDLwPY2z9xqKzJ0/edit?tab=t.0#heading=h.g7jwx3lx0ydd ... @@ -505,13 +506,14 @@ export class KeylayoutToKmnConverter { } } } else { - this.callbacks.reportMessage(ConverterMessages.Info_UnsupportedCharactersDetected({ + this.callbacks.reportMessage(ConverterMessages.Error_UnsupportedCharactersDetected({ inputFilename: jsonObj.keyboard['@__name'] + ".keylayout", keymapIndex: jsonObj.keyboard.keyMapSet[0].keyMap[i]['@__index'], output: jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@__output'], key: jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@__code'], KeyName: this.mapUkeleleKeycodeToVK(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@__code']) })); + return null; } } } @@ -544,10 +546,8 @@ export class KeylayoutToKmnConverter { for (let i = 0; i < rules.length; i++) { - if ( - ((rules[i].modifierDeadkey !== undefined) && (rules[i].modifierDeadkey !== "")) && - ((rules[i].deadkey !== undefined) && (rules[i].deadkey !== "")) - ) { + if (((rules[i].modifierDeadkey !== undefined) && (rules[i].modifierDeadkey !== "")) + && ((rules[i].deadkey !== undefined) && (rules[i].deadkey !== ""))) { let IsFirstUsedHereDk: boolean = true; // check if not used before @@ -593,7 +593,7 @@ export class KeylayoutToKmnConverter { rules[i].uniquePrevDeadkey = uniqueCountDkA; uniqueCountDkA++; for (let k = 0; k < uniqueTextRules.length; k++) { - if ((uniqueTextRules[k][0] === rules[i].modifierDeadkey) && ((uniqueTextRules[k][1] === rules[i].deadkey))) { + if ((uniqueTextRules[k][0] === rules[i].modifierDeadkey) && (uniqueTextRules[k][1] === rules[i].deadkey)) { rules[i].uniqueDeadkey = Number(uniqueTextRules[k][2]); } } @@ -919,7 +919,7 @@ export class KeylayoutToKmnConverter { for (let i = 0; i < data.keyboard.actions.action.length; i++) { for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { - if ((data.keyboard.actions.action[i].when[j]['@__state'] === search)) { + if (data.keyboard.actions.action[i].when[j]['@__state'] === search) { if (data.keyboard.actions.action[i].when[j]['@__output'] !== undefined) { const singleDataSet = { id: data.keyboard.actions.action[i]['@__id'], diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts index 196520ebc93..a027b853ab7 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts @@ -170,7 +170,7 @@ export class KmnFileWriter { // add a warning in front of rules in case unavailable modifiers or ambiguous rules are used // if warning contains duplicate rules we do not write out the entire rule // (even if there are other warnings for the same rule) since that rule had been written before - if ((warnText[2].indexOf("duplicate") < 0)) { + if (warnText[2].indexOf("duplicate") < 0) { let warningTextToWrite = ""; if (!KeylayoutToKmnConverter.SKIP_COMMENTED_LINES && (warnText[2].length > 0)) { @@ -236,7 +236,7 @@ export class KmnFileWriter { // add a warning in front of rules in case unavailable modifiers or ambiguous rules are used // if warning contains duplicate rules we do not write out the entire rule // (even if there are other warnings for the same rule) since that rule had been written before - if ((warnText[1].indexOf("duplicate") < 0)) { + if (warnText[1].indexOf("duplicate") < 0) { let warningTextToWrite = ""; if (!KeylayoutToKmnConverter.SKIP_COMMENTED_LINES && (warnText[1].length > 0)) { @@ -326,7 +326,7 @@ export class KmnFileWriter { // add a warning in front of rules in case unavailable modifiers or ambiguous rules are used // if warning contains duplicate rules we do not write out the entire rule // (even if there are other warnings for the same rule) since that rule had been written before - if ((warnText[0].indexOf("duplicate") < 0)) { + if (warnText[0].indexOf("duplicate") < 0) { let warningTextToWrite = ""; @@ -344,7 +344,7 @@ export class KmnFileWriter { } } - if ((warnText[1].indexOf("duplicate") < 0)) { + if (warnText[1].indexOf("duplicate") < 0) { let warningTextToWrite = ""; if (!KeylayoutToKmnConverter.SKIP_COMMENTED_LINES && (warnText[1].length > 0)) { @@ -363,7 +363,7 @@ export class KmnFileWriter { } } - if ((warnText[2].indexOf("duplicate") < 0)) { + if (warnText[2].indexOf("duplicate") < 0) { let warningTextToWrite = ""; if (!KeylayoutToKmnConverter.SKIP_COMMENTED_LINES && (warnText[2].length > 0)) { @@ -903,17 +903,17 @@ export class KmnFileWriter { // e.g. U+0061 U+1234 U+1F60E else if (inputString.match(/^U\+([0-9a-f]{2,6})$/i)) { - return String.fromCodePoint(parseInt((inputString.match(/^U\+([0-9a-f]{2,6})$/i))[1], 16)); + return String.fromCodePoint(parseInt(inputString.match(/^U\+([0-9a-f]{2,6})$/i)[1], 16)); } // e.g. a ሴ 😎 else if (inputString.match(/^&#x([0-9a-f]{2,6});$/i)) { - return String.fromCodePoint(parseInt((inputString.match(/^&#x([0-9a-f]{2,6});$/i))[1], 16)); + return String.fromCodePoint(parseInt(inputString.match(/^&#x([0-9a-f]{2,6});$/i)[1], 16)); } // e.g. a ሴ 😆 else if (inputString.match(/^&#([0-9a-f]{2,6});$/i)) { - return String.fromCodePoint(parseInt((inputString.match(/^&#([0-9a-f]{2,6});$/i))[1], 10)); + return String.fromCodePoint(parseInt(inputString.match(/^&#([0-9a-f]{2,6});$/i)[1], 10)); } // e.g. > " diff --git a/developer/src/kmc-convert/test/data/Test_unsupportedCharacters.keylayout b/developer/src/kmc-convert/test/data/Test_unsupportedCharacters.keylayout new file mode 100644 index 00000000000..e2551263ef3 --- /dev/null +++ b/developer/src/kmc-convert/test/data/Test_unsupportedCharacters.keylayout @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index c87be4708a8..831b4d5fe8c 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -75,16 +75,17 @@ describe('KeylayoutToKmnConverter', function () { }); }); - describe('RunSpecialTestFiles - create Info', function () { + describe('RunSpecialTestFiles - create Error: unsupported characters', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); [ [makePathToFixture('../data/Test_characters.keylayout')], [makePathToFixture('../data/Test_onlyOneKeymap.keylayout')], + [makePathToFixture('../data/Test_unsupportedCharacters.keylayout')], ].forEach(function (files) { - it(files + " should give Info: unsupported characters ", async function () { + it(files + " should give Error: unsupported characters ", async function () { sut.run(files[0]); assert.isTrue(compilerTestCallbacks.messages.length === 1); - assert.isTrue(compilerTestCallbacks.messages[0].code === (CompilerErrorSeverity.Info | CompilerErrorNamespace.Converter | 0x0007)); + assert.isTrue(compilerTestCallbacks.messages[0].code === (CompilerErrorSeverity.Error | CompilerErrorNamespace.Converter | 0x0007)); }); }); }); From 5cb2b1e312f3411a116b6ddbc9f6ffe78c31ff3d Mon Sep 17 00:00:00 2001 From: Sabine Date: Thu, 19 Mar 2026 13:42:57 +0100 Subject: [PATCH 206/251] feat(developer): start rework read function first step (Uint8Array-> XMLSourceFile) --- .../src/kmc-convert/src/converter-messages.ts | 12 +++- developer/src/kmc-convert/src/converter.ts | 4 +- .../keylayout-to-kmn/keylayout-file-reader.ts | 53 ++++++++++++++++- .../keylayout-to-kmn-converter.ts | 58 +++++++++++++++++-- .../test/keylayout-to-kmn-converter.tests.ts | 29 +++++++--- .../kmc-convert/test/kmn-file-reader.tests.ts | 12 ++-- .../kmc-convert/test/kmn-file-writer.tests.ts | 1 - 7 files changed, 141 insertions(+), 28 deletions(-) diff --git a/developer/src/kmc-convert/src/converter-messages.ts b/developer/src/kmc-convert/src/converter-messages.ts index 5fb0a44769d..fb79c56db72 100644 --- a/developer/src/kmc-convert/src/converter-messages.ts +++ b/developer/src/kmc-convert/src/converter-messages.ts @@ -34,12 +34,18 @@ export class ConverterMessages { `Input filename '${def(o.inputFilename)}' does not exist or could not be loaded.` ); - static ERROR_UnableToRead = SevError | 0x0004; - static Error_UnableToRead = (o: { inputFilename: string; }) => m( - this.ERROR_UnableToRead, + static ERROR_UnableToReadFile = SevError | 0x0004; + static Error_UnableToReadFile = (o: { inputFilename: string; }) => m( + this.ERROR_UnableToReadFile, `Input file '${def(o.inputFilename)}' could not be read.` ); + static ERROR_UnableToRead = SevError | 0x000A; + static Error_UnableToRead = () => m( + this.ERROR_UnableToRead, + `Input file could not be read.` + ); + static ERROR_UnableToConvert = SevError | 0x0005; static Error_UnableToConvert = (o: { inputFilename: string; }) => m( this.ERROR_UnableToConvert, diff --git a/developer/src/kmc-convert/src/converter.ts b/developer/src/kmc-convert/src/converter.ts index 46ec0892631..936fb1918c1 100644 --- a/developer/src/kmc-convert/src/converter.ts +++ b/developer/src/kmc-convert/src/converter.ts @@ -81,9 +81,9 @@ export class Converter implements KeymanCompiler { } const converter = new ConverterClass(this.callbacks, converterOptions); - const result = await converter.run(inputFilename, outputFilename); + const result = await converter.run(inputFilename, binaryData, outputFilename); // Note: any subsequent errors in conversion will have been reported by the converter - return result ? result : null; + return result ? result : null; } /** diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts index dc5ce8c23c7..bd53ae82882 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts @@ -9,9 +9,9 @@ import { XMLParser } from 'fast-xml-parser'; import { CompilerCallbacks, DeveloperUtilsMessages, Keylayout } from "@keymanapp/developer-utils"; +//import { KeymanXMLReader } from "@keymanapp/developer-utils"; import { util, SchemaValidators } from '@keymanapp/common-types'; import { ConverterMessages } from '../converter-messages.js'; - import boxXmlArray = util.boxXmlArray; export class KeylayoutFileReader { @@ -23,7 +23,7 @@ export class KeylayoutFileReader { */ public validate(source: Keylayout.KeylayoutXMLSourceFile): boolean { if (!SchemaValidators.default.keylayout(source)) { - for (const err of (SchemaValidators.default.keylayout).errors) { + for (const err of (SchemaValidators.default.keylayout).errors) { this.callbacks.reportMessage(DeveloperUtilsMessages.Error_InvalidXml({ e: err.instancePath })); @@ -102,6 +102,8 @@ export class KeylayoutFileReader { * @param inputFilename the ukelele .keylayout-file to be parsed * @return in case of success: json object containing data of the .keylayout file; else null */ + //................................................................................................. + // old read() with fast-xml-parser (string-> XMLSourceFile) public read(inputFilename: string): Keylayout.KeylayoutXMLSourceFile { const options = { @@ -120,8 +122,53 @@ export class KeylayoutFileReader { return jsonObj; } catch (err) { - this.callbacks.reportMessage(ConverterMessages.Error_UnableToRead({ inputFilename })); + this.callbacks.reportMessage(ConverterMessages.Error_UnableToReadFile({ inputFilename })); + return null; + } + } + //................................................................................................. + // new read() with keyman xml parser (Uint8Array-> XMLSourceFile) + public read_Uint8Array(source: Uint8Array): Keylayout.KeylayoutXMLSourceFile { + + const options = { + ignoreAttributes: [''], // we do not process an output character of "" + trimValues: false, // we do not trim values because if we do we cannot process an output character of " " (space) + parseTagValue: false, + attributeNamePrefix: '@__', // to access the attribute + ignoreDeclaration: true + }; + + try { + const xmlFile = source; + const parser = new XMLParser(options); + const jsonObj = parser.parse(xmlFile); // get plain Object + this.boxArray(jsonObj.keyboard); // jsonObj now contains arrays; no single fields + return jsonObj; + } + catch (err) { + this.callbacks.reportMessage(ConverterMessages.Error_UnableToRead()); return null; } } + //................................................................................................. + /*// very new read() with KeymanXMLReader (Uint8Array-> XMLSourceFile) + public read_Uint8Array_UseKeymanXMLReader(file: Uint8Array): Keylayout.KeylayoutXMLSourceFile { + + let result: Keylayout.KeylayoutXMLSourceFile; + const data = new TextDecoder().decode(file); + + try { + result = new KeymanXMLReader('keylayout').parse(data) as Keylayout.KeylayoutXMLSourceFile; + this.boxArray(result.keyboard); + } catch (e) { + console.log("TODO here error"); + //this.callbacks.reportMessage(ConverterMessages.Error_UnableToReadFile({ e })); + } + if (!result) { + return null; + } + this.boxArray(result.keyboard); // result now contains arrays; no single fields + return result; + }*/ + //................................................................................................. } diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 5013219ef3c..a09ea08f5e9 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -13,7 +13,6 @@ import { KeylayoutFileReader } from './keylayout-file-reader.js'; import { ConverterMessages } from '../converter-messages.js'; import { ConverterArtifacts, ConverterToKmnArtifacts } from "../converter-artifacts.js"; - export interface ConverterResult extends KeymanCompilerResult { /** * Internal in-memory build artifacts from a successful compilation. Caller @@ -129,15 +128,41 @@ export class KeylayoutToKmnConverter { * @param outputFilename the resulting keyman .kmn-file * @return null on success */ - async run(inputFilename: string, outputFilename?: string): Promise { + async run(inputFilename: string, binaryData?: Uint8Array, outputFilename?: string): Promise { if (!inputFilename) { this.callbacks.reportMessage(ConverterMessages.Error_FileNotFound({ inputFilename })); return null; } - - const KeylayoutReader = new KeylayoutFileReader(this.callbacks/*, this.options*/); - const jsonO: Keylayout.KeylayoutXMLSourceFile = KeylayoutReader.read(inputFilename); + //................................................................................................... + /* OLD good VERSION - old read() with fast-xml-parser (string-> XMLSourceFile) + + if (outputFilename === null) { + this.callbacks.reportMessage(ConverterMessages.Error_OutputFilenameIsRequired()); + return null; + } + + const KeylayoutReader = new KeylayoutFileReader(this.callbacks//, this.options//); + const jsonO: KeylayoutXMLSourceFile = KeylayoutReader.read(inputFilename); + + try { + if (!KeylayoutReader.validate(jsonO)) { + return null; + } + } catch (e) { + this.callbacks.reportMessage(ConverterMessages.Error_InvalidFile({ errorText: e.toString() })); + return null; + }*/ + + //................................................................................................... + //NEW READER 1st easier version - new read() with keyman xml parser (Uint8Array-> XMLSourceFile) + + let jsonO: Keylayout.KeylayoutXMLSourceFile; + const KeylayoutReader = new KeylayoutFileReader(this.callbacks,/* this.options*/); + if (!binaryData) { + jsonO = KeylayoutReader.read_Uint8Array(this.callbacks.loadFile(inputFilename)); + } + else jsonO = KeylayoutReader.read_Uint8Array(binaryData); try { if (!KeylayoutReader.validate(jsonO)) { @@ -147,6 +172,27 @@ export class KeylayoutToKmnConverter { this.callbacks.reportMessage(ConverterMessages.Error_InvalidFile({ errorText: e.toString() })); return null; } + //................................................................................................... + //VERY NEW READER next version - very new read() with KeymanXMLReader (Uint8Array-> XMLSourceFile) + /* + // TODO + let jsonO: Keylayout.KeylayoutXMLSourceFile; + const KeylayoutReader = new KeylayoutFileReader(this.callbacks,// this.options//); + if (!binaryData) { + jsonO = KeylayoutReader.read_Uint8Array_UseKeymanXMLReader(this.callbacks.loadFile(inputFilename)); + } + else jsonO = KeylayoutReader.read_Uint8Array_UseKeymanXMLReader(binaryData); + + try { + if (!KeylayoutReader.validate(jsonO)) { + return null; + } + } catch (e) { + this.callbacks.reportMessage(ConverterMessages.Error_InvalidFile({ errorText: e.toString() })); + return null; + } + */ + //................................................................................................... const processedData = await this.convert(jsonO, inputFilename); @@ -793,7 +839,7 @@ export class KeylayoutToKmnConverter { "K_N" /* N */, "K_M" /* M */, "K_PERIOD" /* . */, - "K_?C1" /* \ */, // 48 for ANSI correct?? + "K_oE2" /* \ */, // 48 for ANSI correct?? "K_SPACE" /* \ */ ]; diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index 831b4d5fe8c..599a51a1a33 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -6,7 +6,6 @@ * Tests for KeylayoutToKmnConverter, KeylayoutFileReader, KmnFileWriter * */ - import 'mocha'; import { assert } from 'chai'; import * as NodeAssert from 'node:assert'; @@ -16,12 +15,28 @@ import { ActionStateOutput, KeylayoutFileData, KeylayoutToKmnConverter, Rule } f import { KeylayoutFileReader } from '../src/keylayout-to-kmn/keylayout-file-reader.js'; import { ConverterMessages } from '../src/converter-messages.js'; + describe('KeylayoutToKmnConverter', function () { before(function () { compilerTestCallbacks.clear(); }); + describe('Run kmc-convert with or without binary data or outputfile', async function () { + const converter = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const infile = makePathToFixture('../data/test.keylayout'); + const outfile = makePathToFixture('../data/test.kmn'); + const binaryData = compilerTestCallbacks.loadFile(infile); + + assert.deepEqual(await converter.run(infile, binaryData, outfile), await converter.run(infile)); + assert.deepEqual(await converter.run(infile, binaryData, outfile), await converter.run(infile, null)); + assert.deepEqual(await converter.run(infile, binaryData, outfile), await converter.run(infile, null, null)); + assert.deepEqual(await converter.run(infile, binaryData, outfile), await converter.run(infile, null, outfile)); + assert.deepEqual(await converter.run(infile, binaryData, outfile), await converter.run(infile, binaryData)); + assert.deepEqual(await converter.run(infile, binaryData, outfile), await converter.run(infile, binaryData, null)); + assert.deepEqual(await converter.run(infile, binaryData, outfile), await converter.run(infile, binaryData, outfile)); + }); + describe('RunTestFiles resulting in errors ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); [ @@ -115,14 +130,14 @@ describe('KeylayoutToKmnConverter', function () { }); it('run() should throw on null input file name and empty output file name', async function () { - const result = sut.run(null, ''); + const result = sut.run(null, null, ''); assert.isNotNull(result); assert.equal(compilerTestCallbacks.messages.length, 1); assert.deepEqual(compilerTestCallbacks.messages[0], ConverterMessages.Error_FileNotFound({ inputFilename: null })); }); it('run() should throw on null input file name and unknown output file name', async function () { - const result = sut.run(null, 'X'); + const result = sut.run(null, null, 'X'); assert.isNotNull(result); assert.equal(compilerTestCallbacks.messages.length, 1); assert.deepEqual(compilerTestCallbacks.messages[0], ConverterMessages.Error_FileNotFound({ inputFilename: null })); @@ -133,7 +148,7 @@ describe('KeylayoutToKmnConverter', function () { const result = sut.run(inputFilename, null); assert.isNotNull(result); assert.equal(compilerTestCallbacks.messages.length, 2); - assert.deepEqual(compilerTestCallbacks.messages[0], ConverterMessages.Error_UnableToRead({ inputFilename })); + assert.deepEqual(compilerTestCallbacks.messages[0], ConverterMessages.Error_UnableToRead()); assert.equal(compilerTestCallbacks.messages[1].code, 5246984); }); @@ -148,7 +163,7 @@ describe('KeylayoutToKmnConverter', function () { it('run() should return on correct input file name and empty output file name ', async function () { const inputFilename = makePathToFixture('../data/Test.keylayout'); - await NodeAssert.doesNotReject(async () => sut.run(inputFilename, '')); + await NodeAssert.doesNotReject(async () => sut.run(inputFilename,null, '')); assert.equal(compilerTestCallbacks.messages.length, 0); }); @@ -161,14 +176,14 @@ describe('KeylayoutToKmnConverter', function () { it('run() should return on correct input file name and given output file name ', async function () { const inputFilename = makePathToFixture('../data/Test.keylayout'); const outputFilename = makePathToFixture('../data/OutputName.kmn'); - await NodeAssert.doesNotReject(async () => sut.run(inputFilename, outputFilename)); + await NodeAssert.doesNotReject(async () => sut.run(inputFilename, null, outputFilename)); assert.equal(compilerTestCallbacks.messages.length, 0); }); it('run() return on correct input file extention and unsupperted output file extention', async function () { const inputFilename = makePathToFixture('../data/Test.keylayout'); const outputFilename = makePathToFixture('../data/OutputXName.B'); - await NodeAssert.doesNotReject(async () => sut.run(inputFilename, outputFilename)); + await NodeAssert.doesNotReject(async () => sut.run(inputFilename, null, outputFilename)); assert.equal(compilerTestCallbacks.messages.length, 0); }); }); diff --git a/developer/src/kmc-convert/test/kmn-file-reader.tests.ts b/developer/src/kmc-convert/test/kmn-file-reader.tests.ts index 5a7f5af1a5d..a03214de824 100644 --- a/developer/src/kmc-convert/test/kmn-file-reader.tests.ts +++ b/developer/src/kmc-convert/test/kmn-file-reader.tests.ts @@ -9,7 +9,7 @@ import 'mocha'; import { assert } from 'chai'; -import { Keylayout } from "@keymanapp/developer-utils" +import { Keylayout } from "@keymanapp/developer-utils"; import { compilerTestCallbacks, makePathToFixture } from './helpers/index.js'; import { KeylayoutFileReader } from '../src/keylayout-to-kmn/keylayout-file-reader.js'; @@ -22,7 +22,7 @@ describe('KeylayoutFileReader', function () { describe("validate() ", function () { it('validate() should return true on correct inputfile', async function () { - const sutR = new KeylayoutFileReader(compilerTestCallbacks); + const sutR = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Test.keylayout'); const result: Keylayout.KeylayoutXMLSourceFile = sutR.read(inputFilename); const validated = sutR.validate(result); @@ -30,7 +30,7 @@ describe('KeylayoutFileReader', function () { }); it('validate() should return false on inputfile with unknown tags', async function () { - const sutR = new KeylayoutFileReader(compilerTestCallbacks); + const sutR = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Test_unknownTags.keylayout'); const result: Keylayout.KeylayoutXMLSourceFile = sutR.read(inputFilename); const validated = sutR.validate(result); @@ -38,21 +38,21 @@ describe('KeylayoutFileReader', function () { }); it('validate() should return false on inputfile with additional tags', async function () { - const sutR = new KeylayoutFileReader(compilerTestCallbacks); + const sutR = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Test_additionalTags.keylayout'); const result: Keylayout.KeylayoutXMLSourceFile = sutR.read(inputFilename); const validated = sutR.validate(result); assert.isFalse(validated); }); it('validate() should return false on inputfile with missing tags', async function () { - const sutR = new KeylayoutFileReader(compilerTestCallbacks); + const sutR = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Test_missingTags.keylayout'); const result: Keylayout.KeylayoutXMLSourceFile = sutR.read(inputFilename); const validated = sutR.validate(result); assert.isFalse(validated); }); it('validate() should return false on no entries in action-when', async function () { - const sutR = new KeylayoutFileReader(compilerTestCallbacks); + const sutR = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Test_noActionWhen.keylayout'); const result: Keylayout.KeylayoutXMLSourceFile = sutR.read(inputFilename); const validated = sutR.validate(result); diff --git a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts index 4991ab9da17..aee7fb2c7d6 100644 --- a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts +++ b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts @@ -21,7 +21,6 @@ describe('KmnFileWriter', function () { compilerTestCallbacks.clear(); }); - describe("write() ", function () { const inputFilename = makePathToFixture('../data/Test.keylayout'); const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); From e7b56f9908cb4862e1e9104b13659553a4292a43 Mon Sep 17 00:00:00 2001 From: Sabine Date: Fri, 20 Mar 2026 11:58:07 +0100 Subject: [PATCH 207/251] feat(developer): rework read function --- .../src/common/web/utils/src/xml-utils.ts | 61 +++++++++++-------- .../keylayout-to-kmn/keylayout-file-reader.ts | 47 ++++++++------ .../test/keylayout-to-kmn-converter.tests.ts | 17 +++--- 3 files changed, 74 insertions(+), 51 deletions(-) diff --git a/developer/src/common/web/utils/src/xml-utils.ts b/developer/src/common/web/utils/src/xml-utils.ts index 901ca5bbf0e..9f1e48bc9d9 100644 --- a/developer/src/common/web/utils/src/xml-utils.ts +++ b/developer/src/common/web/utils/src/xml-utils.ts @@ -66,6 +66,14 @@ const PARSER_OPTIONS: KeymanXMLParserOptionsBag = { preserveOrder: true, // Gives us a 'special' format }, 'keylayout': { + /* + //my options copied from fast-xml-parser + ignoreAttributes: [''], // we do not process an output character of "" + trimValues: false, // we do not trim values because if we do we cannot process an output character of " " (space) + parseTagValue: false, + attributeNamePrefix: '@__', // to access the attribute + ignoreDeclaration: true +*/ attributeNamePrefix: '@__', htmlEntities: true, ignoreAttributes: false, // use attributes @@ -74,6 +82,7 @@ const PARSER_OPTIONS: KeymanXMLParserOptionsBag = { return tagValue?.trim(); }, trimValues: false, // preserve spaces, but see tagValueProcessor + }, 'kps': { ...PARSER_COMMON_OPTIONS, @@ -84,7 +93,7 @@ const PARSER_OPTIONS: KeymanXMLParserOptionsBag = { }, 'kvks': { ...PARSER_COMMON_OPTIONS, - tagValueProcessor: (_tagName: string, tagValue: string, _jPath: string, _hasAttributes: boolean, isLeafNode: boolean) : string | undefined => { + tagValueProcessor: (_tagName: string, tagValue: string, _jPath: string, _hasAttributes: boolean, isLeafNode: boolean): string | undefined => { if (!isLeafNode) { return tagValue?.trim(); // trimmed value } else { @@ -137,20 +146,20 @@ export class KeymanXMLReader { } /** Get metadata on a node if not already set */ - static getMetaData(o: any) : KeymanXMLMetadata { - if(!o) return o; - const metadata : KeymanXMLMetadata = o[XML_META_DATA_SYMBOL as any]; + static getMetaData(o: any): KeymanXMLMetadata { + if (!o) return o; + const metadata: KeymanXMLMetadata = o[XML_META_DATA_SYMBOL as any]; return metadata; } /** Set metadata if not already set */ - public static setMetaData(o: any, metadata: KeymanXMLMetadata) : KeymanXMLMetadata { - let m : KeymanXMLMetadata = KeymanXMLReader.getMetaData(o); + public static setMetaData(o: any, metadata: KeymanXMLMetadata): KeymanXMLMetadata { + let m: KeymanXMLMetadata = KeymanXMLReader.getMetaData(o); if (!m) { m = {}; } // copy non-symbols - m = {...metadata, ...m}; + m = { ...metadata, ...m }; // copy symbols SymbolUtils.copySymbols(m, metadata); o[XML_META_DATA_SYMBOL as any] = m; @@ -168,21 +177,21 @@ export class KeymanXMLReader { } if (Array.isArray(data)) { data.forEach(e => KeymanXMLReader.setDefaultFilename(e, filename)); - } else for(const k of Object.keys(data)) { + } else for (const k of Object.keys(data)) { KeymanXMLReader.setDefaultFilename(data[k], filename); } } } /** move `{ $abc: 4 }` into `{ $: { abc: 4 } }` */ - private static fixupDollarAttributes(data: any) : any { + private static fixupDollarAttributes(data: any): any { if (typeof data === 'object') { if (Array.isArray(data)) { return data.map(v => KeymanXMLReader.fixupDollarAttributes(v)); } // object - const e : any = []; - const attrs : any = []; + const e: any = []; + const attrs: any = []; Object.entries(data).forEach(([k, v]) => { if (k[0] === '$') { k = k.slice(1); @@ -204,7 +213,7 @@ export class KeymanXMLReader { * Requires attribute prefix @__ (double underscore) * For attributes, just remove @__ and continue. * For objects, replace any empty string "" with an empty object {} */ - private static fixupEmptyStringToEmptyObject(data: any) : any { + private static fixupEmptyStringToEmptyObject(data: any): any { if (typeof data === 'object') { // For arrays of objects, we map "" to {} // "" means an empty object @@ -268,10 +277,10 @@ export class KeymanXMLReader { /** takes an 'object' with a property `:@` containing attrs, and one other property with the object name */ private static fixupPreserveOrderObject(data: any): any { const attrs = data[':@']; - const mainEntry : any = Object.entries(data).filter(([k,v]) => k !== ':@'); + const mainEntry: any = Object.entries(data).filter(([k, v]) => k !== ':@'); const [elementName, subItems] = mainEntry[0]; - const out : any = {}; - if ( attrs ) { + const out: any = {}; + if (attrs) { out['$'] = attrs; } if (!elementName) { @@ -286,7 +295,7 @@ export class KeymanXMLReader { for (const o of out['$$']) { const subElementName = o['#name']; const nonPreservedElements = out[subElementName] = out[subElementName] ?? []; - const oWithoutName = {...o}; + const oWithoutName = { ...o }; delete oWithoutName['#name']; // #name is only there in the preserved-order form. nonPreservedElements.push(oWithoutName); } @@ -325,18 +334,18 @@ const PROLOGUE = { '?xml': { '$version': '1.0', '$encoding': 'utf-8' } }; /** wrapper for XML generation support */ export class KeymanXMLWriter { - private static fixDataForWrite(data: any) : any { - if(typeof data === 'object') { + private static fixDataForWrite(data: any): any { + if (typeof data === 'object') { if (Array.isArray(data)) { // just fixup each item of the array return data.map(d => KeymanXMLWriter.fixDataForWrite(d)); } // else object - const e : any = []; - Object.entries(data).forEach(([k,v]) => { + const e: any = []; + Object.entries(data).forEach(([k, v]) => { if (k === '$') { /* convert $: { a: 1, b: 2 } to { $a: 1, $b: 2} */ - Object.entries(v).forEach(([k,v]) => { + Object.entries(v).forEach(([k, v]) => { e.push([`\$${k}`, KeymanXMLWriter.fixDataForWrite(v)]); }); } else { @@ -375,12 +384,12 @@ export class KeymanXMLWriter { * @param path ajv split instancePath, such as '/keyboard3/layers/0'.split('/') * @returns undefined if the path was not present, null if path went to something that wasn't an object, otherwise the compileContext object is returned. */ -export function findInstanceObject(source: any, path: string[]) : any { - if(!path || !source || path.length == 0) { +export function findInstanceObject(source: any, path: string[]): any { + if (!path || !source || path.length == 0) { return source; - } else if(path[0] == '') { + } else if (path[0] == '') { return findInstanceObject(source, path.slice(1)); - } else if(Array.isArray(source) || typeof source == 'object') { + } else if (Array.isArray(source) || typeof source == 'object') { const child = source[path[0]]; if (child == undefined) return child; // nothing here if (!child || typeof child == 'string') { @@ -398,7 +407,7 @@ export function findInstanceObject(source: any, path: string[]) : any { * @param c number for the offset setting * @param x if set, this object will be used as the base object instead of {} */ -export function withOffset(c: number, compileContext?: any) : KeymanXMLMetadata { +export function withOffset(c: number, compileContext?: any): KeymanXMLMetadata { // set metadata on an empty object const o = Object.assign({}, compileContext); KeymanXMLReader.setMetaData(o, { diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts index bd53ae82882..9214ce1b573 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts @@ -9,7 +9,7 @@ import { XMLParser } from 'fast-xml-parser'; import { CompilerCallbacks, DeveloperUtilsMessages, Keylayout } from "@keymanapp/developer-utils"; -//import { KeymanXMLReader } from "@keymanapp/developer-utils"; +import { KeymanXMLReader } from "@keymanapp/developer-utils"; import { util, SchemaValidators } from '@keymanapp/common-types'; import { ConverterMessages } from '../converter-messages.js'; import boxXmlArray = util.boxXmlArray; @@ -39,8 +39,10 @@ export class KeylayoutFileReader { * @return objects that do not contain property #text */ public removeWhitespace(o: any): void { - if (o['#text']) { - delete o['#text']; + if (o !== undefined) { + if (o['#text']) { + delete o['#text']; + } } } @@ -127,7 +129,7 @@ export class KeylayoutFileReader { } } //................................................................................................. - // new read() with keyman xml parser (Uint8Array-> XMLSourceFile) + // new read() with fast xml parser (Uint8Array-> XMLSourceFile) public read_Uint8Array(source: Uint8Array): Keylayout.KeylayoutXMLSourceFile { const options = { @@ -139,9 +141,9 @@ export class KeylayoutFileReader { }; try { - const xmlFile = source; + //const xmlFile = source; const parser = new XMLParser(options); - const jsonObj = parser.parse(xmlFile); // get plain Object + const jsonObj = parser.parse(source); // get plain Object this.boxArray(jsonObj.keyboard); // jsonObj now contains arrays; no single fields return jsonObj; } @@ -151,24 +153,35 @@ export class KeylayoutFileReader { } } //................................................................................................. - /*// very new read() with KeymanXMLReader (Uint8Array-> XMLSourceFile) + // very new read() with KeymanXMLReader (Uint8Array-> XMLSourceFile) public read_Uint8Array_UseKeymanXMLReader(file: Uint8Array): Keylayout.KeylayoutXMLSourceFile { + // public read_Uint8Array(file: Uint8Array): Keylayout.KeylayoutXMLSourceFile { - let result: Keylayout.KeylayoutXMLSourceFile; - const data = new TextDecoder().decode(file); + /* // first idea use regex -> no + const data_with = new TextDecoder().decode(file); + let source: Keylayout.KeylayoutXMLSourceFile; + const data = data_with.replace(/(>[\\r\\n\s]+)/g, ">"); + */ + // second use options + const data = new TextDecoder().decode(file); + let source: Keylayout.KeylayoutXMLSourceFile; try { - result = new KeymanXMLReader('keylayout').parse(data) as Keylayout.KeylayoutXMLSourceFile; - this.boxArray(result.keyboard); - } catch (e) { + source = new KeymanXMLReader('keylayout'). + parse(data) as Keylayout.KeylayoutXMLSourceFile; + console.log("source"); + } + catch (e) { console.log("TODO here error"); //this.callbacks.reportMessage(ConverterMessages.Error_UnableToReadFile({ e })); - } - if (!result) { return null; } - this.boxArray(result.keyboard); // result now contains arrays; no single fields - return result; - }*/ + + if (this.boxArray(source)) { + return source; + } + // boxArrays ... resolveImports has already logged a message + return null; + } //................................................................................................. } diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index 599a51a1a33..2729b55194d 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -27,14 +27,15 @@ describe('KeylayoutToKmnConverter', function () { const infile = makePathToFixture('../data/test.keylayout'); const outfile = makePathToFixture('../data/test.kmn'); const binaryData = compilerTestCallbacks.loadFile(infile); - - assert.deepEqual(await converter.run(infile, binaryData, outfile), await converter.run(infile)); - assert.deepEqual(await converter.run(infile, binaryData, outfile), await converter.run(infile, null)); - assert.deepEqual(await converter.run(infile, binaryData, outfile), await converter.run(infile, null, null)); - assert.deepEqual(await converter.run(infile, binaryData, outfile), await converter.run(infile, null, outfile)); - assert.deepEqual(await converter.run(infile, binaryData, outfile), await converter.run(infile, binaryData)); - assert.deepEqual(await converter.run(infile, binaryData, outfile), await converter.run(infile, binaryData, null)); - assert.deepEqual(await converter.run(infile, binaryData, outfile), await converter.run(infile, binaryData, outfile)); + const base= await converter.run(infile, binaryData, outfile) + + assert.deepEqual(base, await converter.run(infile)); + assert.deepEqual(base, await converter.run(infile, null)); + assert.deepEqual(base, await converter.run(infile, null, null)); + assert.deepEqual(base, await converter.run(infile, null, outfile)); + assert.deepEqual(base, await converter.run(infile, binaryData)); + assert.deepEqual(base, await converter.run(infile, binaryData, null)); + assert.deepEqual(base, await converter.run(infile, binaryData, outfile)); }); describe('RunTestFiles resulting in errors ', function () { From 67204d2483b3593d5210354e517654eef38992d6 Mon Sep 17 00:00:00 2001 From: Sabine Date: Mon, 23 Mar 2026 14:03:10 +0100 Subject: [PATCH 208/251] feat(developer): use read function with Uint8Array as input using fast-xml parser; rework use of optional outputfilename; order/numbering of converter-messages --- .../src/kmc-convert/src/converter-messages.ts | 54 ++++++++------- developer/src/kmc-convert/src/converter.ts | 5 +- .../keylayout-to-kmn/keylayout-file-reader.ts | 59 +--------------- .../keylayout-to-kmn-converter.ts | 13 ++-- .../test/keylayout-to-kmn-converter.tests.ts | 68 ++++++++++++------- .../kmc-convert/test/kmn-file-reader.tests.ts | 42 +++++++----- .../kmc-convert/test/kmn-file-writer.tests.ts | 12 ++-- 7 files changed, 118 insertions(+), 135 deletions(-) diff --git a/developer/src/kmc-convert/src/converter-messages.ts b/developer/src/kmc-convert/src/converter-messages.ts index fb79c56db72..42bfff90578 100644 --- a/developer/src/kmc-convert/src/converter-messages.ts +++ b/developer/src/kmc-convert/src/converter-messages.ts @@ -16,16 +16,17 @@ const SevError = CompilerErrorSeverity.Error | Namespace; * @internal */ export class ConverterMessages { + static ERROR_OutputFilenameIsRequired = SevError | 0x0001; static Error_OutputFilenameIsRequired = () => m( this.ERROR_OutputFilenameIsRequired, `An output filename is required for keyboard conversion.` ); - static ERROR_NoConverterFound = SevError | 0x0002; - static Error_NoConverterFound = (o: { inputFilename: string, outputFilename: string; }) => m( - this.ERROR_NoConverterFound, - `No converter is available that can convert from '${def(o.inputFilename)}' to '${def(o.outputFilename)}'.` + static ERROR_IntputFilenameIsRequired = SevError | 0x0002; + static Error_IntputFilenameIsRequired = () => m( + this.ERROR_IntputFilenameIsRequired, + `An output filename is required for keyboard conversion.` ); static ERROR_FileNotFound = SevError | 0x0003; @@ -34,45 +35,52 @@ export class ConverterMessages { `Input filename '${def(o.inputFilename)}' does not exist or could not be loaded.` ); - static ERROR_UnableToReadFile = SevError | 0x0004; + static ERROR_InvalidFile = SevError | 0x0004; + static Error_InvalidFile = (o: { errorText: string; }) => m( + this.ERROR_InvalidFile, + `The source file has an invalid structure: ${def(o.errorText)}` + ); + + static ERROR_UnableToReadFile = SevError | 0x0005; static Error_UnableToReadFile = (o: { inputFilename: string; }) => m( this.ERROR_UnableToReadFile, `Input file '${def(o.inputFilename)}' could not be read.` ); - static ERROR_UnableToRead = SevError | 0x000A; + static ERROR_UnableToRead = SevError | 0x0006; static Error_UnableToRead = () => m( this.ERROR_UnableToRead, `Input file could not be read.` ); - static ERROR_UnableToConvert = SevError | 0x0005; - static Error_UnableToConvert = (o: { inputFilename: string; }) => m( - this.ERROR_UnableToConvert, - `Input file '${def(o.inputFilename)}' could not be converted.` - ); - - static ERROR_UnableToWrite = SevError | 0x0006; - static Error_UnableToWrite = (o: { outputFilename: string, errorText: string; }) => m( - this.ERROR_UnableToWrite, - `Output file for '${def(o.outputFilename)}' could not be written. ${def(o.errorText)}` - ); - static ERROR_UnsupportedCharactersDetected = SevError | 0x0007; static Error_UnsupportedCharactersDetected = (o: { inputFilename: string, keymapIndex: string, key: string, KeyName: string, output: string; }) => m( this.ERROR_UnsupportedCharactersDetected, `Input file ${def(o.inputFilename)} contains unsupported character '${def(o.output)}' at keyMap index ${def(o.keymapIndex)} on Keycode ${def(o.key)} (${def(o.KeyName)})` ); - static ERROR_UndefinedActionDetected = SevError | 0x0009; + static ERROR_UndefinedActionDetected = SevError | 0x0008; static Error_UndefinedActionDetected = (o: { inputFilename: string, action: string, KeyName: string, keymapIndex: string; }) => m( this.ERROR_UndefinedActionDetected, `${def(o.inputFilename)}: Action id ${def(o.action)} of key ${def(o.KeyName)} in keymapIndex ${def(o.keymapIndex)} is not defined` ); - static ERROR_InvalidFile = SevError | 0x0008; - static Error_InvalidFile = (o: { errorText: string; }) => m( - this.ERROR_InvalidFile, - `The source file has an invalid structure: ${def(o.errorText)}` + static ERROR_NoConverterFound = SevError | 0x0009; + static Error_NoConverterFound = (o: { inputFilename: string, outputFilename: string; }) => m( + this.ERROR_NoConverterFound, + `No converter is available that can convert from '${def(o.inputFilename)}' to '${def(o.outputFilename)}'.` + ); + + static ERROR_UnableToConvert = SevError | 0x000A; + static Error_UnableToConvert = (o: { inputFilename: string; }) => m( + this.ERROR_UnableToConvert, + `Input file '${def(o.inputFilename)}' could not be converted.` ); + + static ERROR_UnableToWrite = SevError | 0x000B; + static Error_UnableToWrite = (o: { outputFilename: string, errorText: string; }) => m( + this.ERROR_UnableToWrite, + `Output file for '${def(o.outputFilename)}' could not be written. ${def(o.errorText)}` + ); + } diff --git a/developer/src/kmc-convert/src/converter.ts b/developer/src/kmc-convert/src/converter.ts index 936fb1918c1..fb59d11e338 100644 --- a/developer/src/kmc-convert/src/converter.ts +++ b/developer/src/kmc-convert/src/converter.ts @@ -63,8 +63,9 @@ export class Converter implements KeymanCompiler { ...this.options, }; - if (!outputFilename) { - this.callbacks.reportMessage(ConverterMessages.Error_OutputFilenameIsRequired()); + // TODO-kmc-convert: do we allow !outputFilename? + if (!inputFilename) { + this.callbacks.reportMessage(ConverterMessages.Error_IntputFilenameIsRequired()); return null; } diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts index 9214ce1b573..cb4f8bcad83 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts @@ -9,7 +9,6 @@ import { XMLParser } from 'fast-xml-parser'; import { CompilerCallbacks, DeveloperUtilsMessages, Keylayout } from "@keymanapp/developer-utils"; -import { KeymanXMLReader } from "@keymanapp/developer-utils"; import { util, SchemaValidators } from '@keymanapp/common-types'; import { ConverterMessages } from '../converter-messages.js'; import boxXmlArray = util.boxXmlArray; @@ -105,32 +104,8 @@ export class KeylayoutFileReader { * @return in case of success: json object containing data of the .keylayout file; else null */ //................................................................................................. - // old read() with fast-xml-parser (string-> XMLSourceFile) - public read(inputFilename: string): Keylayout.KeylayoutXMLSourceFile { - - const options = { - ignoreAttributes: [''], // we do not process an output character of "" - trimValues: false, // we do not trim values because if we do we cannot process an output character of " " (space) - parseTagValue: false, - attributeNamePrefix: '@__', // to access the attribute - ignoreDeclaration: true - }; - - try { - const xmlFile = this.callbacks.fs.readFileSync(inputFilename, 'utf8'); - const parser = new XMLParser(options); - const jsonObj = parser.parse(xmlFile); // get plain Object - this.boxArray(jsonObj.keyboard); // jsonObj now contains arrays; no single fields - return jsonObj; - } - catch (err) { - this.callbacks.reportMessage(ConverterMessages.Error_UnableToReadFile({ inputFilename })); - return null; - } - } - //................................................................................................. // new read() with fast xml parser (Uint8Array-> XMLSourceFile) - public read_Uint8Array(source: Uint8Array): Keylayout.KeylayoutXMLSourceFile { + public read(source: Uint8Array): Keylayout.KeylayoutXMLSourceFile { const options = { ignoreAttributes: [''], // we do not process an output character of "" @@ -141,7 +116,6 @@ export class KeylayoutFileReader { }; try { - //const xmlFile = source; const parser = new XMLParser(options); const jsonObj = parser.parse(source); // get plain Object this.boxArray(jsonObj.keyboard); // jsonObj now contains arrays; no single fields @@ -153,35 +127,4 @@ export class KeylayoutFileReader { } } //................................................................................................. - // very new read() with KeymanXMLReader (Uint8Array-> XMLSourceFile) - public read_Uint8Array_UseKeymanXMLReader(file: Uint8Array): Keylayout.KeylayoutXMLSourceFile { - // public read_Uint8Array(file: Uint8Array): Keylayout.KeylayoutXMLSourceFile { - - /* // first idea use regex -> no - const data_with = new TextDecoder().decode(file); - let source: Keylayout.KeylayoutXMLSourceFile; - const data = data_with.replace(/(>[\\r\\n\s]+)/g, ">"); - */ - - // second use options - const data = new TextDecoder().decode(file); - let source: Keylayout.KeylayoutXMLSourceFile; - try { - source = new KeymanXMLReader('keylayout'). - parse(data) as Keylayout.KeylayoutXMLSourceFile; - console.log("source"); - } - catch (e) { - console.log("TODO here error"); - //this.callbacks.reportMessage(ConverterMessages.Error_UnableToReadFile({ e })); - return null; - } - - if (this.boxArray(source)) { - return source; - } - // boxArrays ... resolveImports has already logged a message - return null; - } - //................................................................................................. } diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index a09ea08f5e9..f91f111e7c4 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -160,9 +160,9 @@ export class KeylayoutToKmnConverter { let jsonO: Keylayout.KeylayoutXMLSourceFile; const KeylayoutReader = new KeylayoutFileReader(this.callbacks,/* this.options*/); if (!binaryData) { - jsonO = KeylayoutReader.read_Uint8Array(this.callbacks.loadFile(inputFilename)); + jsonO = KeylayoutReader.read(this.callbacks.loadFile(inputFilename)); } - else jsonO = KeylayoutReader.read_Uint8Array(binaryData); + else jsonO = KeylayoutReader.read(binaryData); try { if (!KeylayoutReader.validate(jsonO)) { @@ -194,7 +194,7 @@ export class KeylayoutToKmnConverter { */ //................................................................................................... - const processedData = await this.convert(jsonO, inputFilename); + const processedData = await this.convert(jsonO, inputFilename, outputFilename); const kmnFileWriter = new KmnFileWriter(this.callbacks, this.options); @@ -213,7 +213,7 @@ export class KeylayoutToKmnConverter { * @param jsonObj containing filename, behaviorand rules of a json object * @return an ProcessedData containing all data ready to print out */ - private convert(jsonObj: any, inputfilename: string): ProcessedData { + private convert(jsonObj: any, inputfilename: string, outputFilename?: string): ProcessedData { // modifiers for each behavior const modifierBehavior: string[][] = []; @@ -242,7 +242,10 @@ export class KeylayoutToKmnConverter { // fill dataObject with filenames, behaviors and (initialized) rules dataObject.keylayoutFilename = inputfilename; - dataObject.kmnFilename = inputfilename.replace(/\.keylayout$/, '.kmn'); + if (!outputFilename) + dataObject.kmnFilename = inputfilename.replace(/\.keylayout$/, '.kmn'); + else + dataObject.kmnFilename = outputFilename; dataObject.modifiers = modifierBehavior; // ukelele uses behaviors e.g. 18 modifiersCombinations in 8 KeyMapSelect(behaviors) dataObject.rules = rules; diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index 2729b55194d..1d9f148b138 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -15,19 +15,37 @@ import { ActionStateOutput, KeylayoutFileData, KeylayoutToKmnConverter, Rule } f import { KeylayoutFileReader } from '../src/keylayout-to-kmn/keylayout-file-reader.js'; import { ConverterMessages } from '../src/converter-messages.js'; - describe('KeylayoutToKmnConverter', function () { before(function () { compilerTestCallbacks.clear(); }); + describe('Run kmc-convert with or without outputfile name', async function () { + + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const infile = '../data/test.keylayout'; + const binaryData = compilerTestCallbacks.loadFile(makePathToFixture(infile)); + [ + [makePathToFixture('../data/test.kmn')], + [], + [makePathToFixture('../data/test_OtherOutputName.kmn')], + ].forEach(function (files) { + it(infile + " should run " + ((files[0]) ? + ("with specified output filename and should create " + files[0]) : + ("without specified output filename and should create " + makePathToFixture(infile.replace(/\.keylayout$/, '.kmn')))), async function () { + await NodeAssert.doesNotReject(async () => sut.run(makePathToFixture(infile), binaryData, files[0])); + assert.equal(compilerTestCallbacks.messages.length, 0); + }); + }); + }); + describe('Run kmc-convert with or without binary data or outputfile', async function () { const converter = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const infile = makePathToFixture('../data/test.keylayout'); const outfile = makePathToFixture('../data/test.kmn'); const binaryData = compilerTestCallbacks.loadFile(infile); - const base= await converter.run(infile, binaryData, outfile) + const base = await converter.run(infile, binaryData, outfile); assert.deepEqual(base, await converter.run(infile)); assert.deepEqual(base, await converter.run(infile, null)); @@ -53,7 +71,7 @@ describe('KeylayoutToKmnConverter', function () { [makePathToFixture('../data/Test_MissingAllERROR.keylayout')], ].forEach(function (files) { it(files + " should give an error ", async function () { - sut.run(files[0]); + sut.run(files[0], compilerTestCallbacks.loadFile(files[0])); assert.isTrue(compilerTestCallbacks.messages.length > 0); }); }); @@ -85,7 +103,7 @@ describe('KeylayoutToKmnConverter', function () { [makePathToFixture('../data/Test.keylayout')], ].forEach(function (files) { it(files + " should give no errors ", async function () { - sut.run(files[0]); + sut.run(files[0], compilerTestCallbacks.loadFile(files[0])); assert.isTrue(compilerTestCallbacks.messages.length === 0); }); }); @@ -99,7 +117,7 @@ describe('KeylayoutToKmnConverter', function () { [makePathToFixture('../data/Test_unsupportedCharacters.keylayout')], ].forEach(function (files) { it(files + " should give Error: unsupported characters ", async function () { - sut.run(files[0]); + sut.run(files[0], compilerTestCallbacks.loadFile(files[0])); assert.isTrue(compilerTestCallbacks.messages.length === 1); assert.isTrue(compilerTestCallbacks.messages[0].code === (CompilerErrorSeverity.Error | CompilerErrorNamespace.Converter | 0x0007)); }); @@ -112,9 +130,9 @@ describe('KeylayoutToKmnConverter', function () { [makePathToFixture('../data/Test_undefinedAction.keylayout')], ].forEach(function (files) { it(files + " should give Error: undefined action detected", async function () { - sut.run(files[0]); + sut.run(files[0], compilerTestCallbacks.loadFile(files[0])); assert.isTrue(compilerTestCallbacks.messages.length === 1); - assert.equal(compilerTestCallbacks.messages[0].code, 5292041); + assert.equal(compilerTestCallbacks.messages[0].code, 5292040); }); }); }); @@ -156,7 +174,7 @@ describe('KeylayoutToKmnConverter', function () { it('run() should return on available input file name and null output file name', async function () { this.timeout(5000); // allow longer time for this test const inputFilename = makePathToFixture('../data/Test.keylayout'); - const result = sut.run(inputFilename, null); + const result = sut.run(inputFilename, compilerTestCallbacks.loadFile(inputFilename), null); assert.isNotNull(result); await NodeAssert.doesNotReject(async () => sut.run(inputFilename, null)); assert.equal(compilerTestCallbacks.messages.length, 0); @@ -164,27 +182,27 @@ describe('KeylayoutToKmnConverter', function () { it('run() should return on correct input file name and empty output file name ', async function () { const inputFilename = makePathToFixture('../data/Test.keylayout'); - await NodeAssert.doesNotReject(async () => sut.run(inputFilename,null, '')); + await NodeAssert.doesNotReject(async () => sut.run(inputFilename, compilerTestCallbacks.loadFile(inputFilename), '')); assert.equal(compilerTestCallbacks.messages.length, 0); }); it('run() should return on correct input file name and null output file name', async function () { const inputFilename = makePathToFixture('../data/Test.keylayout'); - await NodeAssert.doesNotReject(async () => sut.run(inputFilename, null)); + await NodeAssert.doesNotReject(async () => sut.run(inputFilename, compilerTestCallbacks.loadFile(inputFilename), null)); assert.equal(compilerTestCallbacks.messages.length, 0); }); it('run() should return on correct input file name and given output file name ', async function () { const inputFilename = makePathToFixture('../data/Test.keylayout'); const outputFilename = makePathToFixture('../data/OutputName.kmn'); - await NodeAssert.doesNotReject(async () => sut.run(inputFilename, null, outputFilename)); + await NodeAssert.doesNotReject(async () => sut.run(inputFilename, compilerTestCallbacks.loadFile(inputFilename), outputFilename)); assert.equal(compilerTestCallbacks.messages.length, 0); }); it('run() return on correct input file extention and unsupperted output file extention', async function () { const inputFilename = makePathToFixture('../data/Test.keylayout'); const outputFilename = makePathToFixture('../data/OutputXName.B'); - await NodeAssert.doesNotReject(async () => sut.run(inputFilename, null, outputFilename)); + await NodeAssert.doesNotReject(async () => sut.run(inputFilename, compilerTestCallbacks.loadFile(inputFilename), outputFilename)); assert.equal(compilerTestCallbacks.messages.length, 0); }); }); @@ -195,17 +213,17 @@ describe('KeylayoutToKmnConverter', function () { // ProcessedData from usable file const inputFilename = makePathToFixture('../data/Test.keylayout'); - const read = sutR.read(inputFilename); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); const converted = sut.convertBound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); // ProcessedData from unavailable file const inputFilenameUnavailable = makePathToFixture('../data/X.keylayout'); - const readUnavailable = sutR.read(inputFilenameUnavailable); + const readUnavailable = sutR.read(compilerTestCallbacks.loadFile(inputFilenameUnavailable)); const convertedUnavailable = sut.convertBound.convert(readUnavailable, inputFilenameUnavailable.replace(/\.keylayout$/, '.kmn')); // ProcessedData from empty file const inputFilenameEmpty = makePathToFixture(''); - const readEmpty = sutR.read(inputFilenameEmpty); + const readEmpty = sutR.read(compilerTestCallbacks.loadFile(inputFilenameEmpty)); const convertedEmpty = sut.convertBound.convert(readEmpty, inputFilenameEmpty); it('should return converted array on correct input', async function () { @@ -369,7 +387,7 @@ describe('KeylayoutToKmnConverter', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sutR = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Test.keylayout'); - const read = sutR.read(inputFilename); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); const converted = sut.convertBound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); [ [[{ key: '0', behavior: 0 }], [['', 'shift? caps? ']]], @@ -394,7 +412,7 @@ describe('KeylayoutToKmnConverter', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sutR = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Test.keylayout'); - const read = sutR.read(inputFilename); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); [ ['A_16', [{ "key": "32", "behavior": "5" }]], ['A_19', [{ "key": "45", "behavior": "5" }]], @@ -420,7 +438,7 @@ describe('KeylayoutToKmnConverter', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sutR = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Test.keylayout'); - const read = sutR.read(inputFilename); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); [ ['none', ''], @@ -446,7 +464,7 @@ describe('KeylayoutToKmnConverter', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sutR = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Test.keylayout'); - const read = sutR.read(inputFilename); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); [ ['none', -1], @@ -470,7 +488,7 @@ describe('KeylayoutToKmnConverter', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sutR = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Test.keylayout'); - const read = sutR.read(inputFilename); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); [ ['A_14', 'u'], @@ -500,7 +518,7 @@ describe('KeylayoutToKmnConverter', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sutR = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Test.keylayout'); - const read = sutR.read(inputFilename); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); const b1KeycodeArr: KeylayoutFileData[] = [ { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '0', outchar: 'ˆ' }, @@ -607,7 +625,7 @@ describe('KeylayoutToKmnConverter', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sutR = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Test.keylayout'); - const read = sutR.read(inputFilename); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); [['1', [ { "id": "A_0", "state": "1", "output": "ˆ" }, @@ -654,7 +672,7 @@ describe('KeylayoutToKmnConverter', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sutR = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Test.keylayout'); - const read = sutR.read(inputFilename); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); const converted = sut.convertBound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); [ @@ -690,7 +708,7 @@ describe('KeylayoutToKmnConverter', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sutR = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Test.keylayout'); - const read = sutR.read(inputFilename); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); const b6ActionIdArr: ActionStateOutput[] = [ { "id": "A_0", "state": "1", "output": "ˆ" }, @@ -845,7 +863,7 @@ describe('KeylayoutToKmnConverter', function () { ].forEach(function (values: any) { it('data of \'' + values[0] + "' passed into createRuleData() " + 'should create an array of rules', async function () { const inputFilename = makePathToFixture(values[0][0]); - const read = sutR.read(inputFilename); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); const processedData = sut.convertBound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); assert.deepEqual(processedData.rules[0], values[1][0]); }); diff --git a/developer/src/kmc-convert/test/kmn-file-reader.tests.ts b/developer/src/kmc-convert/test/kmn-file-reader.tests.ts index a03214de824..d3eaf25caa6 100644 --- a/developer/src/kmc-convert/test/kmn-file-reader.tests.ts +++ b/developer/src/kmc-convert/test/kmn-file-reader.tests.ts @@ -19,20 +19,35 @@ describe('KeylayoutFileReader', function () { compilerTestCallbacks.clear(); }); +/* +compilerTestCallbacks.loadFile + loadFile(filename: string): Uint8Array { + try { + return fs.readFileSync(filename) as Uint8Array; + } catch(e) { + if (e.code === 'ENOENT') { + return null; + } else { + throw e; + } + } + }*/ + + describe("validate() ", function () { it('validate() should return true on correct inputfile', async function () { const sutR = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Test.keylayout'); - const result: Keylayout.KeylayoutXMLSourceFile = sutR.read(inputFilename); - const validated = sutR.validate(result); + const result: Keylayout.KeylayoutXMLSourceFile = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + const validated = sutR.validate(result); assert.isTrue(validated); }); it('validate() should return false on inputfile with unknown tags', async function () { const sutR = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Test_unknownTags.keylayout'); - const result: Keylayout.KeylayoutXMLSourceFile = sutR.read(inputFilename); + const result: Keylayout.KeylayoutXMLSourceFile = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); const validated = sutR.validate(result); assert.isFalse(validated); }); @@ -40,21 +55,21 @@ describe('KeylayoutFileReader', function () { it('validate() should return false on inputfile with additional tags', async function () { const sutR = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Test_additionalTags.keylayout'); - const result: Keylayout.KeylayoutXMLSourceFile = sutR.read(inputFilename); + const result: Keylayout.KeylayoutXMLSourceFile = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); const validated = sutR.validate(result); assert.isFalse(validated); }); it('validate() should return false on inputfile with missing tags', async function () { const sutR = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Test_missingTags.keylayout'); - const result: Keylayout.KeylayoutXMLSourceFile = sutR.read(inputFilename); + const result: Keylayout.KeylayoutXMLSourceFile = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); const validated = sutR.validate(result); assert.isFalse(validated); }); it('validate() should return false on no entries in action-when', async function () { const sutR = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Test_noActionWhen.keylayout'); - const result: Keylayout.KeylayoutXMLSourceFile = sutR.read(inputFilename); + const result: Keylayout.KeylayoutXMLSourceFile = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); const validated = sutR.validate(result); assert.isFalse(validated); }); @@ -66,33 +81,28 @@ describe('KeylayoutFileReader', function () { it('read() should return filled array on correct input', async function () { const inputFilename = makePathToFixture('../data/Test.keylayout'); - const result = sutR.read(inputFilename); + const result = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); assert.isNotEmpty(result); }); - it('read() should return empty array on null input', async function () { - const result = sutR.read(null); - assert.isNull(result); - }); - it('read() should return empty array on empty input', async function () { - const result = sutR.read(""); + const result = sutR.read(compilerTestCallbacks.loadFile("")); assert.isNull(result); }); it('read() should return empty array on space as input', async function () { - const result = sutR.read(" "); + const result = sutR.read(compilerTestCallbacks.loadFile(" ")); assert.isNull(result); }); it('read() should return empty array on unavailable file name', async function () { const inputFilenameUnavailable = makePathToFixture('../data/X.keylayout'); - const result = sutR.read(inputFilenameUnavailable); + const result = sutR.read(compilerTestCallbacks.loadFile(inputFilenameUnavailable)); assert.isNull(result); }); it('read() should return empty array on typo in path', async function () { - const result = sutR.read(makePathToFixture('../data|Test.keylayout')); + const result = sutR.read(compilerTestCallbacks.loadFile(makePathToFixture('../data|Test.keylayout'))); assert.isNull(result); }); }); diff --git a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts index aee7fb2c7d6..b83e94f3219 100644 --- a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts +++ b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts @@ -25,8 +25,8 @@ describe('KmnFileWriter', function () { const inputFilename = makePathToFixture('../data/Test.keylayout'); const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sutR = new KeylayoutFileReader(compilerTestCallbacks); - const sutW = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); - const read = sutR.read(inputFilename); + const sutW = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); + const read= sutR.read(compilerTestCallbacks.loadFile(inputFilename)); const converted = sut.convertBound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); it('write() should return result', async function () { @@ -39,8 +39,8 @@ describe('KmnFileWriter', function () { const inputFilename = makePathToFixture('../data/Test.keylayout'); const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sutR = new KeylayoutFileReader(compilerTestCallbacks); - const sutW = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); - const read = sutR.read(inputFilename); + const sutW = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); const converted = sut.convertBound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); it('writeDataRules() should return true (no error) if written', async function () { @@ -54,8 +54,8 @@ describe('KmnFileWriter', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sutR = new KeylayoutFileReader(compilerTestCallbacks); const sutW = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); - const inputFilename = makePathToFixture('../data/Test.keylayout'); - const read = sutR.read(inputFilename); + const inputFilename = makePathToFixture('../data/Test.keylayout'); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); const converted = sut.convertBound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); const outExpectedFirst: string = From 07dc16e2182cba275ed9ac7d8fd8294a659a8311 Mon Sep 17 00:00:00 2001 From: Sabine Date: Mon, 23 Mar 2026 19:26:31 +0100 Subject: [PATCH 209/251] feat(developer): reading to binary done in keylayout-to-kmn-converter.ts ( instead of in converter.ts) --- developer/src/kmc-convert/src/converter.ts | 9 +--- .../keylayout-to-kmn-converter.ts | 18 ++++---- .../test/keylayout-to-kmn-converter.tests.ts | 44 ++++++++----------- 3 files changed, 30 insertions(+), 41 deletions(-) diff --git a/developer/src/kmc-convert/src/converter.ts b/developer/src/kmc-convert/src/converter.ts index fb59d11e338..6c32603fac9 100644 --- a/developer/src/kmc-convert/src/converter.ts +++ b/developer/src/kmc-convert/src/converter.ts @@ -63,7 +63,6 @@ export class Converter implements KeymanCompiler { ...this.options, }; - // TODO-kmc-convert: do we allow !outputFilename? if (!inputFilename) { this.callbacks.reportMessage(ConverterMessages.Error_IntputFilenameIsRequired()); return null; @@ -75,14 +74,8 @@ export class Converter implements KeymanCompiler { return null; } - const binaryData = this.callbacks.loadFile(inputFilename); - if (!binaryData) { - this.callbacks.reportMessage(ConverterMessages.Error_FileNotFound({ inputFilename })); - return null; - } - const converter = new ConverterClass(this.callbacks, converterOptions); - const result = await converter.run(inputFilename, binaryData, outputFilename); + const result = await converter.run(inputFilename, outputFilename); // Note: any subsequent errors in conversion will have been reported by the converter return result ? result : null; } diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index f91f111e7c4..bbf6d5d7265 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -128,8 +128,8 @@ export class KeylayoutToKmnConverter { * @param outputFilename the resulting keyman .kmn-file * @return null on success */ - async run(inputFilename: string, binaryData?: Uint8Array, outputFilename?: string): Promise { - + // async run(inputFilename: string, outputFilename?: string): Promise { + async run(inputFilename: string,/* binaryData?: Uint8Array, */outputFilename?: string): Promise { if (!inputFilename) { this.callbacks.reportMessage(ConverterMessages.Error_FileNotFound({ inputFilename })); return null; @@ -157,13 +157,15 @@ export class KeylayoutToKmnConverter { //................................................................................................... //NEW READER 1st easier version - new read() with keyman xml parser (Uint8Array-> XMLSourceFile) - let jsonO: Keylayout.KeylayoutXMLSourceFile; - const KeylayoutReader = new KeylayoutFileReader(this.callbacks,/* this.options*/); - if (!binaryData) { - jsonO = KeylayoutReader.read(this.callbacks.loadFile(inputFilename)); - } - else jsonO = KeylayoutReader.read(binaryData); + const KeylayoutReader = new KeylayoutFileReader(this.callbacks/*, this.options*/); + + const binaryData = this.callbacks.loadFile(inputFilename); + const jsonO: Keylayout.KeylayoutXMLSourceFile = KeylayoutReader.read(binaryData); + if (!jsonO) { + this.callbacks.reportMessage(ConverterMessages.Error_UnableToReadFile({ inputFilename :inputFilename})); + return null; + } try { if (!KeylayoutReader.validate(jsonO)) { return null; diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index 1d9f148b138..db246e1cea9 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -22,10 +22,8 @@ describe('KeylayoutToKmnConverter', function () { }); describe('Run kmc-convert with or without outputfile name', async function () { - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const infile = '../data/test.keylayout'; - const binaryData = compilerTestCallbacks.loadFile(makePathToFixture(infile)); [ [makePathToFixture('../data/test.kmn')], [], @@ -34,7 +32,7 @@ describe('KeylayoutToKmnConverter', function () { it(infile + " should run " + ((files[0]) ? ("with specified output filename and should create " + files[0]) : ("without specified output filename and should create " + makePathToFixture(infile.replace(/\.keylayout$/, '.kmn')))), async function () { - await NodeAssert.doesNotReject(async () => sut.run(makePathToFixture(infile), binaryData, files[0])); + await NodeAssert.doesNotReject(async () => sut.run(makePathToFixture(infile), files[0])); assert.equal(compilerTestCallbacks.messages.length, 0); }); }); @@ -44,16 +42,12 @@ describe('KeylayoutToKmnConverter', function () { const converter = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const infile = makePathToFixture('../data/test.keylayout'); const outfile = makePathToFixture('../data/test.kmn'); - const binaryData = compilerTestCallbacks.loadFile(infile); - const base = await converter.run(infile, binaryData, outfile); - + const base = await converter.run(infile, outfile); assert.deepEqual(base, await converter.run(infile)); assert.deepEqual(base, await converter.run(infile, null)); - assert.deepEqual(base, await converter.run(infile, null, null)); - assert.deepEqual(base, await converter.run(infile, null, outfile)); - assert.deepEqual(base, await converter.run(infile, binaryData)); - assert.deepEqual(base, await converter.run(infile, binaryData, null)); - assert.deepEqual(base, await converter.run(infile, binaryData, outfile)); + assert.deepEqual(base, await converter.run(infile, outfile)); + assert.deepEqual(base, await converter.run(infile, null)); + assert.deepEqual(base, await converter.run(infile, outfile)); }); describe('RunTestFiles resulting in errors ', function () { @@ -71,7 +65,7 @@ describe('KeylayoutToKmnConverter', function () { [makePathToFixture('../data/Test_MissingAllERROR.keylayout')], ].forEach(function (files) { it(files + " should give an error ", async function () { - sut.run(files[0], compilerTestCallbacks.loadFile(files[0])); + sut.run(files[0]); assert.isTrue(compilerTestCallbacks.messages.length > 0); }); }); @@ -103,7 +97,7 @@ describe('KeylayoutToKmnConverter', function () { [makePathToFixture('../data/Test.keylayout')], ].forEach(function (files) { it(files + " should give no errors ", async function () { - sut.run(files[0], compilerTestCallbacks.loadFile(files[0])); + sut.run(files[0]); assert.isTrue(compilerTestCallbacks.messages.length === 0); }); }); @@ -117,7 +111,7 @@ describe('KeylayoutToKmnConverter', function () { [makePathToFixture('../data/Test_unsupportedCharacters.keylayout')], ].forEach(function (files) { it(files + " should give Error: unsupported characters ", async function () { - sut.run(files[0], compilerTestCallbacks.loadFile(files[0])); + sut.run(files[0]); assert.isTrue(compilerTestCallbacks.messages.length === 1); assert.isTrue(compilerTestCallbacks.messages[0].code === (CompilerErrorSeverity.Error | CompilerErrorNamespace.Converter | 0x0007)); }); @@ -130,7 +124,7 @@ describe('KeylayoutToKmnConverter', function () { [makePathToFixture('../data/Test_undefinedAction.keylayout')], ].forEach(function (files) { it(files + " should give Error: undefined action detected", async function () { - sut.run(files[0], compilerTestCallbacks.loadFile(files[0])); + sut.run(files[0]); assert.isTrue(compilerTestCallbacks.messages.length === 1); assert.equal(compilerTestCallbacks.messages[0].code, 5292040); }); @@ -149,14 +143,14 @@ describe('KeylayoutToKmnConverter', function () { }); it('run() should throw on null input file name and empty output file name', async function () { - const result = sut.run(null, null, ''); + const result = sut.run(null, ''); assert.isNotNull(result); assert.equal(compilerTestCallbacks.messages.length, 1); assert.deepEqual(compilerTestCallbacks.messages[0], ConverterMessages.Error_FileNotFound({ inputFilename: null })); }); it('run() should throw on null input file name and unknown output file name', async function () { - const result = sut.run(null, null, 'X'); + const result = sut.run(null, 'X'); assert.isNotNull(result); assert.equal(compilerTestCallbacks.messages.length, 1); assert.deepEqual(compilerTestCallbacks.messages[0], ConverterMessages.Error_FileNotFound({ inputFilename: null })); @@ -166,15 +160,15 @@ describe('KeylayoutToKmnConverter', function () { const inputFilename = makePathToFixture('../data/Unavailable.keylayout'); const result = sut.run(inputFilename, null); assert.isNotNull(result); - assert.equal(compilerTestCallbacks.messages.length, 2); - assert.deepEqual(compilerTestCallbacks.messages[0], ConverterMessages.Error_UnableToRead()); - assert.equal(compilerTestCallbacks.messages[1].code, 5246984); + assert.equal(compilerTestCallbacks.messages.length, 1); + assert.deepEqual(compilerTestCallbacks.messages[0], ConverterMessages.Error_UnableToReadFile({ inputFilename: inputFilename }));// ok + assert.equal(compilerTestCallbacks.messages[1].code, 5292037); }); it('run() should return on available input file name and null output file name', async function () { this.timeout(5000); // allow longer time for this test const inputFilename = makePathToFixture('../data/Test.keylayout'); - const result = sut.run(inputFilename, compilerTestCallbacks.loadFile(inputFilename), null); + const result = sut.run(inputFilename, null); assert.isNotNull(result); await NodeAssert.doesNotReject(async () => sut.run(inputFilename, null)); assert.equal(compilerTestCallbacks.messages.length, 0); @@ -182,27 +176,27 @@ describe('KeylayoutToKmnConverter', function () { it('run() should return on correct input file name and empty output file name ', async function () { const inputFilename = makePathToFixture('../data/Test.keylayout'); - await NodeAssert.doesNotReject(async () => sut.run(inputFilename, compilerTestCallbacks.loadFile(inputFilename), '')); + await NodeAssert.doesNotReject(async () => sut.run(inputFilename, '')); assert.equal(compilerTestCallbacks.messages.length, 0); }); it('run() should return on correct input file name and null output file name', async function () { const inputFilename = makePathToFixture('../data/Test.keylayout'); - await NodeAssert.doesNotReject(async () => sut.run(inputFilename, compilerTestCallbacks.loadFile(inputFilename), null)); + await NodeAssert.doesNotReject(async () => sut.run(inputFilename, null)); assert.equal(compilerTestCallbacks.messages.length, 0); }); it('run() should return on correct input file name and given output file name ', async function () { const inputFilename = makePathToFixture('../data/Test.keylayout'); const outputFilename = makePathToFixture('../data/OutputName.kmn'); - await NodeAssert.doesNotReject(async () => sut.run(inputFilename, compilerTestCallbacks.loadFile(inputFilename), outputFilename)); + await NodeAssert.doesNotReject(async () => sut.run(inputFilename, outputFilename)); assert.equal(compilerTestCallbacks.messages.length, 0); }); it('run() return on correct input file extention and unsupperted output file extention', async function () { const inputFilename = makePathToFixture('../data/Test.keylayout'); const outputFilename = makePathToFixture('../data/OutputXName.B'); - await NodeAssert.doesNotReject(async () => sut.run(inputFilename, compilerTestCallbacks.loadFile(inputFilename), outputFilename)); + await NodeAssert.doesNotReject(async () => sut.run(inputFilename, outputFilename)); assert.equal(compilerTestCallbacks.messages.length, 0); }); }); From 21caa521567082154a68a0729552f30c18c75895 Mon Sep 17 00:00:00 2001 From: Sabine Date: Mon, 23 Mar 2026 20:02:17 +0100 Subject: [PATCH 210/251] feat(developer): tidy up --- .../keylayout-to-kmn-converter.ts | 49 +------------------ .../test/keylayout-to-kmn-converter.tests.ts | 17 +++---- .../kmc-convert/test/kmn-file-reader.tests.ts | 17 +------ .../kmc-convert/test/kmn-file-writer.tests.ts | 8 +-- 4 files changed, 15 insertions(+), 76 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index bbf6d5d7265..d9764c0dfb5 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -128,34 +128,11 @@ export class KeylayoutToKmnConverter { * @param outputFilename the resulting keyman .kmn-file * @return null on success */ - // async run(inputFilename: string, outputFilename?: string): Promise { - async run(inputFilename: string,/* binaryData?: Uint8Array, */outputFilename?: string): Promise { + async run(inputFilename: string, outputFilename?: string): Promise { if (!inputFilename) { this.callbacks.reportMessage(ConverterMessages.Error_FileNotFound({ inputFilename })); return null; } - //................................................................................................... - /* OLD good VERSION - old read() with fast-xml-parser (string-> XMLSourceFile) - - if (outputFilename === null) { - this.callbacks.reportMessage(ConverterMessages.Error_OutputFilenameIsRequired()); - return null; - } - - const KeylayoutReader = new KeylayoutFileReader(this.callbacks//, this.options//); - const jsonO: KeylayoutXMLSourceFile = KeylayoutReader.read(inputFilename); - - try { - if (!KeylayoutReader.validate(jsonO)) { - return null; - } - } catch (e) { - this.callbacks.reportMessage(ConverterMessages.Error_InvalidFile({ errorText: e.toString() })); - return null; - }*/ - - //................................................................................................... - //NEW READER 1st easier version - new read() with keyman xml parser (Uint8Array-> XMLSourceFile) const KeylayoutReader = new KeylayoutFileReader(this.callbacks/*, this.options*/); @@ -163,7 +140,7 @@ export class KeylayoutToKmnConverter { const jsonO: Keylayout.KeylayoutXMLSourceFile = KeylayoutReader.read(binaryData); if (!jsonO) { - this.callbacks.reportMessage(ConverterMessages.Error_UnableToReadFile({ inputFilename :inputFilename})); + this.callbacks.reportMessage(ConverterMessages.Error_UnableToReadFile({ inputFilename: inputFilename })); return null; } try { @@ -174,30 +151,8 @@ export class KeylayoutToKmnConverter { this.callbacks.reportMessage(ConverterMessages.Error_InvalidFile({ errorText: e.toString() })); return null; } - //................................................................................................... - //VERY NEW READER next version - very new read() with KeymanXMLReader (Uint8Array-> XMLSourceFile) - /* - // TODO - let jsonO: Keylayout.KeylayoutXMLSourceFile; - const KeylayoutReader = new KeylayoutFileReader(this.callbacks,// this.options//); - if (!binaryData) { - jsonO = KeylayoutReader.read_Uint8Array_UseKeymanXMLReader(this.callbacks.loadFile(inputFilename)); - } - else jsonO = KeylayoutReader.read_Uint8Array_UseKeymanXMLReader(binaryData); - - try { - if (!KeylayoutReader.validate(jsonO)) { - return null; - } - } catch (e) { - this.callbacks.reportMessage(ConverterMessages.Error_InvalidFile({ errorText: e.toString() })); - return null; - } - */ - //................................................................................................... const processedData = await this.convert(jsonO, inputFilename, outputFilename); - const kmnFileWriter = new KmnFileWriter(this.callbacks, this.options); // write to object/ConverterToKmnResult diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index db246e1cea9..e3e41e63271 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -31,14 +31,15 @@ describe('KeylayoutToKmnConverter', function () { ].forEach(function (files) { it(infile + " should run " + ((files[0]) ? ("with specified output filename and should create " + files[0]) : - ("without specified output filename and should create " + makePathToFixture(infile.replace(/\.keylayout$/, '.kmn')))), async function () { - await NodeAssert.doesNotReject(async () => sut.run(makePathToFixture(infile), files[0])); - assert.equal(compilerTestCallbacks.messages.length, 0); - }); + ("without specified output filename and should create " + + makePathToFixture(infile.replace(/\.keylayout$/, '.kmn')))), async function () { + await NodeAssert.doesNotReject(async () => sut.run(makePathToFixture(infile), files[0])); + assert.equal(compilerTestCallbacks.messages.length, 0); + }); }); }); - describe('Run kmc-convert with or without binary data or outputfile', async function () { + describe('Run kmc-convert with or without outputfile', async function () { const converter = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const infile = makePathToFixture('../data/test.keylayout'); const outfile = makePathToFixture('../data/test.kmn'); @@ -46,8 +47,6 @@ describe('KeylayoutToKmnConverter', function () { assert.deepEqual(base, await converter.run(infile)); assert.deepEqual(base, await converter.run(infile, null)); assert.deepEqual(base, await converter.run(infile, outfile)); - assert.deepEqual(base, await converter.run(infile, null)); - assert.deepEqual(base, await converter.run(infile, outfile)); }); describe('RunTestFiles resulting in errors ', function () { @@ -160,8 +159,8 @@ describe('KeylayoutToKmnConverter', function () { const inputFilename = makePathToFixture('../data/Unavailable.keylayout'); const result = sut.run(inputFilename, null); assert.isNotNull(result); - assert.equal(compilerTestCallbacks.messages.length, 1); - assert.deepEqual(compilerTestCallbacks.messages[0], ConverterMessages.Error_UnableToReadFile({ inputFilename: inputFilename }));// ok + assert.equal(compilerTestCallbacks.messages.length, 2); + assert.deepEqual(compilerTestCallbacks.messages[0], ConverterMessages.Error_UnableToRead());// ok assert.equal(compilerTestCallbacks.messages[1].code, 5292037); }); diff --git a/developer/src/kmc-convert/test/kmn-file-reader.tests.ts b/developer/src/kmc-convert/test/kmn-file-reader.tests.ts index d3eaf25caa6..3b99b6400d4 100644 --- a/developer/src/kmc-convert/test/kmn-file-reader.tests.ts +++ b/developer/src/kmc-convert/test/kmn-file-reader.tests.ts @@ -19,28 +19,13 @@ describe('KeylayoutFileReader', function () { compilerTestCallbacks.clear(); }); -/* -compilerTestCallbacks.loadFile - loadFile(filename: string): Uint8Array { - try { - return fs.readFileSync(filename) as Uint8Array; - } catch(e) { - if (e.code === 'ENOENT') { - return null; - } else { - throw e; - } - } - }*/ - - describe("validate() ", function () { it('validate() should return true on correct inputfile', async function () { const sutR = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Test.keylayout'); const result: Keylayout.KeylayoutXMLSourceFile = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); - const validated = sutR.validate(result); + const validated = sutR.validate(result); assert.isTrue(validated); }); diff --git a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts index b83e94f3219..84893621f0e 100644 --- a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts +++ b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts @@ -25,8 +25,8 @@ describe('KmnFileWriter', function () { const inputFilename = makePathToFixture('../data/Test.keylayout'); const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sutR = new KeylayoutFileReader(compilerTestCallbacks); - const sutW = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); - const read= sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + const sutW = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); const converted = sut.convertBound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); it('write() should return result', async function () { @@ -39,7 +39,7 @@ describe('KmnFileWriter', function () { const inputFilename = makePathToFixture('../data/Test.keylayout'); const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sutR = new KeylayoutFileReader(compilerTestCallbacks); - const sutW = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); + const sutW = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); const converted = sut.convertBound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); @@ -54,7 +54,7 @@ describe('KmnFileWriter', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sutR = new KeylayoutFileReader(compilerTestCallbacks); const sutW = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../data/Test.keylayout'); const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); const converted = sut.convertBound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); From 516c16990a845b4f9ec5bbf7ea188ff684442aeb Mon Sep 17 00:00:00 2001 From: Sabine Date: Mon, 23 Mar 2026 20:29:37 +0100 Subject: [PATCH 211/251] feat(developer): change test output --- .../src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index e3e41e63271..f65d5a47d90 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -30,9 +30,8 @@ describe('KeylayoutToKmnConverter', function () { [makePathToFixture('../data/test_OtherOutputName.kmn')], ].forEach(function (files) { it(infile + " should run " + ((files[0]) ? - ("with specified output filename and should create " + files[0]) : - ("without specified output filename and should create " - + makePathToFixture(infile.replace(/\.keylayout$/, '.kmn')))), async function () { + ("and use specified output filename") : + ("create outputfile name from input filename ")), async function () { await NodeAssert.doesNotReject(async () => sut.run(makePathToFixture(infile), files[0])); assert.equal(compilerTestCallbacks.messages.length, 0); }); From 8e9308252e480632ce16556fb4e9eb38dafcec2c Mon Sep 17 00:00:00 2001 From: Sabine Date: Mon, 23 Mar 2026 20:29:37 +0100 Subject: [PATCH 212/251] feat(developer): change test --- .../src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index e3e41e63271..bd3b5c34ddc 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -29,10 +29,7 @@ describe('KeylayoutToKmnConverter', function () { [], [makePathToFixture('../data/test_OtherOutputName.kmn')], ].forEach(function (files) { - it(infile + " should run " + ((files[0]) ? - ("with specified output filename and should create " + files[0]) : - ("without specified output filename and should create " - + makePathToFixture(infile.replace(/\.keylayout$/, '.kmn')))), async function () { + it(infile + " should run " , async function () { await NodeAssert.doesNotReject(async () => sut.run(makePathToFixture(infile), files[0])); assert.equal(compilerTestCallbacks.messages.length, 0); }); From e444bc5c047c9a44442a3d0402b584adcd682f7f Mon Sep 17 00:00:00 2001 From: Sabine Date: Mon, 23 Mar 2026 20:57:55 +0100 Subject: [PATCH 213/251] feat(developer): change 1 test --- .../kmc-convert/test/keylayout-to-kmn-converter.tests.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index bd3b5c34ddc..56ab5907b56 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -22,6 +22,7 @@ describe('KeylayoutToKmnConverter', function () { }); describe('Run kmc-convert with or without outputfile name', async function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const infile = '../data/test.keylayout'; [ @@ -36,14 +37,15 @@ describe('KeylayoutToKmnConverter', function () { }); }); - describe('Run kmc-convert with or without outputfile', async function () { + describe('Run kmc-convert with or without outputfile', async function () { const converter = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const infile = makePathToFixture('../data/test.keylayout'); const outfile = makePathToFixture('../data/test.kmn'); + const out_diff = makePathToFixture('../data/test_OtherOutputName.kmn'); const base = await converter.run(infile, outfile); assert.deepEqual(base, await converter.run(infile)); assert.deepEqual(base, await converter.run(infile, null)); - assert.deepEqual(base, await converter.run(infile, outfile)); + assert.notDeepEqual(base, await converter.run(infile, out_diff)); }); describe('RunTestFiles resulting in errors ', function () { From 5d9357470405c0bd9db9ed4af6b0bfc597e18eb9 Mon Sep 17 00:00:00 2001 From: Sabine Date: Tue, 31 Mar 2026 16:23:12 +0200 Subject: [PATCH 214/251] feat(developer): change 1 test --- .../src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index 56ab5907b56..e4d2238c046 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -44,7 +44,6 @@ describe('KeylayoutToKmnConverter', function () { const out_diff = makePathToFixture('../data/test_OtherOutputName.kmn'); const base = await converter.run(infile, outfile); assert.deepEqual(base, await converter.run(infile)); - assert.deepEqual(base, await converter.run(infile, null)); assert.notDeepEqual(base, await converter.run(infile, out_diff)); }); From e4fecda6922752254de1f402877d7e0bc6cdaf80 Mon Sep 17 00:00:00 2001 From: Sabine Date: Tue, 31 Mar 2026 19:13:10 +0200 Subject: [PATCH 215/251] feat(developer): change test --- .../test/keylayout-to-kmn-converter.tests.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index e4d2238c046..fefc913467d 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -9,7 +9,6 @@ import 'mocha'; import { assert } from 'chai'; import * as NodeAssert from 'node:assert'; -import { CompilerErrorNamespace, CompilerErrorSeverity } from '@keymanapp/developer-utils'; import { compilerTestCallbacks, compilerTestOptions, makePathToFixture } from './helpers/index.js'; import { ActionStateOutput, KeylayoutFileData, KeylayoutToKmnConverter, Rule } from '../src/keylayout-to-kmn/keylayout-to-kmn-converter.js'; import { KeylayoutFileReader } from '../src/keylayout-to-kmn/keylayout-file-reader.js'; @@ -44,14 +43,13 @@ describe('KeylayoutToKmnConverter', function () { const out_diff = makePathToFixture('../data/test_OtherOutputName.kmn'); const base = await converter.run(infile, outfile); assert.deepEqual(base, await converter.run(infile)); - assert.notDeepEqual(base, await converter.run(infile, out_diff)); + assert.deepEqual(base, await converter.run(infile, null)); }); describe('RunTestFiles resulting in errors ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); [ [makePathToFixture('../data/Test_DifferentAmountOfMapSelectInKeyMapERROR.keylayout')], - [makePathToFixture('../data/Test_DifferentAmountOfMapSelectInKeyMapERROR_1.keylayout')], [makePathToFixture('../data/Test_MissingkeyERROR.keylayout')], [makePathToFixture('../data/Test_MissingkeyMapERROR.keylayout')], [makePathToFixture('../data/Test_MissingLayoutsERROR.keylayout')], @@ -60,6 +58,7 @@ describe('KeylayoutToKmnConverter', function () { [makePathToFixture('../data/Test_MissingActionsERROR.keylayout')], [makePathToFixture('../data/Test_MissingTerminatorsERROR.keylayout')], [makePathToFixture('../data/Test_MissingAllERROR.keylayout')], + [makePathToFixture('../data/Test_characters.keylayout')], ].forEach(function (files) { it(files + " should give an error ", async function () { sut.run(files[0]); @@ -92,6 +91,10 @@ describe('KeylayoutToKmnConverter', function () { [makePathToFixture('../data/Test_ambiguous_keys.keylayout')], [makePathToFixture('../data/Test_nr_elements.keylayout')], [makePathToFixture('../data/Test.keylayout')], + [makePathToFixture('../data/Test_mixedEncodings.keylayout')], + [makePathToFixture('../data/Test_Character_Codepoint_C0.keylayout')], + [makePathToFixture('../data/Test_Character_Codepoint_C2.keylayout')], + [makePathToFixture('../data/Test_Character_Codepoint_C3.keylayout')], ].forEach(function (files) { it(files + " should give no errors ", async function () { sut.run(files[0]); @@ -110,7 +113,6 @@ describe('KeylayoutToKmnConverter', function () { it(files + " should give Error: unsupported characters ", async function () { sut.run(files[0]); assert.isTrue(compilerTestCallbacks.messages.length === 1); - assert.isTrue(compilerTestCallbacks.messages[0].code === (CompilerErrorSeverity.Error | CompilerErrorNamespace.Converter | 0x0007)); }); }); }); From 2f615c93802afda9ab6e1ca7c11cfbf5fa5edaa4 Mon Sep 17 00:00:00 2001 From: Sabine Date: Tue, 31 Mar 2026 19:24:17 +0200 Subject: [PATCH 216/251] feat(developer): change test --- .../test/keylayout-to-kmn-converter.tests.ts | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index fefc913467d..2dc4affe1be 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -36,16 +36,6 @@ describe('KeylayoutToKmnConverter', function () { }); }); - describe('Run kmc-convert with or without outputfile', async function () { - const converter = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const infile = makePathToFixture('../data/test.keylayout'); - const outfile = makePathToFixture('../data/test.kmn'); - const out_diff = makePathToFixture('../data/test_OtherOutputName.kmn'); - const base = await converter.run(infile, outfile); - assert.deepEqual(base, await converter.run(infile)); - assert.deepEqual(base, await converter.run(infile, null)); - }); - describe('RunTestFiles resulting in errors ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); [ @@ -91,10 +81,6 @@ describe('KeylayoutToKmnConverter', function () { [makePathToFixture('../data/Test_ambiguous_keys.keylayout')], [makePathToFixture('../data/Test_nr_elements.keylayout')], [makePathToFixture('../data/Test.keylayout')], - [makePathToFixture('../data/Test_mixedEncodings.keylayout')], - [makePathToFixture('../data/Test_Character_Codepoint_C0.keylayout')], - [makePathToFixture('../data/Test_Character_Codepoint_C2.keylayout')], - [makePathToFixture('../data/Test_Character_Codepoint_C3.keylayout')], ].forEach(function (files) { it(files + " should give no errors ", async function () { sut.run(files[0]); From 20de41a11ce5053100852474d9915b834a7a9633 Mon Sep 17 00:00:00 2001 From: Sabine Date: Tue, 31 Mar 2026 20:08:01 +0200 Subject: [PATCH 217/251] feat(developer): change timeout for 1 test --- .../test/keylayout-to-kmn-converter.tests.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index 2dc4affe1be..bcdd57bcbb0 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -22,6 +22,7 @@ describe('KeylayoutToKmnConverter', function () { describe('Run kmc-convert with or without outputfile name', async function () { + this.timeout(5000); // allow longer time for this test const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const infile = '../data/test.keylayout'; [ @@ -29,10 +30,12 @@ describe('KeylayoutToKmnConverter', function () { [], [makePathToFixture('../data/test_OtherOutputName.kmn')], ].forEach(function (files) { - it(infile + " should run " , async function () { - await NodeAssert.doesNotReject(async () => sut.run(makePathToFixture(infile), files[0])); - assert.equal(compilerTestCallbacks.messages.length, 0); - }); + it(infile + " should run ", async function () { + await NodeAssert.doesNotReject(async () => sut.run(makePathToFixture(infile), files[0])); + if (compilerTestCallbacks.messages.length > 0) console.log(compilerTestCallbacks.messages[0]); + if (compilerTestCallbacks.messages.length > 1) console.log(compilerTestCallbacks.messages[1]); + assert.equal(compilerTestCallbacks.messages.length, 0); + }); }); }); From fcfe4f72bbc62efec88b3753284d390a17496ff5 Mon Sep 17 00:00:00 2001 From: Sabine Date: Tue, 31 Mar 2026 20:33:29 +0200 Subject: [PATCH 218/251] feat(developer): add console.log for 1 test --- .../src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index bcdd57bcbb0..a68b270087a 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -31,7 +31,11 @@ describe('KeylayoutToKmnConverter', function () { [makePathToFixture('../data/test_OtherOutputName.kmn')], ].forEach(function (files) { it(infile + " should run ", async function () { +console.log('infile',infile) +console.log('makePathToFixture(infile)',makePathToFixture(infile)) await NodeAssert.doesNotReject(async () => sut.run(makePathToFixture(infile), files[0])); + + if (compilerTestCallbacks.messages.length > 0) console.log(compilerTestCallbacks.messages[0]); if (compilerTestCallbacks.messages.length > 1) console.log(compilerTestCallbacks.messages[1]); assert.equal(compilerTestCallbacks.messages.length, 0); From 718d608aa0541af8095490870600c26bca94e815 Mon Sep 17 00:00:00 2001 From: Sabine Date: Tue, 31 Mar 2026 20:38:38 +0200 Subject: [PATCH 219/251] feat(developer): change 1 test --- .../src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index a68b270087a..4deb6d35f4a 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -30,10 +30,10 @@ describe('KeylayoutToKmnConverter', function () { [], [makePathToFixture('../data/test_OtherOutputName.kmn')], ].forEach(function (files) { - it(infile + " should run ", async function () { + it( "test.keylayout should run ", async function () { console.log('infile',infile) console.log('makePathToFixture(infile)',makePathToFixture(infile)) - await NodeAssert.doesNotReject(async () => sut.run(makePathToFixture(infile), files[0])); + await NodeAssert.doesNotReject(async () => sut.run(makePathToFixture('../data/test.keylayout'), files[0])); if (compilerTestCallbacks.messages.length > 0) console.log(compilerTestCallbacks.messages[0]); From e96a9fb67f20a06afb050dbdc670e9be87c6857a Mon Sep 17 00:00:00 2001 From: Sabine Date: Tue, 31 Mar 2026 20:38:38 +0200 Subject: [PATCH 220/251] feat(developer): change 1 test --- .../src/keylayout-to-kmn/keylayout-to-kmn-converter.ts | 2 ++ .../src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts | 5 +++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index d9764c0dfb5..532353c45b8 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -129,6 +129,8 @@ export class KeylayoutToKmnConverter { * @return null on success */ async run(inputFilename: string, outputFilename?: string): Promise { + + console.log('inputFilename', inputFilename, 'outputFilename', outputFilename); if (!inputFilename) { this.callbacks.reportMessage(ConverterMessages.Error_FileNotFound({ inputFilename })); return null; diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index a68b270087a..36127cbbcd1 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -30,10 +30,11 @@ describe('KeylayoutToKmnConverter', function () { [], [makePathToFixture('../data/test_OtherOutputName.kmn')], ].forEach(function (files) { - it(infile + " should run ", async function () { + it( "test.keylayout should run ", async function () { console.log('infile',infile) console.log('makePathToFixture(infile)',makePathToFixture(infile)) - await NodeAssert.doesNotReject(async () => sut.run(makePathToFixture(infile), files[0])); + await NodeAssert.doesNotReject(async () => sut.run(makePathToFixture('../data/test.keylayout'), files[0])); + if (compilerTestCallbacks.messages.length > 0) console.log(compilerTestCallbacks.messages[0]); From 023223d19937170f4b9b05b01f93e6cca987ac6f Mon Sep 17 00:00:00 2001 From: Sabine Date: Tue, 31 Mar 2026 21:25:03 +0200 Subject: [PATCH 221/251] feat(developer): use correct filename for test --- .../test/keylayout-to-kmn-converter.tests.ts | 23 ++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index 4deb6d35f4a..28a5f88891b 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -22,24 +22,17 @@ describe('KeylayoutToKmnConverter', function () { describe('Run kmc-convert with or without outputfile name', async function () { - this.timeout(5000); // allow longer time for this test const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const infile = '../data/test.keylayout'; + const infile = '../data/Test.keylayout'; [ - [makePathToFixture('../data/test.kmn')], + [makePathToFixture('../data/Test.kmn')], [], [makePathToFixture('../data/test_OtherOutputName.kmn')], ].forEach(function (files) { - it( "test.keylayout should run ", async function () { -console.log('infile',infile) -console.log('makePathToFixture(infile)',makePathToFixture(infile)) - await NodeAssert.doesNotReject(async () => sut.run(makePathToFixture('../data/test.keylayout'), files[0])); - - - if (compilerTestCallbacks.messages.length > 0) console.log(compilerTestCallbacks.messages[0]); - if (compilerTestCallbacks.messages.length > 1) console.log(compilerTestCallbacks.messages[1]); - assert.equal(compilerTestCallbacks.messages.length, 0); - }); + it(infile + " should run " , async function () { + await NodeAssert.doesNotReject(async () => sut.run(makePathToFixture(infile), files[0])); + assert.equal(compilerTestCallbacks.messages.length, 0); + }); }); }); @@ -88,6 +81,10 @@ console.log('makePathToFixture(infile)',makePathToFixture(infile)) [makePathToFixture('../data/Test_ambiguous_keys.keylayout')], [makePathToFixture('../data/Test_nr_elements.keylayout')], [makePathToFixture('../data/Test.keylayout')], + [makePathToFixture('../data/Test_mixedEncodings.keylayout')], + [makePathToFixture('../data/Test_Character_Codepoint_C0.keylayout')], + [makePathToFixture('../data/Test_Character_Codepoint_C2.keylayout')], + [makePathToFixture('../data/Test_Character_Codepoint_C3.keylayout')], ].forEach(function (files) { it(files + " should give no errors ", async function () { sut.run(files[0]); From 9920442c146667ed4628e685c6e98f71283bc344 Mon Sep 17 00:00:00 2001 From: Sabine Date: Tue, 31 Mar 2026 21:41:50 +0200 Subject: [PATCH 222/251] feat(developer): remove some tests --- .../src/keylayout-to-kmn/keylayout-to-kmn-converter.ts | 1 - .../src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts | 4 ---- 2 files changed, 5 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 532353c45b8..afe4c3d7c3f 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -130,7 +130,6 @@ export class KeylayoutToKmnConverter { */ async run(inputFilename: string, outputFilename?: string): Promise { - console.log('inputFilename', inputFilename, 'outputFilename', outputFilename); if (!inputFilename) { this.callbacks.reportMessage(ConverterMessages.Error_FileNotFound({ inputFilename })); return null; diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index 28a5f88891b..d6793ce3618 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -81,10 +81,6 @@ describe('KeylayoutToKmnConverter', function () { [makePathToFixture('../data/Test_ambiguous_keys.keylayout')], [makePathToFixture('../data/Test_nr_elements.keylayout')], [makePathToFixture('../data/Test.keylayout')], - [makePathToFixture('../data/Test_mixedEncodings.keylayout')], - [makePathToFixture('../data/Test_Character_Codepoint_C0.keylayout')], - [makePathToFixture('../data/Test_Character_Codepoint_C2.keylayout')], - [makePathToFixture('../data/Test_Character_Codepoint_C3.keylayout')], ].forEach(function (files) { it(files + " should give no errors ", async function () { sut.run(files[0]); From 0e67a6605a066c274ad9af39f5021b7306d61e94 Mon Sep 17 00:00:00 2001 From: Sabine Date: Thu, 2 Apr 2026 20:21:56 +0200 Subject: [PATCH 223/251] feat(developer): use KeymanXMLReader instead of XMLParser adapt writing use new keylayout.xsd without "@__" change name MAX_KEY_COUNT, USE_KEY_COUNT remove init() --- .../keylayout-to-kmn/keylayout-file-reader.ts | 18 +-- .../keylayout-to-kmn-converter.ts | 121 +++++++++--------- .../src/keylayout-to-kmn/kmn-file-writer.ts | 95 +++++++------- .../keylayout/dtd/keylayout.xsd | 50 ++++---- .../keylayout/keylayout.schema.json | 66 +++++----- 5 files changed, 170 insertions(+), 180 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts index cb4f8bcad83..bb57fdd315d 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts @@ -7,8 +7,7 @@ * */ -import { XMLParser } from 'fast-xml-parser'; -import { CompilerCallbacks, DeveloperUtilsMessages, Keylayout } from "@keymanapp/developer-utils"; +import { CompilerCallbacks, DeveloperUtilsMessages, Keylayout, KeymanXMLReader } from "@keymanapp/developer-utils"; import { util, SchemaValidators } from '@keymanapp/common-types'; import { ConverterMessages } from '../converter-messages.js'; import boxXmlArray = util.boxXmlArray; @@ -103,21 +102,11 @@ export class KeylayoutFileReader { * @param inputFilename the ukelele .keylayout-file to be parsed * @return in case of success: json object containing data of the .keylayout file; else null */ - //................................................................................................. - // new read() with fast xml parser (Uint8Array-> XMLSourceFile) public read(source: Uint8Array): Keylayout.KeylayoutXMLSourceFile { - const options = { - ignoreAttributes: [''], // we do not process an output character of "" - trimValues: false, // we do not trim values because if we do we cannot process an output character of " " (space) - parseTagValue: false, - attributeNamePrefix: '@__', // to access the attribute - ignoreDeclaration: true - }; - try { - const parser = new XMLParser(options); - const jsonObj = parser.parse(source); // get plain Object + const data = new TextDecoder().decode(source); + const jsonObj = new KeymanXMLReader('keylayout').parse(data) as Keylayout.KeylayoutXMLSourceFile; this.boxArray(jsonObj.keyboard); // jsonObj now contains arrays; no single fields return jsonObj; } @@ -126,5 +115,4 @@ export class KeylayoutFileReader { return null; } } - //................................................................................................. } diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index afe4c3d7c3f..caf939851c3 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -90,13 +90,14 @@ export class Rule { /** * @brief member function to find the number of keys defined in a .keykayout file. - * We process 'MAX_KEY_COUNT' keys at maximum. In case a keylayout has fewer keys defined, we use that smaller number of keys (USE_KEY_COUNT) + * We process 'MAX_KEY_IDENTIFIER' keys at maximum. + * In case a keylayout has fewer keys defined, we use that smaller number of keys (USED_KEY_IDENTIFIER) * @param data data read from keylayout file * @return usedKeyCount holding the number of keys of a certain keyMap used in a .keykayout file. */ export function findUsedKeysCount(data: any): number { - let usedKeyCount = KeylayoutToKmnConverter.MAX_KEY_COUNT; + let usedKeyCount = KeylayoutToKmnConverter.MAX_KEY_IDENTIFIER; if (data.keyboard.keyMapSet[0].keyMap[0].key.length < usedKeyCount) { // set max to n-1 (keys are zero indexed ) usedKeyCount = data.keyboard.keyMapSet[0].keyMap[0].key.length - 1; @@ -109,18 +110,14 @@ export class KeylayoutToKmnConverter { static readonly OUTPUT_FILE_EXTENSION = '.kmn'; static readonly SKIP_COMMENTED_LINES = false; static readonly MAX_CTRL_CHARACTER = 0x20; // the hightest control character we print out as a Unicode CodePoint - static readonly MAX_KEY_COUNT = 49; // At most we use key Nr 0 (A) -> key Nr 49 (Space) - static USE_KEY_COUNT = KeylayoutToKmnConverter.MAX_KEY_COUNT; // we use key Nr 0 (A) -> highest available key of .keylayout file + static readonly MAX_KEY_IDENTIFIER = 49; // At most we use key Nr 0 (A) -> key Nr 49 (Space) + static USED_KEY_IDENTIFIER = KeylayoutToKmnConverter.MAX_KEY_IDENTIFIER; // we use key Nr 0 (A) -> highest available key of .keylayout file private options: CompilerOptions; - async init(callbacks: CompilerCallbacks, options: CompilerOptions): Promise { + constructor(private callbacks: CompilerCallbacks, options: CompilerOptions) { this.options = { ...options }; - this.callbacks = callbacks; - return true; - } - - constructor(private callbacks: CompilerCallbacks, options: CompilerOptions) { }; + }; /** * @brief member function to run read/convert/write @@ -193,7 +190,7 @@ export class KeylayoutToKmnConverter { for (let j = 0; j < jsonObj.keyboard.modifierMap.keyMapSelect.length; j++) { const singleModifierSet: string[] = []; for (let k = 0; k < jsonObj.keyboard.modifierMap.keyMapSelect[j].modifier.length; k++) { - singleModifierSet.push(jsonObj.keyboard.modifierMap.keyMapSelect[j].modifier[k]['@__keys']); + singleModifierSet.push(jsonObj.keyboard.modifierMap.keyMapSelect[j].modifier[k]['keys']); } modifierBehavior.push(singleModifierSet); } @@ -208,7 +205,7 @@ export class KeylayoutToKmnConverter { dataObject.rules = rules; // fix the amount of processable keys to the maximun nr of keys of a keyMap to avoid processing more keys than defined - KeylayoutToKmnConverter.USE_KEY_COUNT = findUsedKeysCount(jsonObj); + KeylayoutToKmnConverter.USED_KEY_IDENTIFIER = findUsedKeysCount(jsonObj); // fill rules into 'rules' of dataObject return this.createRuleData(dataObject, jsonObj); @@ -238,7 +235,7 @@ export class KeylayoutToKmnConverter { return null; } - for (let j = 0; j <= KeylayoutToKmnConverter.MAX_KEY_COUNT; j++) { + for (let j = 0; j <= KeylayoutToKmnConverter.MAX_KEY_IDENTIFIER; j++) { // loop behaviors (in ukelele it is possible to define multiple modifier combinations that behave in the same way) for (let i = 0; i < jsonObj.keyboard.keyMapSet[0].keyMap.length; i++) { @@ -259,13 +256,13 @@ export class KeylayoutToKmnConverter { // ...............e. g. ............................................................................... // ............................................................................................................................... - if ((jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@__output'] !== undefined) - && (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@__output'] !== "")) { + if ((jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['output'] !== undefined) + && (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['output'] !== "")) { // loop modifiers for (let l = 0; l < dataUkelele.modifiers[i].length; l++) { - if (this.mapUkeleleKeycodeToVK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@__code']))) { + if (this.mapUkeleleKeycodeToVK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['code']))) { ruleObj = new Rule( /* ruleType */ "C0", @@ -281,8 +278,8 @@ export class KeylayoutToKmnConverter { /* unique B */ 0, /* modifierKey*/ this.createKmnModifier(dataUkelele.modifiers[i][l], isCapsused), - /* key */ this.mapUkeleleKeycodeToVK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@__code'])), - /* output */ new TextEncoder().encode(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@__output']), + /* key */ this.mapUkeleleKeycodeToVK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['code'])), + /* output */ new TextEncoder().encode(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['output']), ); rules.push(ruleObj); } @@ -290,9 +287,9 @@ export class KeylayoutToKmnConverter { // } } - else if (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@__action'] !== undefined) { + else if (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['action'] !== undefined) { - actionId = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@__action']; + actionId = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['action']; // ............................................................................................................................... // case C1: action + state none + output ......................................................................................... // C1 see: https://docs.google.com/document/d/12J3NGO6RxIthCpZDTR8FYSRjiMgXJDLwPY2z9xqKzJ0/edit?tab=t.0#heading=h.g7jwx3lx0ydd ... @@ -347,10 +344,10 @@ export class KeylayoutToKmnConverter { const b1ActionIndex: number = this.getActionIndexFromActionId(jsonObj, actionId); if (b1ActionIndex < 0) { this.callbacks.reportMessage(ConverterMessages.Error_UndefinedActionDetected({ - inputFilename: jsonObj.keyboard['@__name'] + ".keylayout", + inputFilename: jsonObj.keyboard['name'] + ".keylayout", action: actionId, - KeyName: this.mapUkeleleKeycodeToVK(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@__code']), - keymapIndex: jsonObj.keyboard.keyMapSet[0].keyMap[i]['@__index'] + KeyName: this.mapUkeleleKeycodeToVK(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['code']), + keymapIndex: jsonObj.keyboard.keyMapSet[0].keyMap[i]['index'] })); return null; } @@ -358,12 +355,12 @@ export class KeylayoutToKmnConverter { // with actionId from above loop all 'action' and search for a state(none)-next-pair ............................................................................................................ // e.g. in Block 5: find for action id a18 ...................................................................................................................... for (let l = 0; l < jsonObj.keyboard.actions.action[b1ActionIndex].when.length; l++) { - if ((jsonObj.keyboard.actions.action[b1ActionIndex].when[l]['@__state'] === "none") // find "none" - && (jsonObj.keyboard.actions.action[b1ActionIndex].when[l]['@__next'] !== undefined)) { // find "next" + if ((jsonObj.keyboard.actions.action[b1ActionIndex].when[l]['state'] === "none") // find "none" + && (jsonObj.keyboard.actions.action[b1ActionIndex].when[l]['next'] !== undefined)) { // find "next" // Data of Block Nr 5 ..................................................................................................................................................................... // of this state(none)-next-pair get value of next (next="1") ............................................................................................................................. - /* eg: 1 */ const b5ValueNext: string = jsonObj.keyboard.actions.action[b1ActionIndex].when[l]['@__next']; + /* eg: 1 */ const b5ValueNext: string = jsonObj.keyboard.actions.action[b1ActionIndex].when[l]['next']; // ........................................................................................................................................................................................ @@ -435,13 +432,13 @@ export class KeylayoutToKmnConverter { // with actionId from above loop all 'action' and search for a state-next-pair ................................................................................................................... // e.g. in Block 5: find for action id a16 ............................................................................................................................. for (let l = 0; l < jsonObj.keyboard.actions.action[b1ActionIndex].when.length; l++) { - if ((jsonObj.keyboard.actions.action[b1ActionIndex].when[l]['@__state'] !== "none") - && (jsonObj.keyboard.actions.action[b1ActionIndex].when[l]['@__next'] !== undefined)) { + if ((jsonObj.keyboard.actions.action[b1ActionIndex].when[l]['state'] !== "none") + && (jsonObj.keyboard.actions.action[b1ActionIndex].when[l]['next'] !== undefined)) { // Data of Block Nr 5 ........................................................................................................................................................................ // of this state-next-pair get value of next (next="1") and state="3" ........................................................................................................................ - /* e.g. state = 3 */ const b5ValueState: string = jsonObj.keyboard.actions.action[b1ActionIndex].when[l]['@__state']; - /* e.g. next = 1 */ const b5ValueNext: string = jsonObj.keyboard.actions.action[b1ActionIndex].when[l]['@__next']; + /* e.g. state = 3 */ const b5ValueState: string = jsonObj.keyboard.actions.action[b1ActionIndex].when[l]['state']; + /* e.g. next = 1 */ const b5ValueNext: string = jsonObj.keyboard.actions.action[b1ActionIndex].when[l]['next']; // ........................................................................................................................................................................................... // Data of Block Nr 4 ........................................................................................................................................................................ @@ -514,11 +511,11 @@ export class KeylayoutToKmnConverter { } } else { this.callbacks.reportMessage(ConverterMessages.Error_UnsupportedCharactersDetected({ - inputFilename: jsonObj.keyboard['@__name'] + ".keylayout", - keymapIndex: jsonObj.keyboard.keyMapSet[0].keyMap[i]['@__index'], - output: jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@__output'], - key: jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@__code'], - KeyName: this.mapUkeleleKeycodeToVK(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@__code']) + inputFilename: jsonObj.keyboard['name'] + ".keylayout", + keymapIndex: jsonObj.keyboard.keyMapSet[0].keyMap[i]['index'], + output: jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['output'], + key: jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['code'], + KeyName: this.mapUkeleleKeycodeToVK(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['code']) })); return null; } @@ -819,7 +816,7 @@ export class KeylayoutToKmnConverter { */ public getActionIndexFromActionId(data: any, search: string): number { for (let i = 0; i < data.keyboard.actions.action.length; i++) { - if (data.keyboard.actions.action[i]['@__id'] === search) { + if (data.keyboard.actions.action[i]['id'] === search) { return i; } } @@ -836,8 +833,8 @@ export class KeylayoutToKmnConverter { if (search !== "none") { for (let i = 0; i < data.keyboard.actions.action.length; i++) { for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { - if (data.keyboard.actions.action[i].when[j]['@__next'] === search) { - return data.keyboard.actions.action[i]['@__id']; + if (data.keyboard.actions.action[i].when[j]['next'] === search) { + return data.keyboard.actions.action[i]['id']; } } } @@ -869,11 +866,11 @@ export class KeylayoutToKmnConverter { public getOutputFromActionIdNone(data: any, search: string): string { let OutputValue: string = ""; for (let i = 0; i < data.keyboard.actions.action.length; i++) { - if (data.keyboard.actions.action[i]['@__id'] === search) { + if (data.keyboard.actions.action[i]['id'] === search) { for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { - if (data.keyboard.actions.action[i].when[j]['@__state'] === "none") { - if (data.keyboard.actions.action[i].when[j]['@__output'] !== undefined) { - OutputValue = data.keyboard.actions.action[i].when[j]['@__output']; + if (data.keyboard.actions.action[i].when[j]['state'] === "none") { + if (data.keyboard.actions.action[i].when[j]['output'] !== undefined) { + OutputValue = data.keyboard.actions.action[i].when[j]['output']; } } } @@ -898,13 +895,13 @@ export class KeylayoutToKmnConverter { for (let k = 0; k < search.length; k++) { for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { - if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@__action'] === search[k].id && - data.keyboard.keyMapSet[0].keyMap[i].key[j]['@__code'] <= KeylayoutToKmnConverter.MAX_KEY_COUNT) { + if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['action'] === search[k].id && + data.keyboard.keyMapSet[0].keyMap[i].key[j]['code'] <= KeylayoutToKmnConverter.MAX_KEY_IDENTIFIER) { const singleDataSet = { - keyCode: data.keyboard.keyMapSet[0].keyMap[i].key[j]['@__code'], - key: this.mapUkeleleKeycodeToVK(Number(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@__code'])), - actionId: data.keyboard.keyMapSet[0].keyMap[i].key[j]['@__action'], - behavior: data.keyboard.keyMapSet[0].keyMap[i]['@__index'], + keyCode: data.keyboard.keyMapSet[0].keyMap[i].key[j]['code'], + key: this.mapUkeleleKeycodeToVK(Number(data.keyboard.keyMapSet[0].keyMap[i].key[j]['code'])), + actionId: data.keyboard.keyMapSet[0].keyMap[i].key[j]['action'], + behavior: data.keyboard.keyMapSet[0].keyMap[i]['index'], outchar: search[k].output }; keyActionOutput.push(singleDataSet); @@ -926,12 +923,12 @@ export class KeylayoutToKmnConverter { for (let i = 0; i < data.keyboard.actions.action.length; i++) { for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { - if (data.keyboard.actions.action[i].when[j]['@__state'] === search) { - if (data.keyboard.actions.action[i].when[j]['@__output'] !== undefined) { + if (data.keyboard.actions.action[i].when[j]['state'] === search) { + if (data.keyboard.actions.action[i].when[j]['output'] !== undefined) { const singleDataSet = { - id: data.keyboard.actions.action[i]['@__id'], - state: data.keyboard.actions.action[i].when[j]['@__state'], - output: data.keyboard.actions.action[i].when[j]['@__output'] + id: data.keyboard.actions.action[i]['id'], + state: data.keyboard.actions.action[i].when[j]['state'], + output: data.keyboard.actions.action[i].when[j]['output'] }; actionStateOutput.push(singleDataSet); } @@ -959,7 +956,7 @@ export class KeylayoutToKmnConverter { actionId: search[i].actionId, key: search[i].key, behavior: search[i].behavior, - modifier: this.createKmnModifier(data.keyboard.modifierMap.keyMapSelect[behaviorIdx].modifier[j]['@__keys'], isCAPSused), + modifier: this.createKmnModifier(data.keyboard.modifierMap.keyMapSelect[behaviorIdx].modifier[j]['keys'], isCAPSused), outchar: search[i].outchar, }; keyBehaviorModOutput.push(singleDataSet); @@ -1000,14 +997,14 @@ export class KeylayoutToKmnConverter { // loop behaviors (in ukelele it is possible to define multiple modifier combinations that behave in the same way) for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { - if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@__action'] === search) { - for (let k = 0; k < modi[data.keyboard.keyMapSet[0].keyMap[i]['@__index']].length; k++) { - const behaviorIdx: number = data.keyboard.keyMapSet[0].keyMap[i]['@__index']; + if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['action'] === search) { + for (let k = 0; k < modi[data.keyboard.keyMapSet[0].keyMap[i]['index']].length; k++) { + const behaviorIdx: number = data.keyboard.keyMapSet[0].keyMap[i]['index']; const singleDataSet = { outchar: outchar, - actionId: data.keyboard.keyMapSet[0].keyMap[i].key[j]['@__action'], - behavior: data.keyboard.keyMapSet[0].keyMap[i]['@__index'], - key: this.mapUkeleleKeycodeToVK(Number(data.keyboard.keyMapSet[0].keyMap[i].key[j]['@__code'])), + actionId: data.keyboard.keyMapSet[0].keyMap[i].key[j]['action'], + behavior: data.keyboard.keyMapSet[0].keyMap[i]['index'], + key: this.mapUkeleleKeycodeToVK(Number(data.keyboard.keyMapSet[0].keyMap[i].key[j]['code'])), modifier: this.createKmnModifier(modi[behaviorIdx][k], isCapsused), }; actionOutputBehaviorKeyModi.push(singleDataSet); @@ -1045,9 +1042,9 @@ export class KeylayoutToKmnConverter { const mapIndexObject1D: KeylayoutFileData[] = []; for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { - if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['@__action'] === search) { + if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['action'] === search) { const singleDataSet = { - key: data.keyboard.keyMapSet[0].keyMap[i].key[j]['@__code'], + key: data.keyboard.keyMapSet[0].keyMap[i].key[j]['code'], behavior: String(i), }; mapIndexObject1D.push(singleDataSet); diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts index a027b853ab7..8e5840e438e 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts @@ -117,7 +117,7 @@ export class KmnFileWriter { // lookup key nr of the key which is being processed let keyNr: number = 0; - for (let j = 0; j <= KeylayoutToKmnConverter.MAX_KEY_COUNT; j++) { + for (let j = 0; j <= KeylayoutToKmnConverter.MAX_KEY_IDENTIFIER; j++) { if (keylayoutKmnConverter.mapUkeleleKeycodeToVK(j) === uniqueDataRules[k].key) { keyNr = j; break; @@ -146,22 +146,18 @@ export class KmnFileWriter { // const outputUnicodeCharacter = util.convertToUnicodeCharacter(outputCharacter); // const outputUnicodeCodePoint = util.convertToUnicodeCodePoint(outputCharacter); const outputUnicodeCharacter = this.convertToUnicodeCharacter(outputCharacter); - const outputUnicodeCodePoint = this.convertToUnicodeCodePoint(outputCharacter); - if ((outputUnicodeCharacter !== undefined) && (outputUnicodeCodePoint !== undefined)) { + if ((outputCharacter !== undefined) || (outputCharacter !== "")) { // if we are about to print a unicode codepoint instead of a single character we need to check if it is a control character - if ((Number("0x" + outputUnicodeCodePoint.substring(2, outputUnicodeCodePoint.length)) < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER)) { + if (outputCharacter.charCodeAt(0) < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER) { + versionOutputCharacter = "U+" + outputCharacter.charCodeAt(0).toString(16).toUpperCase().padStart(4, '0'); - versionOutputCharacter = outputUnicodeCodePoint; - - if (outputUnicodeCodePoint.length > 1) { - if (warnText[2] == "") { - warnText[2] = warnText[2] + "c WARNING: use of a control character " /*+ outputUnicodeCodePoint*/; - } - else { - warnText[2] = warnText[2] + " Use of a control character "/* + outputUnicodeCodePoint*/; - } + if (warnText[2] == "") { + warnText[2] = warnText[2] + "c WARNING: use of a control character " /*+ outputUnicodeCodePoint*/; + } + else { + warnText[2] = warnText[2] + " Use of a control character "/* + outputUnicodeCodePoint*/; } } else { versionOutputCharacter = outputUnicodeCharacter; @@ -214,19 +210,18 @@ export class KmnFileWriter { // const outputUnicodeCharacter = util.convertToUnicodeCharacter(outputCharacter); // const outputUnicodeCodePoint = util.convertToUnicodeCodePoint(outputCharacter); const outputUnicodeCharacter = this.convertToUnicodeCharacter(outputCharacter); - const outputUnicodeCodePoint = this.convertToUnicodeCodePoint(outputCharacter); - if ((outputUnicodeCharacter !== undefined) && (outputUnicodeCodePoint !== undefined)) { + if ((outputCharacter !== undefined) || (outputCharacter !== "")) { // if we are about to print a unicode codepoint instead of a single character we need to check if it is a control character - if (Number("0x" + outputUnicodeCodePoint.substring(2, outputUnicodeCodePoint.length)) < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER) { - versionOutputCharacter = outputUnicodeCodePoint; - if (outputUnicodeCodePoint.length > 1) { - if (warnText[2] == "") { - warnText[2] = warnText[2] + "c WARNING: use of a control character "; - } - else { - warnText[2] = warnText[2] + "; Use of a control character "; - } + if (outputCharacter.charCodeAt(0) < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER) { + + versionOutputCharacter = "U+" + outputCharacter.charCodeAt(0).toString(16).toUpperCase().padStart(4, '0'); + + if (warnText[2] == "") { + warnText[2] = warnText[2] + "c WARNING: use of a control character "; + } + else { + warnText[2] = warnText[2] + "; Use of a control character "; } } else { versionOutputCharacter = outputUnicodeCharacter; @@ -300,24 +295,19 @@ export class KmnFileWriter { const warnText = this.reviewRules(uniqueDataRules, k); const outputCharacter = new TextDecoder().decode(uniqueDataRules[k].output); // TODO-kmc-convert: after merge of PR 14564 use functions from util instead of the ones in this class - //const outputUnicodeCharacter = util.convertToUnicodeCharacter(outputCharacter); - //const outputUnicodeCodePoint = util.convertToUnicodeCodePoint(outputCharacter); const outputUnicodeCharacter = this.convertToUnicodeCharacter(outputCharacter); - const outputUnicodeCodePoint = this.convertToUnicodeCodePoint(outputCharacter); - if ((outputUnicodeCharacter !== undefined) && (outputUnicodeCodePoint !== undefined)) { + if ((outputCharacter !== undefined) || (outputCharacter !== "")) { // if we are about to print a unicode codepoint instead of a single character we need to check if a control character is to be used - if (Number("0x" + outputUnicodeCodePoint.substring(2, outputUnicodeCodePoint.length)) < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER) { + if (outputCharacter.charCodeAt(0) < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER) { - versionOutputCharacter = outputUnicodeCodePoint; + versionOutputCharacter = "U+" + outputCharacter.charCodeAt(0).toString(16).toUpperCase().padStart(4, '0'); - if (outputUnicodeCodePoint.length > 1) { - if (warnText[2] == "") { - warnText[2] = warnText[2] + "c WARNING: use of a control character "; - } - else { - warnText[2] = warnText[2] + "; Use of a control character "; - } + if (warnText[2] == "") { + warnText[2] = warnText[2] + "c WARNING: use of a control character "; + } + else { + warnText[2] = warnText[2] + "; Use of a control character "; } } else { versionOutputCharacter = outputUnicodeCharacter; @@ -527,7 +517,7 @@ export class KmnFileWriter { + " " + amb_1_1[0].key + "] > \'" - + new TextDecoder().decode(amb_1_1[0].output) + + this.writeCharacterOrUnicode(new TextDecoder().decode(amb_1_1[0].output)) + "\' "); } @@ -538,7 +528,7 @@ export class KmnFileWriter { + " " + dup_1_1[0].key + "] > \'" - + new TextDecoder().decode(dup_1_1[0].output) + + this.writeCharacterOrUnicode(new TextDecoder().decode(dup_1_1[0].output)) + "\' "); } } @@ -623,7 +613,8 @@ export class KmnFileWriter { + " " + amb_3_3[0].key + "] > \'" - + new TextDecoder().decode(amb_3_3[0].output) + /*+ new TextDecoder().decode(amb_3_3[0].output)*/ + + this.writeCharacterOrUnicode(new TextDecoder().decode(amb_3_3[0].output)) + "\' "); } @@ -636,7 +627,8 @@ export class KmnFileWriter { + " " + dup_3_3[0].key + "] > \'" - + new TextDecoder().decode(dup_3_3[0].output) + /* + new TextDecoder().decode(dup_3_3[0].output)*/ + + this.writeCharacterOrUnicode(new TextDecoder().decode(dup_3_3[0].output)) + "\' "); } @@ -764,7 +756,7 @@ export class KmnFileWriter { + " " + amb_6_3[0].key + "] > \'" - + new TextDecoder().decode(amb_6_3[0].output) + + this.writeCharacterOrUnicode(new TextDecoder().decode(amb_6_3[0].output)) + "\' "); } @@ -777,7 +769,7 @@ export class KmnFileWriter { + " " + dup_6_3[0].key + "] > \'" - + new TextDecoder().decode(dup_6_3[0].output) + + this.writeCharacterOrUnicode(new TextDecoder().decode(dup_6_3[0].output)) + "\' "); } @@ -838,7 +830,7 @@ export class KmnFileWriter { + " " + amb_6_6[0].key + "] > \'" - + new TextDecoder().decode(amb_6_6[0].output) + + this.writeCharacterOrUnicode(new TextDecoder().decode(amb_6_6[0].output)) + "\' "); } @@ -851,7 +843,7 @@ export class KmnFileWriter { + " " + dup_6_6[0].key + "] > \'" - + new TextDecoder().decode(dup_6_6[0].output) + + this.writeCharacterOrUnicode(new TextDecoder().decode(dup_6_6[0].output)) + "\' "); } } @@ -889,6 +881,19 @@ export class KmnFileWriter { return warningText; } + /** + * @brief member function to write a character as Unicode Character or Unicode Codepoint depending on the character that is to be written + * @param ctr : string - the character to be written + * @return a string containing the Unicode representation of the character. + * A control character will be written as unicode (U+0004), + * a non-control character will be written as itself ( 'A', '1', '፩', '😎') + */ + public writeCharacterOrUnicode(ctr: string): string { + return (ctr.charCodeAt(0) < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER) ? + ("U+" + ctr.charCodeAt(0).toString(16).toUpperCase().padStart(4, '0')) + : ctr; + } + // TODO: move to util /** * @brief function to convert a numeric character reference or a unicode value to a unicode character e.g. c -> c; U+1F60E -> 😎 diff --git a/resources/standards-data/keylayout/dtd/keylayout.xsd b/resources/standards-data/keylayout/dtd/keylayout.xsd index 9dc4b4d6fc5..f9aea8c67d4 100644 --- a/resources/standards-data/keylayout/dtd/keylayout.xsd +++ b/resources/standards-data/keylayout/dtd/keylayout.xsd @@ -12,10 +12,10 @@ - - - - + + + + @@ -29,15 +29,15 @@ - + - + - - + + @@ -48,17 +48,17 @@ - - - + + + - - - + + + - + @@ -70,12 +70,12 @@ - - - + + + - + @@ -87,18 +87,18 @@ - - + + - - - - + + + + diff --git a/resources/standards-data/keylayout/keylayout.schema.json b/resources/standards-data/keylayout/keylayout.schema.json index 3772136300c..41b9fa6b2ed 100644 --- a/resources/standards-data/keylayout/keylayout.schema.json +++ b/resources/standards-data/keylayout/keylayout.schema.json @@ -5,18 +5,6 @@ "keyboard": { "additionalProperties": false, "properties": { - "@__group": { - "type": "string" - }, - "@__id": { - "type": "string" - }, - "@__maxout": { - "type": "string" - }, - "@__name": { - "type": "string" - }, "actions": { "additionalProperties": false, "properties": { @@ -24,20 +12,20 @@ "items": { "additionalProperties": false, "properties": { - "@__id": { + "id": { "type": "string" }, "when": { "items": { "additionalProperties": false, "properties": { - "@__next": { + "next": { "type": "string" }, - "@__output": { + "output": { "type": "string" }, - "@__state": { + "state": { "type": "string" } }, @@ -61,37 +49,43 @@ ], "type": "object" }, + "group": { + "type": "string" + }, + "id": { + "type": "string" + }, "keyMapSet": { "items": { "additionalProperties": false, "properties": { - "@__id": { + "id": { "type": "string" }, "keyMap": { "items": { "additionalProperties": false, "properties": { - "@__baseIndex": { + "baseIndex": { "type": "string" }, - "@__baseMapSet": { + "baseMapSet": { "type": "string" }, - "@__index": { + "index": { "type": "string" }, "key": { "items": { "additionalProperties": false, "properties": { - "@__action": { + "action": { "type": "string" }, - "@__code": { + "code": { "type": "string" }, - "@__output": { + "output": { "type": "string" } }, @@ -125,16 +119,16 @@ "items": { "additionalProperties": false, "properties": { - "@__first": { + "first": { "type": "string" }, - "@__last": { + "last": { "type": "string" }, - "@__mapSet": { + "mapSet": { "type": "string" }, - "@__modifiers": { + "modifiers": { "type": "string" } }, @@ -149,27 +143,30 @@ ], "type": "object" }, + "maxout": { + "type": "string" + }, "modifierMap": { "additionalProperties": false, "properties": { - "@__defaultIndex": { + "defaultIndex": { "type": "string" }, - "@__id": { + "id": { "type": "string" }, "keyMapSelect": { "items": { "additionalProperties": false, "properties": { - "@__mapIndex": { + "mapIndex": { "type": "string" }, "modifier": { "items": { "additionalProperties": false, "properties": { - "@__keys": { + "keys": { "type": "string" } }, @@ -193,6 +190,9 @@ ], "type": "object" }, + "name": { + "type": "string" + }, "terminators": { "additionalProperties": false, "properties": { @@ -200,10 +200,10 @@ "items": { "additionalProperties": false, "properties": { - "@__output": { + "output": { "type": "string" }, - "@__state": { + "state": { "type": "string" } }, From 870f75d50a7ad26b1092d44a22e8ff93183fdd81 Mon Sep 17 00:00:00 2001 From: Sabine Date: Fri, 3 Apr 2026 09:56:39 +0200 Subject: [PATCH 224/251] feat(developer): removed removeWhitespace(), removeWhitespaceBoxArray() --- .../keylayout-to-kmn/keylayout-file-reader.ts | 49 +++++-------------- 1 file changed, 11 insertions(+), 38 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts index bb57fdd315d..2dc98fdb3c5 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts @@ -31,31 +31,6 @@ export class KeylayoutFileReader { return true; } - /** - * If object contains attribute #text it will be removed. - * @param o Object with possible property #text containing whitespaces - * @return objects that do not contain property #text - */ - public removeWhitespace(o: any): void { - if (o !== undefined) { - if (o['#text']) { - delete o['#text']; - } - } - } - - /** - * @brief wrapper to remove whitespace and box single-entry objects into arrays - * @param o Object with property to box/remove whitespaces from - * @param x Name of element to box - * @return objects that contain only boxed arrays - */ - public removeWhitespaceBoxArray(o: any, x: string): void { - - this.removeWhitespace(o); - boxXmlArray(o, x); - } - /** * @brief member function to box single-entry objects into arrays * @param source the object to be changed @@ -63,34 +38,32 @@ export class KeylayoutFileReader { */ public boxArray(source: any) { - this.removeWhitespace(source); - - this.removeWhitespaceBoxArray(source, 'keyMapSet'); + boxXmlArray(source, 'keyMapSet'); - this.removeWhitespaceBoxArray(source.layouts, 'layout'); - this.removeWhitespaceBoxArray(source?.modifierMap, 'keyMapSelect'); + boxXmlArray(source.layouts, 'layout'); + boxXmlArray(source?.modifierMap, 'keyMapSelect'); for (const keyMapSelect of source?.modifierMap?.keyMapSelect) { - this.removeWhitespaceBoxArray(keyMapSelect, 'modifier'); + boxXmlArray(keyMapSelect, 'modifier'); } - this.removeWhitespaceBoxArray(source.keyMapSet[0], 'keyMap'); + boxXmlArray(source.keyMapSet[0], 'keyMap'); for (const keyMapSet of source?.keyMapSet) { for (const keyMap of keyMapSet.keyMap) { - this.removeWhitespaceBoxArray(keyMap, 'key'); + boxXmlArray(keyMap, 'key'); } - this.removeWhitespaceBoxArray(keyMapSet, 'keyMap'); + boxXmlArray(keyMapSet, 'keyMap'); } - this.removeWhitespaceBoxArray(source?.actions, 'action'); + boxXmlArray(source?.actions, 'action'); for (const action of source?.actions?.action) { - this.removeWhitespaceBoxArray(action, 'when'); + boxXmlArray(action, 'when'); } - this.removeWhitespaceBoxArray(source.terminators, 'when'); + boxXmlArray(source.terminators, 'when'); for (const action of source?.actions?.action) { - this.removeWhitespaceBoxArray(action, 'when'); + boxXmlArray(action, 'when'); } return source; From 64df04dfe6418addbb642b111f3921447ae40652 Mon Sep 17 00:00:00 2001 From: Sabine Date: Wed, 8 Apr 2026 13:36:38 +0200 Subject: [PATCH 225/251] feat(developer): writing of control characters --- .../src/keylayout-to-kmn/kmn-file-writer.ts | 241 ++++++++++++++---- .../kmc-convert/test/kmn-file-writer.tests.ts | 6 +- 2 files changed, 193 insertions(+), 54 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts index 8e5840e438e..17c0c73391b 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts @@ -145,22 +145,40 @@ export class KmnFileWriter { // TODO-kmc-convert: after merge of PR 14564 use functions from util instead of the ones in this class // const outputUnicodeCharacter = util.convertToUnicodeCharacter(outputCharacter); // const outputUnicodeCodePoint = util.convertToUnicodeCodePoint(outputCharacter); - const outputUnicodeCharacter = this.convertToUnicodeCharacter(outputCharacter); if ((outputCharacter !== undefined) || (outputCharacter !== "")) { - // if we are about to print a unicode codepoint instead of a single character we need to check if it is a control character - if (outputCharacter.charCodeAt(0) < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER) { - versionOutputCharacter = "U+" + outputCharacter.charCodeAt(0).toString(16).toUpperCase().padStart(4, '0'); + const m_uni = /^U\+([0-9a-f]{1,6})$/i.exec(outputCharacter); + const m_hex = /^&#x([0-9a-f]{1,6});$/i.exec(outputCharacter); + const m_dec = /^&#([0-9]{1,7});$/.exec(outputCharacter); + + // find the value of output character which may be specified in unicode, html hex or html dec format ( e.g. U+1234 -> 1234; ሴ -> 1234; ሴ -> 1234) + const c_val = ((m_uni || m_hex || m_dec) ? + m_uni ? parseInt(m_uni[1], 16) : m_hex ? parseInt(m_hex[1], 16) : parseInt(m_dec[1], 10) : KeylayoutToKmnConverter.MAX_CTRL_CHARACTER + ); + + // for control charactersin 'U+...', '&#x...' or '&#...' format as well as in "" format + if ((c_val < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER) || (outputCharacter.charCodeAt(0) < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER)) { + + // for control characters in 'U+...', '&#x...' or '&#...' format + if (c_val < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER) { + versionOutputCharacter = "U+" + c_val.toString(16).toUpperCase().padStart(4, '0'); + } + + // for control characters in "" format + if (outputCharacter.charCodeAt(0) < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER) { + versionOutputCharacter = "U+" + outputCharacter.charCodeAt(0).toString(16).toUpperCase().padStart(4, '0'); + } if (warnText[2] == "") { - warnText[2] = warnText[2] + "c WARNING: use of a control character " /*+ outputUnicodeCodePoint*/; + warnText[2] = warnText[2] + "c WARNING: use of a control character "; } else { - warnText[2] = warnText[2] + " Use of a control character "/* + outputUnicodeCodePoint*/; + warnText[2] = warnText[2] + " Use of a control character "; } - } else { - versionOutputCharacter = outputUnicodeCharacter; + } + else { + versionOutputCharacter = this.convertToUnicodeCharacter(outputCharacter);; } } // add a warning in front of rules in case unavailable modifiers or ambiguous rules are used @@ -209,13 +227,30 @@ export class KmnFileWriter { // TODO-kmc-convert: after merge of PR 14564 use functions from util instead of the ones in this class // const outputUnicodeCharacter = util.convertToUnicodeCharacter(outputCharacter); // const outputUnicodeCodePoint = util.convertToUnicodeCodePoint(outputCharacter); - const outputUnicodeCharacter = this.convertToUnicodeCharacter(outputCharacter); if ((outputCharacter !== undefined) || (outputCharacter !== "")) { - // if we are about to print a unicode codepoint instead of a single character we need to check if it is a control character - if (outputCharacter.charCodeAt(0) < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER) { - versionOutputCharacter = "U+" + outputCharacter.charCodeAt(0).toString(16).toUpperCase().padStart(4, '0'); + const m_uni = /^U\+([0-9a-f]{1,6})$/i.exec(outputCharacter); + const m_hex = /^&#x([0-9a-f]{1,6});$/i.exec(outputCharacter); + const m_dec = /^&#([0-9]{1,7});$/.exec(outputCharacter); + + // find the value of output character which may be specified in unicode, html hex or html dec format ( e.g. U+1234 -> 1234; ሴ -> 1234; ሴ -> 1234) + const c_val = ((m_uni || m_hex || m_dec) ? + m_uni ? parseInt(m_uni[1], 16) : m_hex ? parseInt(m_hex[1], 16) : parseInt(m_dec[1], 10) : KeylayoutToKmnConverter.MAX_CTRL_CHARACTER + ); + + // for control charactersin 'U+...', '&#x...' or '&#...' format as well as in "" format + if ((c_val < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER) || (outputCharacter.charCodeAt(0) < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER)) { + + // for control characters in 'U+...', '&#x...' or '&#...' format + if (c_val < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER) { + versionOutputCharacter = "U+" + c_val.toString(16).toUpperCase().padStart(4, '0'); + } + + // for control characters in "" format + if (outputCharacter.charCodeAt(0) < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER) { + versionOutputCharacter = "U+" + outputCharacter.charCodeAt(0).toString(16).toUpperCase().padStart(4, '0'); + } if (warnText[2] == "") { warnText[2] = warnText[2] + "c WARNING: use of a control character "; @@ -223,11 +258,16 @@ export class KmnFileWriter { else { warnText[2] = warnText[2] + "; Use of a control character "; } - } else { - versionOutputCharacter = outputUnicodeCharacter; + } + else { + versionOutputCharacter = this.convertToUnicodeCharacter(outputCharacter);; } } + + + + // add a warning in front of rules in case unavailable modifiers or ambiguous rules are used // if warning contains duplicate rules we do not write out the entire rule // (even if there are other warnings for the same rule) since that rule had been written before @@ -295,13 +335,30 @@ export class KmnFileWriter { const warnText = this.reviewRules(uniqueDataRules, k); const outputCharacter = new TextDecoder().decode(uniqueDataRules[k].output); // TODO-kmc-convert: after merge of PR 14564 use functions from util instead of the ones in this class - const outputUnicodeCharacter = this.convertToUnicodeCharacter(outputCharacter); if ((outputCharacter !== undefined) || (outputCharacter !== "")) { - // if we are about to print a unicode codepoint instead of a single character we need to check if a control character is to be used - if (outputCharacter.charCodeAt(0) < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER) { - versionOutputCharacter = "U+" + outputCharacter.charCodeAt(0).toString(16).toUpperCase().padStart(4, '0'); + const m_uni = /^U\+([0-9a-f]{1,6})$/i.exec(outputCharacter); + const m_hex = /^&#x([0-9a-f]{1,6});$/i.exec(outputCharacter); + const m_dec = /^&#([0-9]{1,7});$/.exec(outputCharacter); + + // find the value of output character which may be specified in unicode, html hex or html dec format ( e.g. U+1234 -> 1234; ሴ -> 1234; ሴ -> 1234) + const c_val = ((m_uni || m_hex || m_dec) ? + m_uni ? parseInt(m_uni[1], 16) : m_hex ? parseInt(m_hex[1], 16) : parseInt(m_dec[1], 10) : KeylayoutToKmnConverter.MAX_CTRL_CHARACTER + ); + + // for control charactersin 'U+...', '&#x...' or '&#...' format as well as in "" format + if ((c_val < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER) || (outputCharacter.charCodeAt(0) < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER)) { + + // for control characters in 'U+...', '&#x...' or '&#...' format + if (c_val < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER) { + versionOutputCharacter = "U+" + c_val.toString(16).toUpperCase().padStart(4, '0'); + } + + // for control characters in "" format + if (outputCharacter.charCodeAt(0) < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER) { + versionOutputCharacter = "U+" + outputCharacter.charCodeAt(0).toString(16).toUpperCase().padStart(4, '0'); + } if (warnText[2] == "") { warnText[2] = warnText[2] + "c WARNING: use of a control character "; @@ -309,10 +366,12 @@ export class KmnFileWriter { else { warnText[2] = warnText[2] + "; Use of a control character "; } - } else { - versionOutputCharacter = outputUnicodeCharacter; + } + else { + versionOutputCharacter = this.convertToUnicodeCharacter(outputCharacter);; } } + // add a warning in front of rules in case unavailable modifiers or ambiguous rules are used // if warning contains duplicate rules we do not write out the entire rule // (even if there are other warnings for the same rule) since that rule had been written before @@ -884,14 +943,43 @@ export class KmnFileWriter { /** * @brief member function to write a character as Unicode Character or Unicode Codepoint depending on the character that is to be written * @param ctr : string - the character to be written - * @return a string containing the Unicode representation of the character. + * @return a string containing the Unicode representation of the control character. * A control character will be written as unicode (U+0004), * a non-control character will be written as itself ( 'A', '1', '፩', '😎') + * null in case of an empty string or null or undefined input */ - public writeCharacterOrUnicode(ctr: string): string { - return (ctr.charCodeAt(0) < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER) ? - ("U+" + ctr.charCodeAt(0).toString(16).toUpperCase().padStart(4, '0')) - : ctr; + public writeCharacterOrUnicode(ctr: string): string | null { + + if ((ctr === null) || (ctr === undefined) || (ctr.length === 0)) { + return null; + } + + let versionOutputCharacter; + const m_uni = /^U\+([0-9a-f]{1,6})$/i.exec(ctr); + const m_hex = /^&#x([0-9a-f]{1,6});$/i.exec(ctr); + const m_dec = /^&#([0-9]{1,7});$/.exec(ctr); + + // find the value of output character which may be specified in unicode, html hex or html dec format ( e.g. U+1234 -> 1234; ሴ -> 1234; ሴ -> 1234) + const c_val = ((m_uni || m_hex || m_dec) ? + m_uni ? parseInt(m_uni[1], 16) : m_hex ? parseInt(m_hex[1], 16) : parseInt(m_dec[1], 10) : KeylayoutToKmnConverter.MAX_CTRL_CHARACTER + ); + + // for control charactersin 'U+...', '&#x...' or '&#...' format as well as in "" format + if ((c_val < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER) || (ctr.charCodeAt(0) < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER)) { + + // for control characters in 'U+...', '&#x...' or '&#...' format + if (c_val < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER) { + versionOutputCharacter = "U+" + c_val.toString(16).toUpperCase().padStart(4, '0'); + } + + // for control characters in "" format + if (ctr.charCodeAt(0) < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER) { + versionOutputCharacter = "U+" + ctr.charCodeAt(0).toString(16).toUpperCase().padStart(4, '0'); + } + return versionOutputCharacter; + } + else + return ctr; } // TODO: move to util @@ -902,44 +990,95 @@ export class KmnFileWriter { */ public convertToUnicodeCharacter(inputString: string): string { - if ((inputString === null) || (inputString === undefined)) { + + // null, undefined will later be refused for conversion + if (inputString == null || inputString == undefined) { return undefined; } - // e.g. U+0061 U+1234 U+1F60E - else if (inputString.match(/^U\+([0-9a-f]{2,6})$/i)) { - return String.fromCodePoint(parseInt(inputString.match(/^U\+([0-9a-f]{2,6})$/i)[1], 16)); - } + // U+ followed by 1.-6. hex digits will later be used for conversion + const m_uni = /^U\+([0-9a-f]{1,6})$/i.exec(inputString); + + // invalid U+ ( U+ followed by anything) will later be refused for conversion + const m_uni_inv = /^(U\+)+(.?)+$/i.exec(inputString); + + // &#x followed by 1.-6. hex digits will later be used for conversion + const m_hex = /^&#x([0-9a-f]{1,6});$/i.exec(inputString); + + // &# followed by 1.-6. decimal digits will later be used for conversion + const m_dec = /^&#([0-9]{1,7});$/.exec(inputString); + + // & followed by gt, lt, quot, amp, apos will later be used for conversion + const m_nam = /^&(gt|lt|quot|amp|apos);$/i.exec(inputString); - // e.g. a ሴ 😎 - else if (inputString.match(/^&#x([0-9a-f]{2,6});$/i)) { - return String.fromCodePoint(parseInt(inputString.match(/^&#x([0-9a-f]{2,6});$/i)[1], 16)); + // &# followed by anything will later be refused for conversion + const m_html_inv = /^(&#)+(.?)+$/i.exec(inputString); + + // one or more characters except starting with U+ or & will later be used for conversion + const m_chr = /^(?!U\+|&).+$/i.exec(inputString); + + // '&', '&#','&#x', or 'U+' with or without ; will later be refused for conversion + const m_chr_inv = /^((&;?)+|(&#;?)+|(&#x;?)+|(U\+)+;?)$|^$/i.exec(inputString); + + // valid 'U+xxxx' + if (m_uni) { + const codePoint_u = parseInt(m_uni[1], 16); + // Reject surrogates and invalid codepoints + if ((codePoint_u >= 0xD800 && codePoint_u <= 0xDFFF) || codePoint_u > 0x10FFFF) { + return undefined; + } + return String.fromCodePoint(codePoint_u); } - // e.g. a ሴ 😆 - else if (inputString.match(/^&#([0-9a-f]{2,6});$/i)) { - return String.fromCodePoint(parseInt(inputString.match(/^&#([0-9a-f]{2,6});$/i)[1], 10)); + // invalid 'U+xxxx' + else if (m_uni_inv) { + return undefined; } - // e.g. > " - else if (inputString.match(/^&([a-z]{1,4});$/i)) { - if (inputString === '>') { return '>'; } - else if (inputString === '<') { return '<'; } - else if (inputString === '&') { return '&'; } - else if (inputString === ''') { return "'"; } - else if (inputString === '"') { return '"'; } - else return undefined; + // valid '&#x...' + else if (m_hex) { + const codePoint_h = parseInt(m_hex[1], 16); + // Reject surrogates and invalid codepoints + if ((codePoint_h >= 0xD800 && codePoint_h <= 0xDFFF) || codePoint_h > 0x10FFFF) { + return undefined; + } + return String.fromCodePoint(codePoint_h); + } + // valid '&#...' + else if (m_dec) { + const codePoint_d = parseInt(m_dec[1], 10); + // Reject surrogates and invalid codepoints + if ((codePoint_d >= 0xD800 && codePoint_d <= 0xDFFF) || codePoint_d > 0x10FFFF) { + return undefined; + } + return String.fromCodePoint(codePoint_d); + } + // valid '>', '<',.. + else if (m_nam) { + switch (m_nam[1].toLowerCase()) { + case 'gt': return '>'; + case 'lt': return '<'; + case 'quot': return '"'; + case 'amp': return '&'; + case 'apos': return "'"; + default: return undefined; + } + } + // invalid '&...' + else if (m_html_inv) { + return undefined; } - // 'A' or "B" have length=1 and segment-length=1 and will be used. - // "ẘ" or "😎" have length=2 but segment-length=1 and will be used. - // "ab" has length=2 and segment-length=2 and will not be used. - else if ([...new Intl.Segmenter().segment(inputString)].length <= 1) { + // single 'U+', '&', '' + else if (m_chr_inv) { return inputString; } - else { - return undefined; + + // if no matches so far, check for one or more characters ('a','ab', 'ẘ','😎', '😎😎', ) + else if (m_chr) { + return inputString; } + return undefined; } // TODO: move to util /** @@ -972,4 +1111,4 @@ export class KmnFileWriter { -} +} \ No newline at end of file diff --git a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts index 84893621f0e..1d2e90571bd 100644 --- a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts +++ b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts @@ -117,11 +117,11 @@ describe('KmnFileWriter', function () { ["a", 'a'], ["ሴ", 'ሴ'], ["😎", '😎'], - ["�", undefined], + ["�",undefined ], ["a", 'a'], ["ሴ", 'ሴ'], ["😆", '😆'], - ["󴉀", undefined], + ["󴉀", '󴉀'], ["U+0061", 'a'], ["U+1234", 'ሴ'], ["U+1F60E", '😎'], @@ -131,7 +131,7 @@ describe('KmnFileWriter', function () { ["ሴ", 'ሴ'], ['😎', '😎'], ["W̊", "W̊"], - ["ab", undefined], + ["ab", 'ab'], ["", ''], [undefined, undefined], [null, undefined] From 435a0f4269499e9cd472bbb04283bbfe295de299 Mon Sep 17 00:00:00 2001 From: Sabine Date: Wed, 8 Apr 2026 20:37:31 +0200 Subject: [PATCH 226/251] feat(developer): move finding of control characters to function writeCharacterOrUnicode() --- .../src/keylayout-to-kmn/kmn-file-writer.ts | 171 +++++------------- .../data/Test_differentEncodings.keylayout | 37 ++++ .../test/keylayout-to-kmn-converter.tests.ts | 1 + 3 files changed, 85 insertions(+), 124 deletions(-) create mode 100644 developer/src/kmc-convert/test/data/Test_differentEncodings.keylayout diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts index 17c0c73391b..0aff11bbe92 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts @@ -12,6 +12,11 @@ import { KeylayoutToKmnConverter, ProcessedData, Rule } from './keylayout-to-kmn import { ConverterMessages } from '../converter-messages.js'; import KEYMAN_VERSION from "@keymanapp/keyman-version"; +export interface messageCharacter { + message: string; + character: string; +}; + export class KmnFileWriter { constructor(private callbacks: CompilerCallbacks, private options: CompilerOptions) { }; @@ -129,8 +134,6 @@ export class KmnFileWriter { continue; } - //--------------------------------------------------------------------------------------------- - // add a line after rules of each key if ((k > 1) && (uniqueDataRules[k - 1].key !== uniqueDataRules[k].key) && (uniqueDataRules[k - 1].ruleType === uniqueDataRules[k].ruleType)) { data += '\n'; @@ -147,40 +150,11 @@ export class KmnFileWriter { // const outputUnicodeCodePoint = util.convertToUnicodeCodePoint(outputCharacter); if ((outputCharacter !== undefined) || (outputCharacter !== "")) { - - const m_uni = /^U\+([0-9a-f]{1,6})$/i.exec(outputCharacter); - const m_hex = /^&#x([0-9a-f]{1,6});$/i.exec(outputCharacter); - const m_dec = /^&#([0-9]{1,7});$/.exec(outputCharacter); - - // find the value of output character which may be specified in unicode, html hex or html dec format ( e.g. U+1234 -> 1234; ሴ -> 1234; ሴ -> 1234) - const c_val = ((m_uni || m_hex || m_dec) ? - m_uni ? parseInt(m_uni[1], 16) : m_hex ? parseInt(m_hex[1], 16) : parseInt(m_dec[1], 10) : KeylayoutToKmnConverter.MAX_CTRL_CHARACTER - ); - - // for control charactersin 'U+...', '&#x...' or '&#...' format as well as in "" format - if ((c_val < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER) || (outputCharacter.charCodeAt(0) < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER)) { - - // for control characters in 'U+...', '&#x...' or '&#...' format - if (c_val < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER) { - versionOutputCharacter = "U+" + c_val.toString(16).toUpperCase().padStart(4, '0'); - } - - // for control characters in "" format - if (outputCharacter.charCodeAt(0) < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER) { - versionOutputCharacter = "U+" + outputCharacter.charCodeAt(0).toString(16).toUpperCase().padStart(4, '0'); - } - - if (warnText[2] == "") { - warnText[2] = warnText[2] + "c WARNING: use of a control character "; - } - else { - warnText[2] = warnText[2] + " Use of a control character "; - } - } - else { - versionOutputCharacter = this.convertToUnicodeCharacter(outputCharacter);; - } + const characterMessage = this.writeCharacterOrUnicode(outputCharacter, warnText[2]); + versionOutputCharacter = characterMessage.character; + warnText[2] = characterMessage.message; } + // add a warning in front of rules in case unavailable modifiers or ambiguous rules are used // if warning contains duplicate rules we do not write out the entire rule // (even if there are other warnings for the same rule) since that rule had been written before @@ -229,45 +203,11 @@ export class KmnFileWriter { // const outputUnicodeCodePoint = util.convertToUnicodeCodePoint(outputCharacter); if ((outputCharacter !== undefined) || (outputCharacter !== "")) { - - const m_uni = /^U\+([0-9a-f]{1,6})$/i.exec(outputCharacter); - const m_hex = /^&#x([0-9a-f]{1,6});$/i.exec(outputCharacter); - const m_dec = /^&#([0-9]{1,7});$/.exec(outputCharacter); - - // find the value of output character which may be specified in unicode, html hex or html dec format ( e.g. U+1234 -> 1234; ሴ -> 1234; ሴ -> 1234) - const c_val = ((m_uni || m_hex || m_dec) ? - m_uni ? parseInt(m_uni[1], 16) : m_hex ? parseInt(m_hex[1], 16) : parseInt(m_dec[1], 10) : KeylayoutToKmnConverter.MAX_CTRL_CHARACTER - ); - - // for control charactersin 'U+...', '&#x...' or '&#...' format as well as in "" format - if ((c_val < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER) || (outputCharacter.charCodeAt(0) < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER)) { - - // for control characters in 'U+...', '&#x...' or '&#...' format - if (c_val < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER) { - versionOutputCharacter = "U+" + c_val.toString(16).toUpperCase().padStart(4, '0'); - } - - // for control characters in "" format - if (outputCharacter.charCodeAt(0) < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER) { - versionOutputCharacter = "U+" + outputCharacter.charCodeAt(0).toString(16).toUpperCase().padStart(4, '0'); - } - - if (warnText[2] == "") { - warnText[2] = warnText[2] + "c WARNING: use of a control character "; - } - else { - warnText[2] = warnText[2] + "; Use of a control character "; - } - } - else { - versionOutputCharacter = this.convertToUnicodeCharacter(outputCharacter);; - } + const characterMessage = this.writeCharacterOrUnicode(outputCharacter, warnText[2]); + versionOutputCharacter = characterMessage.character; + warnText[2] = characterMessage.message; } - - - - // add a warning in front of rules in case unavailable modifiers or ambiguous rules are used // if warning contains duplicate rules we do not write out the entire rule // (even if there are other warnings for the same rule) since that rule had been written before @@ -337,39 +277,9 @@ export class KmnFileWriter { // TODO-kmc-convert: after merge of PR 14564 use functions from util instead of the ones in this class if ((outputCharacter !== undefined) || (outputCharacter !== "")) { - - const m_uni = /^U\+([0-9a-f]{1,6})$/i.exec(outputCharacter); - const m_hex = /^&#x([0-9a-f]{1,6});$/i.exec(outputCharacter); - const m_dec = /^&#([0-9]{1,7});$/.exec(outputCharacter); - - // find the value of output character which may be specified in unicode, html hex or html dec format ( e.g. U+1234 -> 1234; ሴ -> 1234; ሴ -> 1234) - const c_val = ((m_uni || m_hex || m_dec) ? - m_uni ? parseInt(m_uni[1], 16) : m_hex ? parseInt(m_hex[1], 16) : parseInt(m_dec[1], 10) : KeylayoutToKmnConverter.MAX_CTRL_CHARACTER - ); - - // for control charactersin 'U+...', '&#x...' or '&#...' format as well as in "" format - if ((c_val < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER) || (outputCharacter.charCodeAt(0) < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER)) { - - // for control characters in 'U+...', '&#x...' or '&#...' format - if (c_val < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER) { - versionOutputCharacter = "U+" + c_val.toString(16).toUpperCase().padStart(4, '0'); - } - - // for control characters in "" format - if (outputCharacter.charCodeAt(0) < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER) { - versionOutputCharacter = "U+" + outputCharacter.charCodeAt(0).toString(16).toUpperCase().padStart(4, '0'); - } - - if (warnText[2] == "") { - warnText[2] = warnText[2] + "c WARNING: use of a control character "; - } - else { - warnText[2] = warnText[2] + "; Use of a control character "; - } - } - else { - versionOutputCharacter = this.convertToUnicodeCharacter(outputCharacter);; - } + const characterMessage = this.writeCharacterOrUnicode(outputCharacter, warnText[2]); + versionOutputCharacter = characterMessage.character; + warnText[2] = characterMessage.message; } // add a warning in front of rules in case unavailable modifiers or ambiguous rules are used @@ -576,7 +486,7 @@ export class KmnFileWriter { + " " + amb_1_1[0].key + "] > \'" - + this.writeCharacterOrUnicode(new TextDecoder().decode(amb_1_1[0].output)) + + this.writeCharacterOrUnicode(new TextDecoder().decode(amb_1_1[0].output)).character + "\' "); } @@ -587,7 +497,7 @@ export class KmnFileWriter { + " " + dup_1_1[0].key + "] > \'" - + this.writeCharacterOrUnicode(new TextDecoder().decode(dup_1_1[0].output)) + + this.writeCharacterOrUnicode(new TextDecoder().decode(dup_1_1[0].output)).character + "\' "); } } @@ -672,8 +582,7 @@ export class KmnFileWriter { + " " + amb_3_3[0].key + "] > \'" - /*+ new TextDecoder().decode(amb_3_3[0].output)*/ - + this.writeCharacterOrUnicode(new TextDecoder().decode(amb_3_3[0].output)) + + this.writeCharacterOrUnicode(new TextDecoder().decode(amb_3_3[0].output)).character + "\' "); } @@ -686,8 +595,7 @@ export class KmnFileWriter { + " " + dup_3_3[0].key + "] > \'" - /* + new TextDecoder().decode(dup_3_3[0].output)*/ - + this.writeCharacterOrUnicode(new TextDecoder().decode(dup_3_3[0].output)) + + this.writeCharacterOrUnicode(new TextDecoder().decode(dup_3_3[0].output)).character + "\' "); } @@ -815,7 +723,7 @@ export class KmnFileWriter { + " " + amb_6_3[0].key + "] > \'" - + this.writeCharacterOrUnicode(new TextDecoder().decode(amb_6_3[0].output)) + + this.writeCharacterOrUnicode(new TextDecoder().decode(amb_6_3[0].output)).character + "\' "); } @@ -828,7 +736,7 @@ export class KmnFileWriter { + " " + dup_6_3[0].key + "] > \'" - + this.writeCharacterOrUnicode(new TextDecoder().decode(dup_6_3[0].output)) + + this.writeCharacterOrUnicode(new TextDecoder().decode(dup_6_3[0].output)).character + "\' "); } @@ -889,7 +797,7 @@ export class KmnFileWriter { + " " + amb_6_6[0].key + "] > \'" - + this.writeCharacterOrUnicode(new TextDecoder().decode(amb_6_6[0].output)) + + this.writeCharacterOrUnicode(new TextDecoder().decode(amb_6_6[0].output)).character + "\' "); } @@ -902,7 +810,7 @@ export class KmnFileWriter { + " " + dup_6_6[0].key + "] > \'" - + this.writeCharacterOrUnicode(new TextDecoder().decode(dup_6_6[0].output)) + + this.writeCharacterOrUnicode(new TextDecoder().decode(dup_6_6[0].output)).character + "\' "); } } @@ -948,38 +856,53 @@ export class KmnFileWriter { * a non-control character will be written as itself ( 'A', '1', '፩', '😎') * null in case of an empty string or null or undefined input */ - public writeCharacterOrUnicode(ctr: string): string | null { + public writeCharacterOrUnicode(ctr: string, msg: string = ""): messageCharacter { if ((ctr === null) || (ctr === undefined) || (ctr.length === 0)) { return null; } let versionOutputCharacter; + const out: messageCharacter = { + message: msg, + character: ctr + }; + const m_uni = /^U\+([0-9a-f]{1,6})$/i.exec(ctr); const m_hex = /^&#x([0-9a-f]{1,6});$/i.exec(ctr); const m_dec = /^&#([0-9]{1,7});$/.exec(ctr); // find the value of output character which may be specified in unicode, html hex or html dec format ( e.g. U+1234 -> 1234; ሴ -> 1234; ሴ -> 1234) - const c_val = ((m_uni || m_hex || m_dec) ? + const ctr_val = ((m_uni || m_hex || m_dec) ? m_uni ? parseInt(m_uni[1], 16) : m_hex ? parseInt(m_hex[1], 16) : parseInt(m_dec[1], 10) : KeylayoutToKmnConverter.MAX_CTRL_CHARACTER ); // for control charactersin 'U+...', '&#x...' or '&#...' format as well as in "" format - if ((c_val < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER) || (ctr.charCodeAt(0) < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER)) { + if ((ctr_val < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER) || (ctr.charCodeAt(0) < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER)) { // for control characters in 'U+...', '&#x...' or '&#...' format - if (c_val < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER) { - versionOutputCharacter = "U+" + c_val.toString(16).toUpperCase().padStart(4, '0'); + if (ctr_val < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER) { + versionOutputCharacter = "U+" + ctr_val.toString(16).toUpperCase().padStart(4, '0'); } - // for control characters in "" format if (ctr.charCodeAt(0) < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER) { versionOutputCharacter = "U+" + ctr.charCodeAt(0).toString(16).toUpperCase().padStart(4, '0'); } - return versionOutputCharacter; + if (versionOutputCharacter) + out.character = versionOutputCharacter; + + // add a warning message + if (msg == "") { + out.message = "c WARNING: use of a control character "; + } + else { + out.message = msg + "; Use of a control character "; + } } - else - return ctr; + else { + out.character = this.convertToUnicodeCharacter(ctr);; + } + return out; } // TODO: move to util diff --git a/developer/src/kmc-convert/test/data/Test_differentEncodings.keylayout b/developer/src/kmc-convert/test/data/Test_differentEncodings.keylayout new file mode 100644 index 00000000000..c526f8c2af8 --- /dev/null +++ b/developer/src/kmc-convert/test/data/Test_differentEncodings.keylayout @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index d6793ce3618..966ecf9ec48 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -81,6 +81,7 @@ describe('KeylayoutToKmnConverter', function () { [makePathToFixture('../data/Test_ambiguous_keys.keylayout')], [makePathToFixture('../data/Test_nr_elements.keylayout')], [makePathToFixture('../data/Test.keylayout')], + [makePathToFixture('../data/Test_differentEncodings.keylayout')], ].forEach(function (files) { it(files + " should give no errors ", async function () { sut.run(files[0]); From 2b5782d1778efab598eaf0fd66aa4a5fc6a8d47e Mon Sep 17 00:00:00 2001 From: Sabine Date: Thu, 9 Apr 2026 13:52:22 +0200 Subject: [PATCH 227/251] feat(developer): tidy up and new test for ExtraWarning --- .../src/common/web/utils/src/xml-utils.ts | 8 -- .../src/keylayout-to-kmn/kmn-file-writer.ts | 35 +-------- .../test/data/Test_ExtraWarning.keylayout | 76 +++++++++++++++++++ .../test/keylayout-to-kmn-converter.tests.ts | 1 + 4 files changed, 79 insertions(+), 41 deletions(-) create mode 100644 developer/src/kmc-convert/test/data/Test_ExtraWarning.keylayout diff --git a/developer/src/common/web/utils/src/xml-utils.ts b/developer/src/common/web/utils/src/xml-utils.ts index 9f1e48bc9d9..b00ab4c0aca 100644 --- a/developer/src/common/web/utils/src/xml-utils.ts +++ b/developer/src/common/web/utils/src/xml-utils.ts @@ -66,14 +66,6 @@ const PARSER_OPTIONS: KeymanXMLParserOptionsBag = { preserveOrder: true, // Gives us a 'special' format }, 'keylayout': { - /* - //my options copied from fast-xml-parser - ignoreAttributes: [''], // we do not process an output character of "" - trimValues: false, // we do not trim values because if we do we cannot process an output character of " " (space) - parseTagValue: false, - attributeNamePrefix: '@__', // to access the attribute - ignoreDeclaration: true -*/ attributeNamePrefix: '@__', htmlEntities: true, ignoreAttributes: false, // use attributes diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts index 0aff11bbe92..5f850735d71 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts @@ -905,7 +905,7 @@ export class KmnFileWriter { return out; } - // TODO: move to util + // TODO: move to util in PR 14569 /** * @brief function to convert a numeric character reference or a unicode value to a unicode character e.g. c -> c; U+1F60E -> 😎 * @param inputString the value that will converted @@ -1003,35 +1003,4 @@ export class KmnFileWriter { } return undefined; } - // TODO: move to util - /** - * @brief function to convert a numeric character reference to a unicode Code Point e.g. ሴ -> U+1234; 􏘁 -> U+1F60E - * @param instr the value that will converted - * @return returns a unicode Code Point like U+0063, U+1234, U+1F60E; returns the input character if a non-numeric reference is used or returns 'undefined' if instr is not recognized - */ - public convertToUnicodeCodePoint(instr: string): string { - - if ((instr === null) || (instr === undefined)) { - return undefined; - } - - if (instr.substring(0, 3) === "&#x") { - const numLength = instr.length - instr.indexOf("x") - 1; - const numStr = instr.substring(instr.indexOf("x") + 1, instr.length - 1); - return ("U+" + numStr.slice(-numLength).padStart(4, "0")); - } - - // if not hex: convert to hex - if ((instr.substring(0, 2) === "&#")) { - const numLength = instr.length - instr.indexOf("#") - 1; - const numStr = instr.substring(instr.indexOf("#") + 1, instr.length - 1); - return "U+" + Number(numStr.slice(-numLength)).toString(16).slice(-6).toUpperCase().padStart(4, "0"); - } - else - return instr; - } - - - - -} \ No newline at end of file +} diff --git a/developer/src/kmc-convert/test/data/Test_ExtraWarning.keylayout b/developer/src/kmc-convert/test/data/Test_ExtraWarning.keylayout new file mode 100644 index 00000000000..0d36b2a5fea --- /dev/null +++ b/developer/src/kmc-convert/test/data/Test_ExtraWarning.keylayout @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index 966ecf9ec48..c370acf3fc2 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -82,6 +82,7 @@ describe('KeylayoutToKmnConverter', function () { [makePathToFixture('../data/Test_nr_elements.keylayout')], [makePathToFixture('../data/Test.keylayout')], [makePathToFixture('../data/Test_differentEncodings.keylayout')], + [makePathToFixture('../data/Test_ExtraWarning.keylayout')], ].forEach(function (files) { it(files + " should give no errors ", async function () { sut.run(files[0]); From cc31feb32b34ee66032327587432e5d9983a7ab9 Mon Sep 17 00:00:00 2001 From: Sabine Date: Thu, 9 Apr 2026 14:08:49 +0200 Subject: [PATCH 228/251] feat(developer): remove tests for convertToUnicodeCodePoint --- .../kmc-convert/test/kmn-file-writer.tests.ts | 30 ------------------- 1 file changed, 30 deletions(-) diff --git a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts index 1d2e90571bd..16a5cb66126 100644 --- a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts +++ b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts @@ -81,36 +81,6 @@ describe('KmnFileWriter', function () { }); }); - describe('convertToUnicodeCodePoint ', function () { - const sutW = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); - [ - ["􏘁", 'U+10F601'], - ["😁", 'U+1F601'], - [" ", 'U+0009'], - ["™", 'U+0099'], - ["ঙ", 'U+0999'], - ["香", 'U+9999'], - ["򙦙", 'U+99999'], - ["􏘁", 'U+10F601'], - ["😁", 'U+1F601'], - [" ", 'U+0009'], - ["c", 'U+0063'], - ["ϧ", 'U+03E7'], - ["✏", 'U+270F'], - ["𘚟", 'U+1869F'], - ['0000;', '0000;'], - ['X;', 'X;'], - ['123;', '123;'], - [';', ';'], - [' ;', ' ;'] - ].forEach(function (values) { - it(('should convert "' + values[0] + '"').padEnd(25, " ") + 'to "' + values[1] + '"', async function () { - const result = sutW.convertToUnicodeCodePoint(values[0] as string); - assert.equal(result, values[1]); - }); - }); - }); - describe('convertToUnicodeCharacter ', function () { const sutW = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); [ From fa19344866e4b7135e5b8bd2b4034d7356ba933e Mon Sep 17 00:00:00 2001 From: Sabine Date: Thu, 9 Apr 2026 16:21:11 +0200 Subject: [PATCH 229/251] feat(developer): some tidy up in tests --- .../data/Test_unsupportedCharacters.keylayout | 2 +- .../test/keylayout-to-kmn-converter.tests.ts | 156 +++++++++--------- .../kmc-convert/test/kmn-file-reader.tests.ts | 44 +---- .../kmc-convert/test/kmn-file-writer.tests.ts | 22 +-- 4 files changed, 83 insertions(+), 141 deletions(-) diff --git a/developer/src/kmc-convert/test/data/Test_unsupportedCharacters.keylayout b/developer/src/kmc-convert/test/data/Test_unsupportedCharacters.keylayout index e2551263ef3..d393b332ee6 100644 --- a/developer/src/kmc-convert/test/data/Test_unsupportedCharacters.keylayout +++ b/developer/src/kmc-convert/test/data/Test_unsupportedCharacters.keylayout @@ -23,7 +23,7 @@ - + diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index c370acf3fc2..34f0f99e6a7 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -20,42 +20,28 @@ describe('KeylayoutToKmnConverter', function () { compilerTestCallbacks.clear(); }); - describe('Run kmc-convert with or without outputfile name', async function () { - - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const infile = '../data/Test.keylayout'; - [ - [makePathToFixture('../data/Test.kmn')], - [], - [makePathToFixture('../data/test_OtherOutputName.kmn')], - ].forEach(function (files) { - it(infile + " should run " , async function () { - await NodeAssert.doesNotReject(async () => sut.run(makePathToFixture(infile), files[0])); - assert.equal(compilerTestCallbacks.messages.length, 0); - }); - }); - }); - - describe('RunTestFiles resulting in errors ', function () { + /*describe('RunFILES', function () { + this.timeout(10000); // allow longer time for these tests const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); [ - [makePathToFixture('../data/Test_DifferentAmountOfMapSelectInKeyMapERROR.keylayout')], - [makePathToFixture('../data/Test_MissingkeyERROR.keylayout')], - [makePathToFixture('../data/Test_MissingkeyMapERROR.keylayout')], - [makePathToFixture('../data/Test_MissingLayoutsERROR.keylayout')], - [makePathToFixture('../data/Test_MissingmodifierMapERROR.keylayout')], - [makePathToFixture('../data/Test_MissingkeyMapSetERROR.keylayout')], - [makePathToFixture('../data/Test_MissingActionsERROR.keylayout')], - [makePathToFixture('../data/Test_MissingTerminatorsERROR.keylayout')], - [makePathToFixture('../data/Test_MissingAllERROR.keylayout')], - [makePathToFixture('../data/Test_characters.keylayout')], + [makePathToFixture('../data/Polish.keylayout')], + [makePathToFixture('../data/Spanish.keylayout')], + [makePathToFixture('../data/French.keylayout')], + [makePathToFixture('../data/German_complete_reduced.keylayout')], + // [makePathToFixture('../data/German_complete.keylayout')], + // [makePathToFixture('../data/German_standard.keylayout')], + [makePathToFixture('../data/Italian_command.keylayout')], + [makePathToFixture('../data/Italian.keylayout')], + [makePathToFixture('../data/Latin_American.keylayout')], + [makePathToFixture('../data/Swiss_French.keylayout')], + [makePathToFixture('../data/Swiss_German.keylayout')], ].forEach(function (files) { - it(files + " should give an error ", async function () { + it(files + " should give no errors ", async function () { sut.run(files[0]); - assert.isTrue(compilerTestCallbacks.messages.length > 0); + assert.isTrue(compilerTestCallbacks.messages.length === 0); }); }); - }); + });*/ describe('RunSpecialTestFiles', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); @@ -91,12 +77,31 @@ describe('KeylayoutToKmnConverter', function () { }); }); + describe('RunTestFiles resulting in errors ', function () { + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + [ + [makePathToFixture('../data/Test_DifferentAmountOfMapSelectInKeyMapERROR.keylayout')], + [makePathToFixture('../data/Test_MissingkeyERROR.keylayout')], + [makePathToFixture('../data/Test_MissingkeyMapERROR.keylayout')], + [makePathToFixture('../data/Test_MissingLayoutsERROR.keylayout')], + [makePathToFixture('../data/Test_MissingmodifierMapERROR.keylayout')], + [makePathToFixture('../data/Test_MissingkeyMapSetERROR.keylayout')], + [makePathToFixture('../data/Test_MissingActionsERROR.keylayout')], + [makePathToFixture('../data/Test_MissingTerminatorsERROR.keylayout')], + [makePathToFixture('../data/Test_MissingAllERROR.keylayout')], + ].forEach(function (files) { + it(files + " should give an error ", async function () { + sut.run(files[0]); + assert.isTrue(compilerTestCallbacks.messages.length > 0); + }); + }); + }); + describe('RunSpecialTestFiles - create Error: unsupported characters', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); [ [makePathToFixture('../data/Test_characters.keylayout')], - [makePathToFixture('../data/Test_onlyOneKeymap.keylayout')], - [makePathToFixture('../data/Test_unsupportedCharacters.keylayout')], + [makePathToFixture('../data/Test_EmptyOutputCharacter.keylayout')], ].forEach(function (files) { it(files + " should give Error: unsupported characters ", async function () { sut.run(files[0]); @@ -105,7 +110,7 @@ describe('KeylayoutToKmnConverter', function () { }); }); - describe('RunSpecialTestFiles - undefined action', function () { + describe('RunSpecialTestFiles - create Error: undefined action', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); [ [makePathToFixture('../data/Test_undefinedAction.keylayout')], @@ -148,43 +153,27 @@ describe('KeylayoutToKmnConverter', function () { const result = sut.run(inputFilename, null); assert.isNotNull(result); assert.equal(compilerTestCallbacks.messages.length, 2); - assert.deepEqual(compilerTestCallbacks.messages[0], ConverterMessages.Error_UnableToRead());// ok + assert.deepEqual(compilerTestCallbacks.messages[0], ConverterMessages.Error_UnableToRead()); assert.equal(compilerTestCallbacks.messages[1].code, 5292037); }); + }); - it('run() should return on available input file name and null output file name', async function () { - this.timeout(5000); // allow longer time for this test - const inputFilename = makePathToFixture('../data/Test.keylayout'); - const result = sut.run(inputFilename, null); - assert.isNotNull(result); - await NodeAssert.doesNotReject(async () => sut.run(inputFilename, null)); - assert.equal(compilerTestCallbacks.messages.length, 0); - }); - - it('run() should return on correct input file name and empty output file name ', async function () { - const inputFilename = makePathToFixture('../data/Test.keylayout'); - await NodeAssert.doesNotReject(async () => sut.run(inputFilename, '')); - assert.equal(compilerTestCallbacks.messages.length, 0); - }); - - it('run() should return on correct input file name and null output file name', async function () { - const inputFilename = makePathToFixture('../data/Test.keylayout'); - await NodeAssert.doesNotReject(async () => sut.run(inputFilename, null)); - assert.equal(compilerTestCallbacks.messages.length, 0); - }); - - it('run() should return on correct input file name and given output file name ', async function () { - const inputFilename = makePathToFixture('../data/Test.keylayout'); - const outputFilename = makePathToFixture('../data/OutputName.kmn'); - await NodeAssert.doesNotReject(async () => sut.run(inputFilename, outputFilename)); - assert.equal(compilerTestCallbacks.messages.length, 0); - }); - - it('run() return on correct input file extention and unsupperted output file extention', async function () { - const inputFilename = makePathToFixture('../data/Test.keylayout'); - const outputFilename = makePathToFixture('../data/OutputXName.B'); - await NodeAssert.doesNotReject(async () => sut.run(inputFilename, outputFilename)); - assert.equal(compilerTestCallbacks.messages.length, 0); + describe('Run kmc-convert with or without outputfile name', async function () { + this.timeout(5000); // allow longer time for this test + const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const infile = '../data/Test.keylayout'; + [ + [makePathToFixture('../data/Test.kmn')], + [makePathToFixture('')], + [], + [null], + [makePathToFixture('../data/test_OtherOutputName.kmn')], + [makePathToFixture('../data/OutputXName.bb')], + ].forEach(function (files) { + it(infile + " should run ", async function () { + await NodeAssert.doesNotReject(async () => sut.run(makePathToFixture(infile), files[0])); + assert.equal(compilerTestCallbacks.messages.length, 0); + }); }); }); @@ -211,14 +200,14 @@ describe('KeylayoutToKmnConverter', function () { assert.isTrue(converted.rules.length !== 0); }); - it('should return empty on empty input', async function () { - assert.isNull(convertedEmpty); - }); - it('should return empty on empty name as input', async function () { assert.isNull(convertedUnavailable); }); + it('should return empty on empty input', async function () { + assert.isNull(convertedEmpty); + }); + it('should return empty on only modifiers as input', async function () { const convertedMod = sut.convertBound.convert({ keylayoutFilename: '', @@ -240,7 +229,6 @@ describe('KeylayoutToKmnConverter', function () { it('should return empty array of rules on null input', async function () { const convertedRule = sut.convertBound.convert(null, 'ABC.kmn'); assert.isNull(convertedRule); - }); }); @@ -248,10 +236,15 @@ describe('KeylayoutToKmnConverter', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); [ [' ', true, 'NCAPS'], + [' ', false, ''], + ['NCAPS', true, 'NCAPS'], ['NCAPS', false, ''], + ['caps', true, 'CAPS'], ['CAPS', true, 'CAPS'], ['CAPS?', true, 'NCAPS'], + ['CAPS', false, 'CAPS'], + ['CAPS?', false, ''], ['CAPS? NCAPS', true, 'NCAPS'], ['CAPS NCAPS', true, 'CAPS NCAPS'], ['caps ncaps', true, 'CAPS NCAPS'], @@ -259,6 +252,9 @@ describe('KeylayoutToKmnConverter', function () { ['shift', true, 'NCAPS SHIFT'], ['leftshift', true, 'NCAPS SHIFT'], ['rightShift', true, 'NCAPS SHIFT'], + ['shift', false, 'SHIFT'], + ['leftshift', false, 'SHIFT'], + ['rightShift', false, 'SHIFT'], ['shift rightShift?', true, 'NCAPS SHIFT'], ['rightShift?', true, 'NCAPS'], ['shift Shift?', true, 'NCAPS SHIFT'], @@ -268,7 +264,6 @@ describe('KeylayoutToKmnConverter', function () { ['shift?', true, 'NCAPS'], ['?', true, 'NCAPS'], ['?', false, ''], - ['caps', true, 'CAPS'], ['', true, 'NCAPS'], [' ', false, ''], ['wrongModifierName', false, 'wrongModifierName'], @@ -294,7 +289,6 @@ describe('KeylayoutToKmnConverter', function () { describe('isAcceptableKeymanModifier ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - [ ['NCAPS', true], ['NxCAPS', false], @@ -346,6 +340,7 @@ describe('KeylayoutToKmnConverter', function () { [[['Caps', 'xxx'], ['yyy']], true], [[['CaPs', 'xxx'], ['yyy']], true], [[['Caps?', 'xxx'], ['yyy']], false], + [[['zzz', 'xxx'], ['Caps?']], false], [[['caps?', 'xxx'], ['yyy']], false], [[['zzz', 'xxx'], ['yyy']], false], [[['shift', 'xxx'], ['caps']], true], @@ -420,7 +415,6 @@ describe('KeylayoutToKmnConverter', function () { const sutR = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Test.keylayout'); const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); - [ ['none', ''], ['0', ''], @@ -441,12 +435,12 @@ describe('KeylayoutToKmnConverter', function () { }); }); }); + describe('getActionIndexFromActionId ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sutR = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Test.keylayout'); const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); - [ ['none', -1], ['A_16', 8], @@ -465,12 +459,12 @@ describe('KeylayoutToKmnConverter', function () { }); }); }); + describe('getOutputFromActionIdNone ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sutR = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Test.keylayout'); const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); - [ ['A_14', 'u'], ['', ''], @@ -495,6 +489,7 @@ describe('KeylayoutToKmnConverter', function () { }); }); }); + describe('getKeybehaviorModOutputArrayFromKeyActionbehaviorOutputArray ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sutR = new KeylayoutFileReader(compilerTestCallbacks); @@ -602,12 +597,12 @@ describe('KeylayoutToKmnConverter', function () { }); }); }); + describe('getActionStateOutputArrayFromActionState ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sutR = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Test.keylayout'); const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); - [['1', [ { "id": "A_0", "state": "1", "output": "ˆ" }, { "id": "A_1", "state": "1", "output": "Â" }, @@ -649,13 +644,13 @@ describe('KeylayoutToKmnConverter', function () { }); }); }); + describe('getActionOutputbehaviorKeyModiFromActionIDStateOutput ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sutR = new KeylayoutFileReader(compilerTestCallbacks); const inputFilename = makePathToFixture('../data/Test.keylayout'); const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); const converted = sut.convertBound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); - [ ['A_1', 'A', true, [{ "outchar": "A", "actionId": "A_1", "behavior": "1", "key": "K_A", "modifier": "CAPS" }, @@ -675,7 +670,6 @@ describe('KeylayoutToKmnConverter', function () { ['', 'a', true, []], ['', 'a', false, []], ['', '', , []], - ].forEach(function (values) { it((JSON.stringify(values[3]).length > 35) ? ("getActionOutputbehaviorKeyModiFromActionIDStateOutput('" + values[0] + "', '" + values[1] + "', " + values[2] + ")").padEnd(67, " ") + ' should return an array of objects' : @@ -685,6 +679,7 @@ describe('KeylayoutToKmnConverter', function () { }); }); }); + describe('getKeyActionOutputArrayFromActionStateOutputArray ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sutR = new KeylayoutFileReader(compilerTestCallbacks); @@ -793,7 +788,6 @@ describe('KeylayoutToKmnConverter', function () { describe('createRuleData ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sutR = new KeylayoutFileReader(compilerTestCallbacks); - [ [ ['../data/Test_C0.keylayout'], diff --git a/developer/src/kmc-convert/test/kmn-file-reader.tests.ts b/developer/src/kmc-convert/test/kmn-file-reader.tests.ts index 3b99b6400d4..c68e0e52415 100644 --- a/developer/src/kmc-convert/test/kmn-file-reader.tests.ts +++ b/developer/src/kmc-convert/test/kmn-file-reader.tests.ts @@ -9,7 +9,6 @@ import 'mocha'; import { assert } from 'chai'; -import { Keylayout } from "@keymanapp/developer-utils"; import { compilerTestCallbacks, makePathToFixture } from './helpers/index.js'; import { KeylayoutFileReader } from '../src/keylayout-to-kmn/keylayout-file-reader.js'; @@ -19,49 +18,7 @@ describe('KeylayoutFileReader', function () { compilerTestCallbacks.clear(); }); - describe("validate() ", function () { - - it('validate() should return true on correct inputfile', async function () { - const sutR = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); - const result: Keylayout.KeylayoutXMLSourceFile = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); - const validated = sutR.validate(result); - assert.isTrue(validated); - }); - - it('validate() should return false on inputfile with unknown tags', async function () { - const sutR = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test_unknownTags.keylayout'); - const result: Keylayout.KeylayoutXMLSourceFile = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); - const validated = sutR.validate(result); - assert.isFalse(validated); - }); - - it('validate() should return false on inputfile with additional tags', async function () { - const sutR = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test_additionalTags.keylayout'); - const result: Keylayout.KeylayoutXMLSourceFile = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); - const validated = sutR.validate(result); - assert.isFalse(validated); - }); - it('validate() should return false on inputfile with missing tags', async function () { - const sutR = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test_missingTags.keylayout'); - const result: Keylayout.KeylayoutXMLSourceFile = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); - const validated = sutR.validate(result); - assert.isFalse(validated); - }); - it('validate() should return false on no entries in action-when', async function () { - const sutR = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test_noActionWhen.keylayout'); - const result: Keylayout.KeylayoutXMLSourceFile = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); - const validated = sutR.validate(result); - assert.isFalse(validated); - }); - }); - describe("read() ", function () { - const sutR = new KeylayoutFileReader(compilerTestCallbacks); it('read() should return filled array on correct input', async function () { @@ -91,4 +48,5 @@ describe('KeylayoutFileReader', function () { assert.isNull(result); }); }); + }); diff --git a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts index 16a5cb66126..0eb23c88b46 100644 --- a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts +++ b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts @@ -21,20 +21,6 @@ describe('KmnFileWriter', function () { compilerTestCallbacks.clear(); }); - describe("write() ", function () { - const inputFilename = makePathToFixture('../data/Test.keylayout'); - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const sutR = new KeylayoutFileReader(compilerTestCallbacks); - const sutW = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); - const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); - const converted = sut.convertBound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); - - it('write() should return result', async function () { - const result = sutW.write(converted); - assert.isNotNull(result); - }); - }); - describe("writeDataRules() ", function () { const inputFilename = makePathToFixture('../data/Test.keylayout'); const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); @@ -87,14 +73,17 @@ describe('KmnFileWriter', function () { ["a", 'a'], ["ሴ", 'ሴ'], ["😎", '😎'], + ["", '\u0002'], ["�",undefined ], ["a", 'a'], ["ሴ", 'ሴ'], ["😆", '😆'], + ["", '\u0003'], ["󴉀", '󴉀'], ["U+0061", 'a'], ["U+1234", 'ሴ'], ["U+1F60E", '😎'], + ["U+0001", '\u0001'], ["U+1000000;", undefined], ["@", undefined], ["a", 'a'], @@ -103,6 +92,9 @@ describe('KmnFileWriter', function () { ["W̊", "W̊"], ["ab", 'ab'], ["", ''], + ["␤", '␤'], + ["␕", '␕'], + ["", ''], [undefined, undefined], [null, undefined] ].forEach(function (values) { @@ -115,7 +107,6 @@ describe('KmnFileWriter', function () { describe('reviewRules messages', function () { const sutW = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); - [ [[new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'UNAVAILABLE', 'K_A', new TextEncoder().encode('A'))], [''], @@ -168,7 +159,6 @@ describe('KmnFileWriter', function () { }); describe('reviewRules messages duplicate and ambiguous', function () { - const sutW = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); [ //all From e85e965a5e1e1188d33761c2c510a6c6d0fde86b Mon Sep 17 00:00:00 2001 From: Sabine Date: Thu, 9 Apr 2026 16:30:09 +0200 Subject: [PATCH 230/251] feat(developer): more tidy up in tests --- .../src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index 34f0f99e6a7..bff598a3905 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -101,7 +101,6 @@ describe('KeylayoutToKmnConverter', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); [ [makePathToFixture('../data/Test_characters.keylayout')], - [makePathToFixture('../data/Test_EmptyOutputCharacter.keylayout')], ].forEach(function (files) { it(files + " should give Error: unsupported characters ", async function () { sut.run(files[0]); From f061a467cef79a1441d3e2f630ba6014beef4802 Mon Sep 17 00:00:00 2001 From: Sabine Date: Tue, 21 Apr 2026 16:03:47 +0200 Subject: [PATCH 231/251] feat(developer): Errormessage, remove keyboard tests, duplicate line boxXmlArray, filter function, remove USED_KEY_IDENTIFIER and function to calculate it --- .../src/kmc-convert/src/converter-messages.ts | 2 +- .../keylayout-to-kmn/keylayout-file-reader.ts | 4 +-- .../keylayout-to-kmn-converter.ts | 34 +++---------------- .../src/keylayout-to-kmn/kmn-file-writer.ts | 2 +- .../test/keylayout-to-kmn-converter.tests.ts | 23 ------------- 5 files changed, 8 insertions(+), 57 deletions(-) diff --git a/developer/src/kmc-convert/src/converter-messages.ts b/developer/src/kmc-convert/src/converter-messages.ts index 42bfff90578..dbb0108db7a 100644 --- a/developer/src/kmc-convert/src/converter-messages.ts +++ b/developer/src/kmc-convert/src/converter-messages.ts @@ -26,7 +26,7 @@ export class ConverterMessages { static ERROR_IntputFilenameIsRequired = SevError | 0x0002; static Error_IntputFilenameIsRequired = () => m( this.ERROR_IntputFilenameIsRequired, - `An output filename is required for keyboard conversion.` + `An input filename is required for keyboard conversion.` ); static ERROR_FileNotFound = SevError | 0x0003; diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts index 2dc98fdb3c5..bf07249f019 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts @@ -47,13 +47,11 @@ export class KeylayoutFileReader { boxXmlArray(keyMapSelect, 'modifier'); } - boxXmlArray(source.keyMapSet[0], 'keyMap'); - for (const keyMapSet of source?.keyMapSet) { + boxXmlArray(keyMapSet, 'keyMap'); for (const keyMap of keyMapSet.keyMap) { boxXmlArray(keyMap, 'key'); } - boxXmlArray(keyMapSet, 'keyMap'); } boxXmlArray(source?.actions, 'action'); diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index caf939851c3..a09ec52f50f 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -88,36 +88,18 @@ export class Rule { } -/** - * @brief member function to find the number of keys defined in a .keykayout file. - * We process 'MAX_KEY_IDENTIFIER' keys at maximum. - * In case a keylayout has fewer keys defined, we use that smaller number of keys (USED_KEY_IDENTIFIER) - * @param data data read from keylayout file - * @return usedKeyCount holding the number of keys of a certain keyMap used in a .keykayout file. - */ -export function findUsedKeysCount(data: any): number { - - let usedKeyCount = KeylayoutToKmnConverter.MAX_KEY_IDENTIFIER; - if (data.keyboard.keyMapSet[0].keyMap[0].key.length < usedKeyCount) { - // set max to n-1 (keys are zero indexed ) - usedKeyCount = data.keyboard.keyMapSet[0].keyMap[0].key.length - 1; - } - return usedKeyCount; -} - export class KeylayoutToKmnConverter { static readonly INPUT_FILE_EXTENSION = '.keylayout'; static readonly OUTPUT_FILE_EXTENSION = '.kmn'; static readonly SKIP_COMMENTED_LINES = false; - static readonly MAX_CTRL_CHARACTER = 0x20; // the hightest control character we print out as a Unicode CodePoint - static readonly MAX_KEY_IDENTIFIER = 49; // At most we use key Nr 0 (A) -> key Nr 49 (Space) - static USED_KEY_IDENTIFIER = KeylayoutToKmnConverter.MAX_KEY_IDENTIFIER; // we use key Nr 0 (A) -> highest available key of .keylayout file + static readonly MAX_CTRL_CHARACTER = 0x20; // the hightest control character we print out as a Unicode CodePoint (U+0020) + static readonly MAX_KEY_IDENTIFIER = 49; // We only use key Nr 0 (A) -> key Nr 49 (Space) private options: CompilerOptions; constructor(private callbacks: CompilerCallbacks, options: CompilerOptions) { this.options = { ...options }; - }; + }; /** * @brief member function to run read/convert/write @@ -204,12 +186,8 @@ export class KeylayoutToKmnConverter { dataObject.modifiers = modifierBehavior; // ukelele uses behaviors e.g. 18 modifiersCombinations in 8 KeyMapSelect(behaviors) dataObject.rules = rules; - // fix the amount of processable keys to the maximun nr of keys of a keyMap to avoid processing more keys than defined - KeylayoutToKmnConverter.USED_KEY_IDENTIFIER = findUsedKeysCount(jsonObj); - // fill rules into 'rules' of dataObject return this.createRuleData(dataObject, jsonObj); - } /** @@ -722,7 +700,7 @@ export class KeylayoutToKmnConverter { if (!keylayoutModifier) return false; // make sure we always have a whitespace before and after each modifier( to distinguish from caps? ) - return (" " + keylayoutModifier.flat().join(" ").toUpperCase() + " ").indexOf(" CAPS ") >= 0;; + return (" " + keylayoutModifier.flat().join(" ").toUpperCase() + " ").indexOf(" CAPS ") >= 0; } /** @@ -947,7 +925,6 @@ export class KeylayoutToKmnConverter { */ public getKeyBehaviorModOutputArrayFromKeyActionBehaviorOutputArray(data: any, search: KeylayoutFileData[], isCAPSused: boolean): KeylayoutFileData[] { const keyBehaviorModOutput = []; - if (!((search === undefined) || (search === null) || (search.length === 0))) { for (let i = 0; i < search.length; i++) { const behaviorIdx: number = Number(search[i].behavior); @@ -990,8 +967,7 @@ export class KeylayoutToKmnConverter { */ public getActionOutputBehaviorKeyModiFromActionIDStateOutput(data: any, modi: string[][], search: string, outchar: string, isCapsused: boolean): KeylayoutFileData[] { const actionOutputBehaviorKeyModi = []; - - if ((search === "") || (search === undefined) || !((isCapsused === true) || (isCapsused === false))) { + if ((!modi) || (search === "") || (search === undefined)) { return []; } // loop behaviors (in ukelele it is possible to define multiple modifier combinations that behave in the same way) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts index 5f850735d71..b2181eeb1c5 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts @@ -88,7 +88,7 @@ export class KmnFileWriter { // (e.g. when in a keylayout file the same modifiers occur in several behaviors thus producing the same rules). // This is to filter out those duplicate Rule objects const uniqueDataRules: Rule[] = dataUkelele.rules.filter((curr) => { - return (!(curr.output === new TextEncoder().encode("") || curr.output === undefined) + return (!(curr.output.length === 0 || curr.output === undefined) && (curr.key !== "") && ((curr.ruleType === "C0") || (curr.ruleType === "C1") diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index bff598a3905..f99fc03e510 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -20,29 +20,6 @@ describe('KeylayoutToKmnConverter', function () { compilerTestCallbacks.clear(); }); - /*describe('RunFILES', function () { - this.timeout(10000); // allow longer time for these tests - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - [ - [makePathToFixture('../data/Polish.keylayout')], - [makePathToFixture('../data/Spanish.keylayout')], - [makePathToFixture('../data/French.keylayout')], - [makePathToFixture('../data/German_complete_reduced.keylayout')], - // [makePathToFixture('../data/German_complete.keylayout')], - // [makePathToFixture('../data/German_standard.keylayout')], - [makePathToFixture('../data/Italian_command.keylayout')], - [makePathToFixture('../data/Italian.keylayout')], - [makePathToFixture('../data/Latin_American.keylayout')], - [makePathToFixture('../data/Swiss_French.keylayout')], - [makePathToFixture('../data/Swiss_German.keylayout')], - ].forEach(function (files) { - it(files + " should give no errors ", async function () { - sut.run(files[0]); - assert.isTrue(compilerTestCallbacks.messages.length === 0); - }); - }); - });*/ - describe('RunSpecialTestFiles', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); [ From ea7582b6f8bd83b0659ffffbe3247c34368d305c Mon Sep 17 00:00:00 2001 From: Sabine Date: Mon, 27 Apr 2026 07:56:46 +0200 Subject: [PATCH 232/251] feat(developer): add a very first version of kmc-convert xbk-kmn functionally identical to kmc-convert keylayout-kmn - using a testfile test.xkb - use xkb-kmn modules(copies of kmc-convert keylayout-kmn modules) - use test.xkb (a renamed copy of test.keylayout) - perform tests: use xkb-kmn modules (copies of keylayout-kmn) --- .../src/converter-class-factory.ts | 2 + .../keylayout-to-kmn-converter.ts | 3 + .../src/keylayout-to-kmn/kmn-file-writer.ts | 73 +- .../src/xkb-to-kmn/kmnXKB-file-writer.ts | 1077 +++++++++++++++++ .../src/xkb-to-kmn/xkb-file-reader.ts | 89 ++ .../src/xkb-to-kmn/xkb-to-kmn-converter.ts | 1040 ++++++++++++++++ developer/src/kmc-convert/test/data/Test.xkb | 596 +++++++++ .../kmc-convert/test/kmn-file-writer.tests.ts | 81 +- .../test/kmnXKB-file-writer.tests.ts | 524 ++++++++ .../kmc-convert/test/xkb-file-reader.tests.ts | 52 + .../test/xkb-to-kmn-converter.tests.ts | 824 +++++++++++++ 11 files changed, 4357 insertions(+), 4 deletions(-) create mode 100644 developer/src/kmc-convert/src/xkb-to-kmn/kmnXKB-file-writer.ts create mode 100644 developer/src/kmc-convert/src/xkb-to-kmn/xkb-file-reader.ts create mode 100644 developer/src/kmc-convert/src/xkb-to-kmn/xkb-to-kmn-converter.ts create mode 100644 developer/src/kmc-convert/test/data/Test.xkb create mode 100644 developer/src/kmc-convert/test/kmnXKB-file-writer.tests.ts create mode 100644 developer/src/kmc-convert/test/xkb-file-reader.tests.ts create mode 100644 developer/src/kmc-convert/test/xkb-to-kmn-converter.tests.ts diff --git a/developer/src/kmc-convert/src/converter-class-factory.ts b/developer/src/kmc-convert/src/converter-class-factory.ts index bbaa88e04a0..549513e3ecd 100644 --- a/developer/src/kmc-convert/src/converter-class-factory.ts +++ b/developer/src/kmc-convert/src/converter-class-factory.ts @@ -4,9 +4,11 @@ * Lists all the available converters and finds matching converter */ import { KeylayoutToKmnConverter } from './keylayout-to-kmn/keylayout-to-kmn-converter.js'; +import { XkbToKmnConverter } from './xkb-to-kmn/xkb-to-kmn-converter.js'; const converters = [ KeylayoutToKmnConverter, + XkbToKmnConverter, ]; export class ConverterClassFactory { diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index a09ec52f50f..0ff6ff0ee43 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -109,6 +109,9 @@ export class KeylayoutToKmnConverter { */ async run(inputFilename: string, outputFilename?: string): Promise { + console.log("°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°\n running KeylayoutToKmnConverter with input file " + + inputFilename + " and output file " + outputFilename); + if (!inputFilename) { this.callbacks.reportMessage(ConverterMessages.Error_FileNotFound({ inputFilename })); return null; diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts index b2181eeb1c5..3d252fa9376 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts @@ -911,7 +911,7 @@ export class KmnFileWriter { * @param inputString the value that will converted * @return a unicode character like 'c', 'ሴ', '😎' or undefined if inputString is not recognized */ - public convertToUnicodeCharacter(inputString: string): string { + public convertToUnicodeCharacter_old(inputString: string): string { // null, undefined will later be refused for conversion @@ -997,6 +997,77 @@ export class KmnFileWriter { return inputString; } + // if no matches so far, check for one or more characters ('a','ab', 'ẘ','😎', '😎😎', ) + else if (m_chr) { + return inputString; + } + return undefined; + } + public convertToUnicodeCharacter(inputString: string): string { + + + // null, undefined will later be refused for conversion + if (inputString == null || inputString == undefined) { + return undefined; + } + + // &#x followed by 1.-6. hex digits will later be used for conversion + const m_hex = /^&#x([0-9a-f]{1,6});$/i.exec(inputString); + + // &# followed by 1.-6. decimal digits will later be used for conversion + const m_dec = /^&#([0-9]{1,7});$/.exec(inputString); + + // & followed by gt, lt, quot, amp, apos will later be used for conversion + const m_nam = /^&(gt|lt|quot|amp|apos);$/i.exec(inputString); + + // &# followed by anything will later be refused for conversion + const m_html_inv = /^(&#)+(.?)+$/i.exec(inputString); + + // one or more characters except starting with & will later be used for conversion + const m_chr = /^(?!&).+$/i.exec(inputString); + + // '&', '&#','&#x' with or without ; will later be refused for conversion + const m_chr_inv = /^((&;?)+|(&#;?)+|(&#x;?)+;?)$|^$/i.exec(inputString); + + // valid '&#x...' + if (m_hex) { + const codePoint_h = parseInt(m_hex[1], 16); + // Reject surrogates and invalid codepoints + if ((codePoint_h >= 0xD800 && codePoint_h <= 0xDFFF) || codePoint_h > 0x10FFFF) { + return undefined; + } + return String.fromCodePoint(codePoint_h); + } + // valid '&#...' + else if (m_dec) { + const codePoint_d = parseInt(m_dec[1], 10); + // Reject surrogates and invalid codepoints + if ((codePoint_d >= 0xD800 && codePoint_d <= 0xDFFF) || codePoint_d > 0x10FFFF) { + return undefined; + } + return String.fromCodePoint(codePoint_d); + } + // valid '>', '<',.. + else if (m_nam) { + switch (m_nam[1].toLowerCase()) { + case 'gt': return '>'; + case 'lt': return '<'; + case 'quot': return '"'; + case 'amp': return '&'; + case 'apos': return "'"; + default: return undefined; + } + } + // invalid '&...' + else if (m_html_inv) { + return undefined; + } + + // single '&', '' + else if (m_chr_inv) { + return inputString; + } + // if no matches so far, check for one or more characters ('a','ab', 'ẘ','😎', '😎😎', ) else if (m_chr) { return inputString; diff --git a/developer/src/kmc-convert/src/xkb-to-kmn/kmnXKB-file-writer.ts b/developer/src/kmc-convert/src/xkb-to-kmn/kmnXKB-file-writer.ts new file mode 100644 index 00000000000..d4c9a97a0ba --- /dev/null +++ b/developer/src/kmc-convert/src/xkb-to-kmn/kmnXKB-file-writer.ts @@ -0,0 +1,1077 @@ +/* + * Keyman is copyright (C) SIL Global. MIT License. + * + * Created by S. Schmitt on 2025-05-12 + * + * Write Keyman .kmn files from an in-memory representation generated + * + */ + +import { CompilerCallbacks, CompilerOptions } from "@keymanapp/developer-utils"; +import { XkbToKmnConverter, ProcessedData, Rule } from './xkb-to-kmn-converter.js'; +import { ConverterMessages } from '../converter-messages.js'; +import KEYMAN_VERSION from "@keymanapp/keyman-version"; + +export interface messageCharacter { + message: string; + character: string; +}; + +export class KmnXKBFileWriter { + + constructor(private callbacks: CompilerCallbacks, private options: CompilerOptions) { }; + + /** + * @brief member function to write data from object to a Uint8Array + * @param dataUkelele the array holding all keyboard data + * @return a Uint8Array holding data + */ + public write(dataUkelele: ProcessedData): Uint8Array { + let data: string = "\n"; + + // top part of kmn file: STORES + const dataStores = this.writeKmnFileHeader(dataUkelele); + + // bottom part of kmn file: RULES + const dataRules = this.writeDataRules(dataUkelele); + + if (dataRules) + data += dataStores + dataRules; + + try { + return new TextEncoder().encode(data); + } catch (err) { + this.callbacks.reportMessage(ConverterMessages.Error_UnableToWrite({ outputFilename: dataUkelele.kmnFilename, errorText: err })); + return null; + } + } + + /** + * @brief member function to create data for the header (stores) that will be printed to the resulting kmn file + * @param dataUkelele an object containing all data read from a .keylayout file + * @return string - all stores to be printed + */ + public writeKmnFileHeader(dataUkelele: ProcessedData): string { + + let data: string = ""; + + data += "c ..................................................................................................................\n"; + data += "c ..................................................................................................................\n"; + data += "c Keyman keyboard generated by kmn-convert version: " + KEYMAN_VERSION.VERSION + "\n"; + data += "c from Ukelele file: " + dataUkelele.keylayoutFilename + "\n"; + data += "c ..................................................................................................................\n"; + data += "c ..................................................................................................................\n"; + data += "\n"; + + data += "store(&TARGETS) \'desktop\'\n"; + + data += "\n"; + data += "begin Unicode > use(main)\n\n"; + data += "group(main) using keys\n\n"; + + data += "\n"; + return data; + } + + /** + * @brief member function to create data from rules that will be printed to the resulting kmn file + * @param dataUkelele an object containing all data read from a .keylayout file + * @return string - all rules to be printed + */ + public writeDataRules(dataUkelele: ProcessedData): string { + + const keylayoutKmnConverter = new XkbToKmnConverter(this.callbacks, this.options); + let data: string = ""; + + // filter array of all rules and remove duplicates + // during the process of creating Rule[], duplicate rules might occur + // (e.g. when in a keylayout file the same modifiers occur in several behaviors thus producing the same rules). + // This is to filter out those duplicate Rule objects + const uniqueDataRules: Rule[] = dataUkelele.rules.filter((curr) => { + return (!(curr.output.length === 0 || curr.output === undefined) + && (curr.key !== "") + && ((curr.ruleType === "C0") + || (curr.ruleType === "C1") + || (curr.ruleType === "C2" && (curr.deadkey !== "")) + || (curr.ruleType === "C3" && (curr.deadkey !== "") && (curr.prevDeadkey !== ""))) + ); + }).reduce((unique, o) => { + if (!unique.some((obj: Rule) => + new TextDecoder().decode(obj.output) === new TextDecoder().decode(o.output) + + && obj.ruleType === o.ruleType + && obj.modifierKey === o.modifierKey + && obj.key === o.key + + && obj.modifierDeadkey === o.modifierDeadkey + && obj.deadkey === o.deadkey + + && obj.modifierPrevDeadkey === o.modifierPrevDeadkey + && obj.prevDeadkey === o.prevDeadkey) + ) { + unique.push(o); + } + return unique; + }, []); + + //................................................ C0 C1 ................................................................ + + for (let k = 0; k < uniqueDataRules.length; k++) { + + if ((uniqueDataRules[k].ruleType === "C0") || (uniqueDataRules[k].ruleType === "C1")) { + + // lookup key nr of the key which is being processed + let keyNr: number = 0; + for (let j = 0; j <= XkbToKmnConverter.MAX_KEY_IDENTIFIER; j++) { + if (keylayoutKmnConverter.mapUkeleleKeycodeToVK(j) === uniqueDataRules[k].key) { + keyNr = j; + break; + } + } + + // skip keyNr 48 (K_TAB) and 36 (K_ENTER) + if ((keyNr === 48) || (keyNr === 36)) { + continue; + } + + // add a line after rules of each key + if ((k > 1) && (uniqueDataRules[k - 1].key !== uniqueDataRules[k].key) && (uniqueDataRules[k - 1].ruleType === uniqueDataRules[k].ruleType)) { + data += '\n'; + } + + // use of Unicode Character vs Unicode Codepoint; + // If it`s a ctrl character we print out the Unicode Codepoint else we print out the Unicode Character + let versionOutputCharacter; + const warnText = this.reviewRules(uniqueDataRules, k); + + const outputCharacter = new TextDecoder().decode(uniqueDataRules[k].output); + // TODO-kmc-convert: after merge of PR 14564 use functions from util instead of the ones in this class + // const outputUnicodeCharacter = util.convertToUnicodeCharacter(outputCharacter); + // const outputUnicodeCodePoint = util.convertToUnicodeCodePoint(outputCharacter); + + if ((outputCharacter !== undefined) || (outputCharacter !== "")) { + const characterMessage = this.writeCharacterOrUnicode(outputCharacter, warnText[2]); + versionOutputCharacter = characterMessage.character; + warnText[2] = characterMessage.message; + } + + // add a warning in front of rules in case unavailable modifiers or ambiguous rules are used + // if warning contains duplicate rules we do not write out the entire rule + // (even if there are other warnings for the same rule) since that rule had been written before + if (warnText[2].indexOf("duplicate") < 0) { + + let warningTextToWrite = ""; + if (!XkbToKmnConverter.SKIP_COMMENTED_LINES && (warnText[2].length > 0)) { + warningTextToWrite = warnText[2]; + } + + if (!((warnText[2].length > 0) && XkbToKmnConverter.SKIP_COMMENTED_LINES)) { + if (versionOutputCharacter === "'") { + data += warningTextToWrite + + "+ [" + + (uniqueDataRules[k].modifierKey + ' ' + uniqueDataRules[k].key).trim() + + `] > \"` + + versionOutputCharacter + + '\"\n'; + } + else { + data += warningTextToWrite + + "+ [" + + (uniqueDataRules[k].modifierKey + ' ' + uniqueDataRules[k].key).trim() + + `] > \'` + + versionOutputCharacter + + '\'\n'; + } + } + } + } + } + + //................................................ C2 ................................................................... + for (let k = 0; k < uniqueDataRules.length; k++) { + + if (uniqueDataRules[k].ruleType === "C2") { + + // use of Unicode Character vs Unicode Codepoint; + // If it`s a ctrl character we print out the Unicode Codepoint else we print out the Unicode Character + let versionOutputCharacter; + const warnText = this.reviewRules(uniqueDataRules, k); + + const outputCharacter = new TextDecoder().decode(uniqueDataRules[k].output); + // TODO-kmc-convert: after merge of PR 14564 use functions from util instead of the ones in this class + // const outputUnicodeCharacter = util.convertToUnicodeCharacter(outputCharacter); + // const outputUnicodeCodePoint = util.convertToUnicodeCodePoint(outputCharacter); + + if ((outputCharacter !== undefined) || (outputCharacter !== "")) { + const characterMessage = this.writeCharacterOrUnicode(outputCharacter, warnText[2]); + versionOutputCharacter = characterMessage.character; + warnText[2] = characterMessage.message; + } + + // add a warning in front of rules in case unavailable modifiers or ambiguous rules are used + // if warning contains duplicate rules we do not write out the entire rule + // (even if there are other warnings for the same rule) since that rule had been written before + if (warnText[1].indexOf("duplicate") < 0) { + + let warningTextToWrite = ""; + if (!XkbToKmnConverter.SKIP_COMMENTED_LINES && (warnText[1].length > 0)) { + warningTextToWrite = warnText[1]; + } + + if (!((warnText[1].length > 0) && XkbToKmnConverter.SKIP_COMMENTED_LINES)) { + data += warningTextToWrite + + "+ [" + (uniqueDataRules[k].modifierDeadkey + " " + + uniqueDataRules[k].deadkey).trim() + + "] > dk(A" + String(uniqueDataRules[k].idDeadkey) + + ")\n"; + } + } + + if ((warnText[2].indexOf("duplicate") < 0)) { + + let warningTextToWrite = ""; + if (!XkbToKmnConverter.SKIP_COMMENTED_LINES && (warnText[2].length > 0)) { + warningTextToWrite = warnText[2]; + } + + if (!((warnText[2].length > 0) && XkbToKmnConverter.SKIP_COMMENTED_LINES)) { + if (versionOutputCharacter === "'") { + data += warningTextToWrite + + "dk(A" + + (String(uniqueDataRules[k].idDeadkey) + ") + [" + + uniqueDataRules[k].modifierKey).trim() + + " " + + uniqueDataRules[k].key + '] > \"' + + versionOutputCharacter + + '\"\n'; + } + else { + data += warningTextToWrite + + "dk(A" + + (String(uniqueDataRules[k].idDeadkey) + ") + [" + + uniqueDataRules[k].modifierKey).trim() + + " " + + uniqueDataRules[k].key + "] > \'" + + versionOutputCharacter + + "\'\n"; + } + + + } + data += "\n"; + } + } + } + + //................................................ C3 ................................................................... + + for (let k = 0; k < uniqueDataRules.length; k++) { + if (uniqueDataRules[k].ruleType === "C3") { + + // use of Unicode Character vs Unicode Codepoint; + // If it`s a ctrl character we print out the Unicode Codepoint else we print out the Unicode Character + let versionOutputCharacter; + + const warnText = this.reviewRules(uniqueDataRules, k); + const outputCharacter = new TextDecoder().decode(uniqueDataRules[k].output); + // TODO-kmc-convert: after merge of PR 14564 use functions from util instead of the ones in this class + + if ((outputCharacter !== undefined) || (outputCharacter !== "")) { + const characterMessage = this.writeCharacterOrUnicode(outputCharacter, warnText[2]); + versionOutputCharacter = characterMessage.character; + warnText[2] = characterMessage.message; + } + + // add a warning in front of rules in case unavailable modifiers or ambiguous rules are used + // if warning contains duplicate rules we do not write out the entire rule + // (even if there are other warnings for the same rule) since that rule had been written before + if (warnText[0].indexOf("duplicate") < 0) { + + let warningTextToWrite = ""; + + if (!XkbToKmnConverter.SKIP_COMMENTED_LINES && (warnText[0].length > 0)) { + warningTextToWrite = warnText[0]; + } + + if (!((warnText[0].length > 0) && XkbToKmnConverter.SKIP_COMMENTED_LINES)) { + data += warningTextToWrite + + "+ [" + + (uniqueDataRules[k].modifierPrevDeadkey + " " + + uniqueDataRules[k].prevDeadkey).trim() + + "] > dk(A" + + String(uniqueDataRules[k].idPrevDeadkey) + ")\n"; + } + } + + if (warnText[1].indexOf("duplicate") < 0) { + + let warningTextToWrite = ""; + if (!XkbToKmnConverter.SKIP_COMMENTED_LINES && (warnText[1].length > 0)) { + warningTextToWrite = warnText[1]; + } + + if (!((warnText[1].length > 0) && XkbToKmnConverter.SKIP_COMMENTED_LINES)) { + data += warningTextToWrite + + "dk(A" + (String(uniqueDataRules[k].idPrevDeadkey) + ") + [" + + uniqueDataRules[k].modifierDeadkey).trim() + + " " + + uniqueDataRules[k].deadkey + + "] > dk(B" + + String(uniqueDataRules[k].idDeadkey) + + ")\n"; + } + } + + if (warnText[2].indexOf("duplicate") < 0) { + + let warningTextToWrite = ""; + if (!XkbToKmnConverter.SKIP_COMMENTED_LINES && (warnText[2].length > 0)) { + warningTextToWrite = warnText[2]; + } + + if (!((warnText[2].length > 0) && XkbToKmnConverter.SKIP_COMMENTED_LINES)) { + data += warningTextToWrite + "dk(B" + + (String(uniqueDataRules[k].idDeadkey) + + ") + [" + + uniqueDataRules[k].modifierKey).trim() + + " " + + uniqueDataRules[k].key + + "] > \'" + + versionOutputCharacter + + "\'\n"; + } + } + + if ((warnText[0].indexOf("duplicate") < 0) || (warnText[1].indexOf("duplicate") < 0) || (warnText[2].indexOf("duplicate") < 0)) { + data += "\n"; + } + } + } + return data; + } + + /** + * @brief member function to review rules for acceptable modifiers, duplicate or ambiguous rules and return an array containing possible warnings. + * Keyman can not handle duplicate rules so we need to make sure a rule is written only once by either omitting a duplicate rule or commenting out an ambiguous rule. + * Omitting rules and definition of comparisons e.g. 1-1, 2-4, 6-6 + * see https://docs.google.com/document/d/12J3NGO6RxIthCpZDTR8FYSRjiMgXJDLwPY2z9xqKzJ0/edit?tab=t.0#heading=h.pcz8rjyrl5ug + * @param rule : Rule[] - an array of all rules + * @param index the index of a rule in Rule[] + * @return a string[] containing possible warnings for a rule + */ + public reviewRules(rule: Rule[], index: number): string[] { + + const keylayoutKmnConverter = new XkbToKmnConverter(this.callbacks, this.options); + const warningText: string[] = Array(3).fill(""); + + // ------------------------- check unavailable modifiers ------------------------- + + if ((rule[index].ruleType === "C0") || (rule[index].ruleType === "C1")) { + if (!keylayoutKmnConverter.isAcceptableKeymanModifier(rule[index].modifierKey)) { + warningText[2] = "unavailable modifier : "; + } + } + + else if (rule[index].ruleType === "C2") { + if (!keylayoutKmnConverter.isAcceptableKeymanModifier(rule[index].modifierDeadkey)) { + warningText[1] = "unavailable modifier : "; + warningText[2] = "unavailable superior rule ( [" + + rule[index].modifierDeadkey + " " + + rule[index].deadkey + + "] > dk(A" + + rule[index].idDeadkey + + ") ) : "; + } + if (!keylayoutKmnConverter.isAcceptableKeymanModifier(rule[index].modifierKey)) { + warningText[2] = "unavailable modifier : "; + } + } + + else if (rule[index].ruleType === "C3") { + + if (!keylayoutKmnConverter.isAcceptableKeymanModifier(rule[index].modifierPrevDeadkey)) { + warningText[0] = "unavailable modifier : "; + warningText[1] = "unavailable superior rule ( [" + + rule[index].modifierPrevDeadkey + " " + + rule[index].prevDeadkey + + "] > dk(A" + + rule[index].idPrevDeadkey + + ") ) : "; + } + + if (!keylayoutKmnConverter.isAcceptableKeymanModifier(rule[index].modifierDeadkey)) { + warningText[1] = "unavailable modifier : "; + warningText[2] = "unavailable superior rule ( [" + + rule[index].modifierDeadkey + " " + + rule[index].deadkey + + "] > dk(B" + + rule[index].idDeadkey + + ") ) : "; + } + + if (!keylayoutKmnConverter.isAcceptableKeymanModifier(rule[index].modifierKey)) { + warningText[2] = "unavailable modifier : "; + } + } + + // ------------------------- check ambiguous/duplicate rules ------------------------- + + if ((rule[index].ruleType === "C0") || (rule[index].ruleType === "C1")) { + + // 1-1: + [CAPS K_N] > 'N' <-> + [CAPS K_N] > 'A' + const amb_1_1 = rule.filter((curr, idx) => + (curr.ruleType === "C0" || curr.ruleType === "C1") + && curr.modifierPrevDeadkey === "" + && curr.prevDeadkey === "" + && curr.modifierDeadkey === "" + && curr.deadkey === "" + && curr.modifierKey === rule[index].modifierKey + && curr.key === rule[index].key + && new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output) + && idx < index + ); + // 1-1: + [CAPS K_N] > 'N' <-> + [CAPS K_N] > 'N' + const dup_1_1 = rule.filter((curr, idx) => + (curr.ruleType === "C0" || curr.ruleType === "C1") + && curr.modifierPrevDeadkey === "" + && curr.prevDeadkey === "" + && curr.modifierDeadkey === "" + && curr.deadkey === "" + && curr.modifierKey === rule[index].modifierKey + && curr.key === rule[index].key + && new TextDecoder().decode(curr.output) === new TextDecoder().decode(rule[index].output) + && idx < index + ); + + // 4-1: + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > 'Ñ' + const amb_4_1 = rule.filter((curr, idx) => + ((curr.ruleType === "C3")) + && curr.modifierPrevDeadkey === rule[index].modifierKey + && curr.prevDeadkey === rule[index].key + ); + + // 2-1: + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > 'Ñ' + const amb_2_1 = rule.filter((curr, idx) => + ((curr.ruleType === "C2")) + && curr.modifierDeadkey === rule[index].modifierKey + && curr.deadkey === rule[index].key + ); + + if (amb_4_1.length > 0) { + warningText[2] = warningText[2] + + ("ambiguous rule: later: [" + + amb_4_1[0].modifierPrevDeadkey + + " " + + amb_4_1[0].prevDeadkey + + "] > dk(C" + + amb_2_1[0].idDeadkey + + ") "); + } + + if (amb_2_1.length > 0) { + warningText[2] = warningText[2] + + ("ambiguous rule: later: [" + + amb_2_1[0].modifierDeadkey + + " " + + amb_2_1[0].deadkey + + "] > dk(A" + + amb_2_1[0].idDeadkey + + ") "); + } + + if (amb_1_1.length > 0) { + warningText[2] = warningText[2] + + ("ambiguous rule: earlier: [" + + amb_1_1[0].modifierKey + + " " + + amb_1_1[0].key + + "] > \'" + + this.writeCharacterOrUnicode(new TextDecoder().decode(amb_1_1[0].output)).character + + "\' "); + } + + if (dup_1_1.length > 0) { + warningText[2] = warningText[2] + + ("duplicate rule: earlier: [" + + dup_1_1[0].modifierKey + + " " + + dup_1_1[0].key + + "] > \'" + + this.writeCharacterOrUnicode(new TextDecoder().decode(dup_1_1[0].output)).character + + "\' "); + } + } + + if (rule[index].ruleType === "C2") { + + // 2-2: + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(C3) + const amb_2_2 = rule.filter((curr, idx) => + curr.ruleType === "C2" + && curr.modifierDeadkey === rule[index].modifierDeadkey + && curr.deadkey === rule[index].deadkey + && curr.idDeadkey !== rule[index].idDeadkey + && idx < index + ); + + // 2-2: + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(C11) + const dup_2_2 = rule.filter((curr, idx) => + curr.ruleType === "C2" + && curr.modifierDeadkey === rule[index].modifierDeadkey + && curr.deadkey === rule[index].deadkey + && curr.idDeadkey === rule[index].idDeadkey + && idx < index + ); + + //3-3: dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'B' + const amb_3_3 = rule.filter((curr, idx) => + (curr.ruleType === "C2") + && curr.idDeadkey === rule[index].idDeadkey + && curr.modifierKey === rule[index].modifierKey + && curr.key === rule[index].key + && new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output) + && idx < index + ); + + //3-3: dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'Ã' + const dup_3_3 = rule.filter((curr, idx) => + (curr.ruleType === "C2") + && curr.idDeadkey === rule[index].idDeadkey + && rule[index].uniqueDeadkey === 0 + && curr.modifierKey === rule[index].modifierKey + && curr.key === rule[index].key + && new TextDecoder().decode(curr.output) === new TextDecoder().decode(rule[index].output) + && idx < index + ); + + // 4-2: + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(B11) + const amb_4_2 = rule.filter((curr, idx) => + ((curr.ruleType === "C3")) + && curr.modifierPrevDeadkey === rule[index].modifierDeadkey + && curr.prevDeadkey === rule[index].deadkey + && curr.idPrevDeadkey === rule[index].idDeadkey + ); + + if (amb_2_2.length > 0) { + warningText[1] = warningText[1] + + ("ambiguous rule: earlier: [" + + amb_2_2[0].modifierDeadkey + + " " + + amb_2_2[0].deadkey + + "] > dk(C" + + amb_2_2[0].idDeadkey + + ") "); + } + + if (dup_2_2.length > 0) { + warningText[1] = warningText[1] + + ("duplicate rule: earlier: [" + + dup_2_2[0].modifierDeadkey + + " " + + dup_2_2[0].deadkey + + "] > dk(C" + + dup_2_2[0].idDeadkey + + ") "); + } + + if (amb_3_3.length > 0) { + warningText[2] = warningText[2] + + ("ambiguous rule: earlier: dk(A" + + amb_3_3[0].idDeadkey + + ") + [" + + amb_3_3[0].modifierKey + + " " + + amb_3_3[0].key + + "] > \'" + + this.writeCharacterOrUnicode(new TextDecoder().decode(amb_3_3[0].output)).character + + "\' "); + } + + if (dup_3_3.length > 0) { + warningText[2] = warningText[2] + + ("duplicate rule: earlier: dk(A" + + dup_3_3[0].idDeadkey + + ") + [" + + dup_3_3[0].modifierKey + + " " + + dup_3_3[0].key + + "] > \'" + + this.writeCharacterOrUnicode(new TextDecoder().decode(dup_3_3[0].output)).character + + "\' "); + } + + if (amb_4_2.length > 0) { + warningText[0] = warningText[0] + + ("ambiguous rule: later: [" + + amb_4_2[0].modifierPrevDeadkey + + " " + + amb_4_2[0].prevDeadkey + + "] > dk(C" + + amb_4_2[0].idPrevDeadkey + + ") "); + } + } + + if (rule[index].ruleType === "C3") { + + // 2-4 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(B11) + const amb_2_4 = rule.filter((curr, idx) => + ((curr.ruleType === "C2")) + && curr.modifierDeadkey === rule[index].modifierPrevDeadkey + && curr.deadkey === rule[index].prevDeadkey + && curr.idDeadkey === rule[index].idPrevDeadkey + ); + + // 6-3 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'B' + const amb_6_3 = rule.filter((curr, idx) => + (curr.ruleType === "C2") + && curr.idPrevDeadkey === rule[index].idPrevDeadkey + && curr.modifierKey === rule[index].modifierKey + && curr.key === rule[index].key + && (new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output)) + ); + + // 6-3 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'Ã' + const dup_6_3 = rule.filter((curr, idx) => + (curr.ruleType === "C2") + && curr.idPrevDeadkey === rule[index].idPrevDeadkey + && curr.modifierKey === rule[index].modifierKey + && curr.key === rule[index].key + && new TextDecoder().decode(curr.output) === new TextDecoder().decode(rule[index].output) + ); + + // 4-4 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(C1) + const amb_4_4 = rule.filter((curr, idx) => + curr.ruleType === "C3" + && curr.modifierPrevDeadkey === rule[index].modifierPrevDeadkey + && curr.idPrevDeadkey !== rule[index].idPrevDeadkey + && curr.prevDeadkey === rule[index].prevDeadkey + && rule[index].uniquePrevDeadkey !== 0 + && idx < index + ); + + // 4-4 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(C11) + const dup_4_4 = rule.filter((curr, idx) => + curr.ruleType === "C3" + && curr.modifierPrevDeadkey === rule[index].modifierPrevDeadkey + && curr.prevDeadkey === rule[index].prevDeadkey + && curr.idPrevDeadkey === rule[index].idPrevDeadkey + && idx < index + ); + + // 5-5 dk(C1) + [SHIFT CAPS K_A] > dk(C2) <-> dk(C1) + [SHIFT CAPS K_A] > dk(C3) + const amb_5_5 = rule.filter((curr, idx) => ( + (curr.ruleType === "C3") + && curr.idPrevDeadkey === rule[index].idPrevDeadkey + && curr.modifierDeadkey === rule[index].modifierDeadkey + && curr.deadkey === rule[index].deadkey + && curr.idDeadkey === rule[index].idDeadkey) + && idx < index + && (rule[index].uniqueDeadkey !== 0 || rule[index].uniquePrevDeadkey !== 0) + ); + + // 5-5 dk(C1) + [SHIFT CAPS K_A] > dk(C2) <-> dk(C1) + [SHIFT CAPS K_A] > dk(C2) + const dup_5_5 = rule.filter((curr, idx) => + (curr.ruleType === "C3") + && curr.idPrevDeadkey === rule[index].idPrevDeadkey + && curr.modifierPrevDeadkey === rule[index].modifierPrevDeadkey + && curr.prevDeadkey === rule[index].prevDeadkey + && curr.modifierDeadkey === rule[index].modifierDeadkey + && curr.deadkey === rule[index].deadkey + && curr.idDeadkey === rule[index].idDeadkey + && rule[index].uniqueDeadkey === 0 + && idx < index + ); + + // 6-6 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'B' + const amb_6_6 = rule.filter((curr, idx) => + (curr.ruleType === "C3") + && curr.idPrevDeadkey === rule[index].idPrevDeadkey + && curr.modifierKey === rule[index].modifierKey + && curr.key === rule[index].key + && (new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output)) + && idx < index + ); + + // 6-6 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'Ã' + const dup_6_6 = + rule.filter((curr, idx) => + (curr.ruleType === "C3") + && curr.idDeadkey === rule[index].idDeadkey + && curr.modifierKey === rule[index].modifierKey + && curr.key === rule[index].key + && (new TextDecoder().decode(curr.output) === new TextDecoder().decode(rule[index].output)) + && idx < index + ); + + if (amb_2_4.length > 0) { + warningText[0] = warningText[0] + + ("ambiguous rule: earlier: [" + + amb_2_4[0].modifierDeadkey + + " " + + amb_2_4[0].deadkey + + "] > dk(A" + + amb_2_4[0].idDeadkey + + ") "); + } + + if (amb_6_3.length > 0) { + warningText[1] = warningText[1] + + ("ambiguous rule: earlier: dk(C" + + amb_6_3[0].idDeadkey + + ") + [" + + amb_6_3[0].modifierKey + + " " + + amb_6_3[0].key + + "] > \'" + + this.writeCharacterOrUnicode(new TextDecoder().decode(amb_6_3[0].output)).character + + "\' "); + } + + if (dup_6_3.length > 0) { + warningText[1] = warningText[1] + + ("duplicate rule: earlier: dk(C" + + dup_6_3[0].idDeadkey + + ") + [" + + dup_6_3[0].modifierKey + + " " + + dup_6_3[0].key + + "] > \'" + + this.writeCharacterOrUnicode(new TextDecoder().decode(dup_6_3[0].output)).character + + "\' "); + } + + if (amb_4_4.length > 0) { + warningText[0] = warningText[0] + + ("ambiguous rule: earlier: [" + + amb_4_4[0].modifierPrevDeadkey + + " " + + amb_4_4[0].prevDeadkey + + "] > dk(C" + + amb_4_4[0].idPrevDeadkey + + ") "); + } + + if (dup_4_4.length > 0) { + warningText[0] = warningText[0] + + ("duplicate rule: earlier: [" + + dup_4_4[0].modifierPrevDeadkey + + " " + + dup_4_4[0].prevDeadkey + + "] > dk(C" + + dup_4_4[0].idPrevDeadkey + + ") "); + } + + if (amb_5_5.length > 0) { + warningText[1] = warningText[1] + + ("ambiguous rule: earlier: dk(B" + + amb_5_5[0].idPrevDeadkey + + ") + [" + + amb_5_5[0].modifierDeadkey + + " " + + amb_5_5[0].deadkey + + "] > dk(B" + + amb_5_5[0].idDeadkey + + ") "); + } + + if (dup_5_5.length > 0) { + warningText[1] = warningText[1] + + ("duplicate rule: earlier: dk(B" + + dup_5_5[0].idPrevDeadkey + + ") + [" + + dup_5_5[0].modifierDeadkey + + " " + + dup_5_5[0].deadkey + + "] > dk(B" + + dup_5_5[0].idDeadkey + + ") "); + } + + if (amb_6_6.length > 0) { + warningText[2] = warningText[2] + + ("ambiguous rule: earlier: dk(B" + + amb_6_6[0].idDeadkey + + ") + [" + + amb_6_6[0].modifierKey + + " " + + amb_6_6[0].key + + "] > \'" + + this.writeCharacterOrUnicode(new TextDecoder().decode(amb_6_6[0].output)).character + + "\' "); + } + + if (dup_6_6.length > 0) { + warningText[2] = warningText[2] + + ("duplicate rule: earlier: dk(B" + + dup_6_6[0].idDeadkey + + ") + [" + + dup_6_6[0].modifierKey + + " " + + dup_6_6[0].key + + "] > \'" + + this.writeCharacterOrUnicode(new TextDecoder().decode(dup_6_6[0].output)).character + + "\' "); + } + } + // In rare cases a rule might not be written out therefore we need to inform the user: + // usually we write the first occurance of an ambiguous C0/C1 rule and comment out the later + // assuming that if several C0/C1 rules are ambiguous the user prefers to use the first C0/C1 rule + // for C2/C3 rules we write the last occurance of an ambiguous rule and comment out the earlier + // assuming that if a C0/C1 and a C2/C3 rule is ambiguous the user prefers to use the C2/C3 rule over the C0/C1 rule + // if both happens, nothing would be written, therefore this messsage + + const extraWarning = "PLEASE CHECK THE FOLLOWING RULE AS IT WILL NOT BE WRITTEN ! "; + + if (warningText[0] !== "") { + warningText[0] = "c WARNING: " + warningText[0] + "here: "; + + if ((warningText[0].indexOf("earlier:") > 0) && (warningText[0].indexOf("later:") > 0)) { + warningText[0] = warningText[0] + extraWarning; + } + } + if (warningText[1] !== "") { + warningText[1] = "c WARNING: " + warningText[1] + "here: "; + + if ((warningText[1].indexOf("earlier:") > 0) && (warningText[1].indexOf("later:") > 0)) { + warningText[1] = warningText[1] + extraWarning; + } + } + + if (warningText[2] !== "") { + warningText[2] = "c WARNING: " + warningText[2] + "here: "; + + if ((warningText[2].indexOf("earlier:") > 0) && (warningText[2].indexOf("later:") > 0)) { + warningText[2] = warningText[2] + extraWarning; + } + } + return warningText; + } + + /** + * @brief member function to write a character as Unicode Character or Unicode Codepoint depending on the character that is to be written + * @param ctr : string - the character to be written + * @return a string containing the Unicode representation of the control character. + * A control character will be written as unicode (U+0004), + * a non-control character will be written as itself ( 'A', '1', '፩', '😎') + * null in case of an empty string or null or undefined input + */ + public writeCharacterOrUnicode(ctr: string, msg: string = ""): messageCharacter { + + if ((ctr === null) || (ctr === undefined) || (ctr.length === 0)) { + return null; + } + + let versionOutputCharacter; + const out: messageCharacter = { + message: msg, + character: ctr + }; + + const m_uni = /^U\+([0-9a-f]{1,6})$/i.exec(ctr); + const m_hex = /^&#x([0-9a-f]{1,6});$/i.exec(ctr); + const m_dec = /^&#([0-9]{1,7});$/.exec(ctr); + + // find the value of output character which may be specified in unicode, html hex or html dec format ( e.g. U+1234 -> 1234; ሴ -> 1234; ሴ -> 1234) + const ctr_val = ((m_uni || m_hex || m_dec) ? + m_uni ? parseInt(m_uni[1], 16) : m_hex ? parseInt(m_hex[1], 16) : parseInt(m_dec[1], 10) : XkbToKmnConverter.MAX_CTRL_CHARACTER + ); + + // for control charactersin 'U+...', '&#x...' or '&#...' format as well as in "" format + if ((ctr_val < XkbToKmnConverter.MAX_CTRL_CHARACTER) || (ctr.charCodeAt(0) < XkbToKmnConverter.MAX_CTRL_CHARACTER)) { + + // for control characters in 'U+...', '&#x...' or '&#...' format + if (ctr_val < XkbToKmnConverter.MAX_CTRL_CHARACTER) { + versionOutputCharacter = "U+" + ctr_val.toString(16).toUpperCase().padStart(4, '0'); + } + // for control characters in "" format + if (ctr.charCodeAt(0) < XkbToKmnConverter.MAX_CTRL_CHARACTER) { + versionOutputCharacter = "U+" + ctr.charCodeAt(0).toString(16).toUpperCase().padStart(4, '0'); + } + if (versionOutputCharacter) + out.character = versionOutputCharacter; + + // add a warning message + if (msg == "") { + out.message = "c WARNING: use of a control character "; + } + else { + out.message = msg + "; Use of a control character "; + } + } + else { + out.character = this.convertToUnicodeCharacter(ctr);; + } + return out; + } + + // TODO: move to util in PR 14569 + /** + * @brief function to convert a numeric character reference or a unicode value to a unicode character e.g. c -> c; U+1F60E -> 😎 + * @param inputString the value that will converted + * @return a unicode character like 'c', 'ሴ', '😎' or undefined if inputString is not recognized + */ + public convertToUnicodeCharacter_old(inputString: string): string { + + + // null, undefined will later be refused for conversion + if (inputString == null || inputString == undefined) { + return undefined; + } + + // U+ followed by 1.-6. hex digits will later be used for conversion + const m_uni = /^U\+([0-9a-f]{1,6})$/i.exec(inputString); + + // invalid U+ ( U+ followed by anything) will later be refused for conversion + const m_uni_inv = /^(U\+)+(.?)+$/i.exec(inputString); + + // &#x followed by 1.-6. hex digits will later be used for conversion + const m_hex = /^&#x([0-9a-f]{1,6});$/i.exec(inputString); + + // &# followed by 1.-6. decimal digits will later be used for conversion + const m_dec = /^&#([0-9]{1,7});$/.exec(inputString); + + // & followed by gt, lt, quot, amp, apos will later be used for conversion + const m_nam = /^&(gt|lt|quot|amp|apos);$/i.exec(inputString); + + // &# followed by anything will later be refused for conversion + const m_html_inv = /^(&#)+(.?)+$/i.exec(inputString); + + // one or more characters except starting with U+ or & will later be used for conversion + const m_chr = /^(?!U\+|&).+$/i.exec(inputString); + + // '&', '&#','&#x', or 'U+' with or without ; will later be refused for conversion + const m_chr_inv = /^((&;?)+|(&#;?)+|(&#x;?)+|(U\+)+;?)$|^$/i.exec(inputString); + + // valid 'U+xxxx' + if (m_uni) { + const codePoint_u = parseInt(m_uni[1], 16); + // Reject surrogates and invalid codepoints + if ((codePoint_u >= 0xD800 && codePoint_u <= 0xDFFF) || codePoint_u > 0x10FFFF) { + return undefined; + } + return String.fromCodePoint(codePoint_u); + } + + // invalid 'U+xxxx' + else if (m_uni_inv) { + return undefined; + } + + // valid '&#x...' + else if (m_hex) { + const codePoint_h = parseInt(m_hex[1], 16); + // Reject surrogates and invalid codepoints + if ((codePoint_h >= 0xD800 && codePoint_h <= 0xDFFF) || codePoint_h > 0x10FFFF) { + return undefined; + } + return String.fromCodePoint(codePoint_h); + } + // valid '&#...' + else if (m_dec) { + const codePoint_d = parseInt(m_dec[1], 10); + // Reject surrogates and invalid codepoints + if ((codePoint_d >= 0xD800 && codePoint_d <= 0xDFFF) || codePoint_d > 0x10FFFF) { + return undefined; + } + return String.fromCodePoint(codePoint_d); + } + // valid '>', '<',.. + else if (m_nam) { + switch (m_nam[1].toLowerCase()) { + case 'gt': return '>'; + case 'lt': return '<'; + case 'quot': return '"'; + case 'amp': return '&'; + case 'apos': return "'"; + default: return undefined; + } + } + // invalid '&...' + else if (m_html_inv) { + return undefined; + } + + // single 'U+', '&', '' + else if (m_chr_inv) { + return inputString; + } + + // if no matches so far, check for one or more characters ('a','ab', 'ẘ','😎', '😎😎', ) + else if (m_chr) { + return inputString; + } + return undefined; + } + public convertToUnicodeCharacter(inputString: string): string { + + + // null, undefined will later be refused for conversion + if (inputString == null || inputString == undefined) { + return undefined; + } + + // &#x followed by 1.-6. hex digits will later be used for conversion + const m_hex = /^&#x([0-9a-f]{1,6});$/i.exec(inputString); + + // &# followed by 1.-6. decimal digits will later be used for conversion + const m_dec = /^&#([0-9]{1,7});$/.exec(inputString); + + // & followed by gt, lt, quot, amp, apos will later be used for conversion + const m_nam = /^&(gt|lt|quot|amp|apos);$/i.exec(inputString); + + // &# followed by anything will later be refused for conversion + const m_html_inv = /^(&#)+(.?)+$/i.exec(inputString); + + // one or more characters except starting with & will later be used for conversion + const m_chr = /^(?!&).+$/i.exec(inputString); + + // '&', '&#','&#x' with or without ; will later be refused for conversion + const m_chr_inv = /^((&;?)+|(&#;?)+|(&#x;?)+;?)$|^$/i.exec(inputString); + + // valid '&#x...' + if (m_hex) { + const codePoint_h = parseInt(m_hex[1], 16); + // Reject surrogates and invalid codepoints + if ((codePoint_h >= 0xD800 && codePoint_h <= 0xDFFF) || codePoint_h > 0x10FFFF) { + return undefined; + } + return String.fromCodePoint(codePoint_h); + } + // valid '&#...' + else if (m_dec) { + const codePoint_d = parseInt(m_dec[1], 10); + // Reject surrogates and invalid codepoints + if ((codePoint_d >= 0xD800 && codePoint_d <= 0xDFFF) || codePoint_d > 0x10FFFF) { + return undefined; + } + return String.fromCodePoint(codePoint_d); + } + // valid '>', '<',.. + else if (m_nam) { + switch (m_nam[1].toLowerCase()) { + case 'gt': return '>'; + case 'lt': return '<'; + case 'quot': return '"'; + case 'amp': return '&'; + case 'apos': return "'"; + default: return undefined; + } + } + // invalid '&...' + else if (m_html_inv) { + return undefined; + } + + // single '&', '' + else if (m_chr_inv) { + return inputString; + } + + // if no matches so far, check for one or more characters ('a','ab', 'ẘ','😎', '😎😎', ) + else if (m_chr) { + return inputString; + } + return undefined; + } +} diff --git a/developer/src/kmc-convert/src/xkb-to-kmn/xkb-file-reader.ts b/developer/src/kmc-convert/src/xkb-to-kmn/xkb-file-reader.ts new file mode 100644 index 00000000000..f737a56780d --- /dev/null +++ b/developer/src/kmc-convert/src/xkb-to-kmn/xkb-file-reader.ts @@ -0,0 +1,89 @@ +/* + * Keyman is copyright (C) SIL Global. MIT License. + * + * Created by S. Schmitt on 2025-05-12 + * + * Read macOS/Ukelele .keylayout files + * + */ + +import { CompilerCallbacks, DeveloperUtilsMessages, Keylayout, KeymanXMLReader } from "@keymanapp/developer-utils"; +import { util, SchemaValidators } from '@keymanapp/common-types'; +import { ConverterMessages } from '../converter-messages.js'; +import boxXmlArray = util.boxXmlArray; + +export class XkbFileReader { + + constructor(private callbacks: CompilerCallbacks /*,private options: CompilerOptions*/) { }; + + /** + * @returns true if valid, false if invalid + */ + public validate(source: Keylayout.KeylayoutXMLSourceFile): boolean { + if (!SchemaValidators.default.keylayout(source)) { + for (const err of (SchemaValidators.default.keylayout).errors) { + this.callbacks.reportMessage(DeveloperUtilsMessages.Error_InvalidXml({ + e: err.instancePath + })); + } + return false; + } + return true; + } + + /** + * @brief member function to box single-entry objects into arrays + * @param source the object to be changed + * @return object that contain only boxed arrays + */ + public boxArray(source: any) { + + boxXmlArray(source, 'keyMapSet'); + + boxXmlArray(source.layouts, 'layout'); + boxXmlArray(source?.modifierMap, 'keyMapSelect'); + + for (const keyMapSelect of source?.modifierMap?.keyMapSelect) { + boxXmlArray(keyMapSelect, 'modifier'); + } + + for (const keyMapSet of source?.keyMapSet) { + boxXmlArray(keyMapSet, 'keyMap'); + for (const keyMap of keyMapSet.keyMap) { + boxXmlArray(keyMap, 'key'); + } + } + + boxXmlArray(source?.actions, 'action'); + for (const action of source?.actions?.action) { + boxXmlArray(action, 'when'); + } + + boxXmlArray(source.terminators, 'when'); + for (const action of source?.actions?.action) { + boxXmlArray(action, 'when'); + } + + return source; + } + + /** + * @brief member function to parse data from a .keylayout-file and store in a json object + * we need to be able to ignore an output character of "", process an output character of " " (space) and allow surrounding whitespace in #text (which will be removed later) + * @param inputFilename the ukelele .keylayout-file to be parsed + * @return in case of success: json object containing data of the .keylayout file; else null + */ + public read(source: Uint8Array): Keylayout.KeylayoutXMLSourceFile { + + try { + const data = new TextDecoder().decode(source); + const jsonObj = new KeymanXMLReader('keylayout').parse(data) as Keylayout.KeylayoutXMLSourceFile; + this.boxArray(jsonObj.keyboard); // jsonObj now contains arrays; no single fields + return jsonObj; + } + catch (err) { + this.callbacks.reportMessage(ConverterMessages.Error_UnableToRead()); + return null; + } + } +} diff --git a/developer/src/kmc-convert/src/xkb-to-kmn/xkb-to-kmn-converter.ts b/developer/src/kmc-convert/src/xkb-to-kmn/xkb-to-kmn-converter.ts new file mode 100644 index 00000000000..0722b5cf1d6 --- /dev/null +++ b/developer/src/kmc-convert/src/xkb-to-kmn/xkb-to-kmn-converter.ts @@ -0,0 +1,1040 @@ +/* + * Keyman is copyright (C) SIL Global. MIT License. + * + * Created by S. Schmitt on 2025-05-12 + * + * Convert macOS/Ukelele .keylayout files to Keyman .kmn + * + */ + +import { CompilerCallbacks, CompilerOptions, KeymanCompilerResult, Keylayout } from "@keymanapp/developer-utils"; +import { KmnXKBFileWriter } from './kmnXKB-file-writer.js'; +import { XkbFileReader } from './xkb-file-reader.js'; +import { ConverterMessages } from '../converter-messages.js'; +import { ConverterArtifacts, ConverterToKmnArtifacts } from "../converter-artifacts.js"; + +export interface ConverterResult extends KeymanCompilerResult { + /** + * Internal in-memory build artifacts from a successful compilation. Caller + * can write these to disk with {@link Converter.write} + */ + artifacts: ConverterArtifacts; +}; + +export interface ConverterToKmnResult extends ConverterResult { + /** + * Internal in-memory build artifacts from a successful compilation. Caller + * can write these to disk with {@link Converter.write} + */ + artifacts: ConverterToKmnArtifacts; +}; + +export interface ProcessedData { + /** + * Interface for all data read from a .keylayout file. Also contains all rules processed from input data. + * Data will be used for writing to a .kmn file (e.g. filename, modifier combinations, rules) + */ + keylayoutFilename: string; + kmnFilename: string; + modifiers: string[][]; + rules: Rule[]; +}; + +export interface KeylayoutFileData { + /** + * Interface for storing data read from a .keylayout file and used for processing rules. + * These are used for obtaining one entity form the other (e.g. from action id to output, from keycode to modifier, etc.) + */ + actionId?: string; + keyCode?: string; + key?: string; + behavior?: string; + modifier?: string; + outchar?: string; +}; + +export interface ActionStateOutput { + /** + * Interface for storing data read from a .keylayout file and used for processing rules. + * These are used for obtaining the triplet [action id, state, output] + * e.g. ['a9','1','â'] from for action id a9 + */ + id: string; + state: string; + output: string; +}; + +/** + * @brief class for all storing a rule containing data for key, deadkey, previous deadkey, output) + */ +export class Rule { + constructor( + public readonly ruleType: string, /* C0, C1, C2, C3, or C4 */ + + public readonly modifierPrevDeadkey: string, /* first key used by C3 rules*/ + public readonly prevDeadkey: string, + public idPrevDeadkey: number, + public uniquePrevDeadkey: number, + + public readonly modifierDeadkey: string, /* second key used by C2,C3 rules*/ + public readonly deadkey: string, + public idDeadkey: number, + public uniqueDeadkey: number, + + public readonly modifierKey: string, /* third key used by C0,C1,C2,C3,C4 rules*/ + public readonly key: string, + public readonly output: Uint8Array, /* output used by C0,C1,C2,C3,C4 rules*/ + ) { } + +} + +export class XkbToKmnConverter { + static readonly INPUT_FILE_EXTENSION = '.xkb'; + static readonly OUTPUT_FILE_EXTENSION = '.kmn'; + static readonly SKIP_COMMENTED_LINES = false; + static readonly MAX_CTRL_CHARACTER = 0x20; // the hightest control character we print out as a Unicode CodePoint (U+0020) + static readonly MAX_KEY_IDENTIFIER = 49; // We only use key Nr 0 (A) -> key Nr 49 (Space) + + private options: CompilerOptions; + + constructor(private callbacks: CompilerCallbacks, options: CompilerOptions) { + this.options = { ...options }; + }; + + /** + * @brief member function to run read/convert/write + * @param inputFilename the ukelele .keylayout-file to be converted + * @param outputFilename the resulting keyman .kmn-file + * @return null on success + */ + async run(inputFilename: string, outputFilename?: string): Promise { + console.log("##############################################################\n running XkbToKmnConverter with input file " + + inputFilename + " and output file " + outputFilename); + + if (!inputFilename) { + this.callbacks.reportMessage(ConverterMessages.Error_FileNotFound({ inputFilename })); + return null; + } + + const KeylayoutReader = new XkbFileReader(this.callbacks/*, this.options*/); + + const binaryData = this.callbacks.loadFile(inputFilename); + const jsonO: Keylayout.KeylayoutXMLSourceFile = KeylayoutReader.read(binaryData); + + if (!jsonO) { + this.callbacks.reportMessage(ConverterMessages.Error_UnableToReadFile({ inputFilename: inputFilename })); + return null; + } + try { + if (!KeylayoutReader.validate(jsonO)) { + return null; + } + } catch (e) { + this.callbacks.reportMessage(ConverterMessages.Error_InvalidFile({ errorText: e.toString() })); + return null; + } + + const processedData = await this.convert(jsonO, inputFilename, outputFilename); + const kmnFileWriter = new KmnXKBFileWriter(this.callbacks, this.options); + + // write to object/ConverterToKmnResult + const outputKmn = kmnFileWriter.write(processedData); + const result: ConverterToKmnResult = { + artifacts: { + kmn: { data: outputKmn, filename: processedData.kmnFilename } + } + }; + return result; + } + + /** + * @brief member function to read filename and behaviorof a json object into a ProcessedData + * @param jsonObj containing filename, behaviorand rules of a json object + * @return an ProcessedData containing all data ready to print out + */ + private convert(jsonObj: any, inputfilename: string, outputFilename?: string): ProcessedData { + // modifiers for each behavior + const modifierBehavior: string[][] = []; + + // an array of data for a kmn rule + const rules: Rule[] = []; + + // dataObject for all relevant data + const dataObject: ProcessedData = { + keylayoutFilename: "", + kmnFilename: "", + modifiers: [], + rules: [] + }; + + if ((jsonObj === null) || (!jsonObj.hasOwnProperty("keyboard"))) { + return null; + } + // create an array of modifier combinations and store in dataObject + for (let j = 0; j < jsonObj.keyboard.modifierMap.keyMapSelect.length; j++) { + const singleModifierSet: string[] = []; + for (let k = 0; k < jsonObj.keyboard.modifierMap.keyMapSelect[j].modifier.length; k++) { + singleModifierSet.push(jsonObj.keyboard.modifierMap.keyMapSelect[j].modifier[k]['keys']); + } + modifierBehavior.push(singleModifierSet); + } + + // fill dataObject with filenames, behaviors and (initialized) rules + dataObject.keylayoutFilename = inputfilename; + if (!outputFilename) + dataObject.kmnFilename = inputfilename.replace(/\.keylayout$/, '.kmn'); + else + dataObject.kmnFilename = outputFilename; + dataObject.modifiers = modifierBehavior; // ukelele uses behaviors e.g. 18 modifiersCombinations in 8 KeyMapSelect(behaviors) + dataObject.rules = rules; + + // fill rules into 'rules' of dataObject + return this.createRuleData(dataObject, jsonObj); + } + + /** + * @brief member function to read the rules contained in a json object and add array of Rules[] to an ProcessedData + * @param dataUkelele: an object containing the name of the in/output file, an array of behaviors and an (empty) array of Rules + * @param jsonObj: json Object containing all data read from a keylayout file + * @return an object containing the name of the input file, an array of behaviors and a populated array of Rules[] + */ + public createRuleData(dataUkelele: ProcessedData, jsonObj: any): ProcessedData { + + const rules: Rule[] = []; + let dkCounterC3: number = 0; + let dkCounterC2: number = 0; + let actionId: string; + + // check if we use CAPS in a modifier throughout the .keylayout file. In this case we need to add NCAPS + const isCapsused = (this.checkIfCapsIsUsed(dataUkelele.modifiers)); + + // if there are different amounts of keyMapSelect vs keyMap + if (jsonObj.keyboard.modifierMap?.keyMapSelect.length !== jsonObj.keyboard.keyMapSet[0].keyMap.length) { + const errorText = dataUkelele.keylayoutFilename; + this.callbacks.reportMessage(ConverterMessages.Error_InvalidFile({ errorText })); + return null; + } + + for (let j = 0; j <= XkbToKmnConverter.MAX_KEY_IDENTIFIER; j++) { + + // loop behaviors (in ukelele it is possible to define multiple modifier combinations that behave in the same way) + for (let i = 0; i < jsonObj.keyboard.keyMapSet[0].keyMap.length; i++) { + + // if index of keys and behaviors exist + const isItAvailable = ((j < jsonObj.keyboard.keyMapSet[0].keyMap[i].key.length) && (i < jsonObj.keyboard.keyMapSet[0].keyMap.length)); + if (!isItAvailable) { + continue; + } + + let ruleObj: Rule; + + if (j < jsonObj.keyboard.keyMapSet[0].keyMap[i].key.length) { + // ............................................................................................................................... + // case C0: output ............................................................................................................... + // C0 see: https://docs.google.com/document/d/12J3NGO6RxIthCpZDTR8FYSRjiMgXJDLwPY2z9xqKzJ0/edit?tab=t.0#heading=h.g7jwx3lx0ydd ... + // a key is mapped to a character directly ( code -> output) ..................................................................... + // ...............e. g. ............................................................................... + // ............................................................................................................................... + + if ((jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['output'] !== undefined) + && (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['output'] !== "")) { + + // loop modifiers + for (let l = 0; l < dataUkelele.modifiers[i].length; l++) { + + if (this.mapUkeleleKeycodeToVK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['code']))) { + + ruleObj = new Rule( + /* ruleType */ "C0", + + /* modifierPrevDeadkey*/ "", + /* prevDeadkey */ "", + /* idPrevDeadkey */ 0, + /* unique A */ 0, + + /* modifierDeadkey */ "", + /* deadkey */ "", + /* dk for C2*/ 0, + /* unique B */ 0, + + /* modifierKey*/ this.createKmnModifier(dataUkelele.modifiers[i][l], isCapsused), + /* key */ this.mapUkeleleKeycodeToVK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['code'])), + /* output */ new TextEncoder().encode(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['output']), + ); + rules.push(ruleObj); + } + } + // } + + } + else if (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['action'] !== undefined) { + + actionId = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['action']; + // ............................................................................................................................... + // case C1: action + state none + output ......................................................................................... + // C1 see: https://docs.google.com/document/d/12J3NGO6RxIthCpZDTR8FYSRjiMgXJDLwPY2z9xqKzJ0/edit?tab=t.0#heading=h.g7jwx3lx0ydd ... + // a key is mapped to an action and then to an output ............................................................................ + // KeyMap:code -> KeyMap:action->action:actionState(none) -> actionOutput ...................................................... + // ...............e. g. ............................................................................ + // replace state x with all rules that result in 14 ( for action id a18 ...................................................................................................................... + for (let l = 0; l < jsonObj.keyboard.actions.action[b1ActionIndex].when.length; l++) { + if ((jsonObj.keyboard.actions.action[b1ActionIndex].when[l]['state'] === "none") // find "none" + && (jsonObj.keyboard.actions.action[b1ActionIndex].when[l]['next'] !== undefined)) { // find "next" + + // Data of Block Nr 5 ..................................................................................................................................................................... + // of this state(none)-next-pair get value of next (next="1") ............................................................................................................................. + /* eg: 1 */ const b5ValueNext: string = jsonObj.keyboard.actions.action[b1ActionIndex].when[l]['next']; + // ........................................................................................................................................................................................ + + + // Data of Block Nr 4 ..................................................................................................................................................................... + // with present actionId (a18) find all keycode-behavior-pairs that use this action (a18) => (keymapIndex 0/keycode 24 and keymapIndex 3/keycode 24) .................................... + // from these create an array of modifier combinations e.g. [['','caps?'], ['Caps']] ..................................................................................................... + /* eg: [['24', 0], ['24', 3]] */ const b4DeadkeyObj: KeylayoutFileData[] = this.getKeyModifierArrayFromActionID(jsonObj, actionId); + /* e.g. [['','caps?'], ['Caps']]*/ const b4DeadkeyModifierObj: string[] = this.getModifierArrayFromKeyModifierArray(dataUkelele.modifiers, b4DeadkeyObj); + // ........................................................................................................................................................................................ + + + // Data of Block Nr 6 ..................................................................................................................................................................... + // create an array[action id,state,output] from all state-output-pairs that use state = b5ValueNext (e.g. use 1 in ) ...................................... + /* eg: [ 'a9','1','â'] */ const b6ActionIdObj: ActionStateOutput[] = this.getActionStateOutputArrayFromActionState(jsonObj, b5ValueNext); + // ........................................................................................................................................................................................ + + + // Data of Block Nr 1 .................................................................................................................................................................... + // create array[Keycode,Keyname,action id,actionIndex,output] and array[Keyname,action id,behavior,modifier,output] ...................................................................... + /* eg: ['0','K_A','a9','0','â'] */ const b1KeycodeObj: KeylayoutFileData[] = this.getKeyActionOutputArrayFromActionStateOutputArray(jsonObj, b6ActionIdObj); + /* eg: ['K_A','a9','0','NCAPS','â']*/ const b1ModifierKeyObj: KeylayoutFileData[] = this.getKeyBehaviorModOutputArrayFromKeyActionBehaviorOutputArray(jsonObj, b1KeycodeObj, isCapsused); + // ....................................................................................................................................................................................... + + for (let n1 = 0; n1 < b4DeadkeyModifierObj.length; n1++) { + for (let n2 = 0; n2 < b4DeadkeyModifierObj[n1].length; n2++) { + for (let n3 = 0; n3 < b4DeadkeyObj.length; n3++) { + for (let n4 = 0; n4 < b1ModifierKeyObj.length; n4++) { + + ruleObj = new Rule( + /* ruleType */ "C2", + + /* modifierPrevDeadkey*/ "", + /* prevDeadkey */ "", + /* idPrevDeadkey */ 0, + /* unique A */ 0, + + /* modifierDeadkey */ this.createKmnModifier(b4DeadkeyModifierObj[n1][n2], isCapsused), + /* deadkey */ this.mapUkeleleKeycodeToVK(Number(b4DeadkeyObj[n3].key)), + /* dk for C2*/ dkCounterC2++, + /* unique B */ 0, + + /* modifierKey*/ b1ModifierKeyObj[n4].modifier, + /* key */ b1ModifierKeyObj[n4].key, + /* output */ new TextEncoder().encode(b1ModifierKeyObj[n4].outchar), + ); + if ((b1ModifierKeyObj[n4].outchar !== undefined) + && (b1ModifierKeyObj[n4].outchar !== "undefined") + && (b1ModifierKeyObj[n4].outchar !== "")) { + rules.push(ruleObj); + } + } + } + } + } + } + } + + // ............................................................................................................................... + // case C3: action + state Nr + Next ............................................................................................. + // ...............e. g. ................................................................................ + // replace state x with all rules that result in 1 ( for action id a16 ............................................................................................................................. + for (let l = 0; l < jsonObj.keyboard.actions.action[b1ActionIndex].when.length; l++) { + if ((jsonObj.keyboard.actions.action[b1ActionIndex].when[l]['state'] !== "none") + && (jsonObj.keyboard.actions.action[b1ActionIndex].when[l]['next'] !== undefined)) { + + // Data of Block Nr 5 ........................................................................................................................................................................ + // of this state-next-pair get value of next (next="1") and state="3" ........................................................................................................................ + /* e.g. state = 3 */ const b5ValueState: string = jsonObj.keyboard.actions.action[b1ActionIndex].when[l]['state']; + /* e.g. next = 1 */ const b5ValueNext: string = jsonObj.keyboard.actions.action[b1ActionIndex].when[l]['next']; + // ........................................................................................................................................................................................... + + // Data of Block Nr 4 ........................................................................................................................................................................ + // with present actionId (a16) find all keycode-behavior-pairs that use this action (a16) => (keymapIndex 3/keycode 32) .................................................................... + // from these create an array of modifier combinations e.g. [ [ 'anyOption', 'Caps' ] ] ..................................................................................................... + /* e.g. [['32', 3]] */ const b4DeadkeyObj: KeylayoutFileData[] = this.getKeyModifierArrayFromActionID(jsonObj, actionId); + /* e.g. [ [ 'anyOption', 'Caps' ] ]*/ const b4DeadkeyModifierObj: string[] = this.getModifierArrayFromKeyModifierArray(dataUkelele.modifiers, b4DeadkeyObj); + // ........................................................................................................................................................................................... + + // Data of Block Nr 3 ........................................................................................................................................................................ + // get an action id from a state-output-pair that use state = b5ValueState (e.g. use 3 in ) ................................................................. + /* e.g. actioniD = a17 */ const b3ActionId: string = this.getActionIdFromActionNext(jsonObj, b5ValueState); + // ........................................................................................................................................................................................... + + // Data of Block Nr 2 ....................................................................................................................................................................... + // with present actionId (a17) find all key names and behaviors that use this action (a17) => (keymapIndex 3/keycode 28) .................................................................... + // from these create an array of modifier combinations e.g. [ [ 'anyOption', 'Caps' ] ] ..................................................................................................... + /* eg: index=3 */ const b2PrevDeadkeyObj: KeylayoutFileData[] = this.getKeyModifierArrayFromActionID(jsonObj, b3ActionId); + /* e.g. [ [ 'anyOption', 'Caps' ] ] */ const b2PrevDeadkeyModifierObj: string[] = this.getModifierArrayFromKeyModifierArray(dataUkelele.modifiers, b2PrevDeadkeyObj); + // ........................................................................................................................................................................................... + // Data of Block Nr 6 ........................................................................................................................................................................ + // create an array[action id,state,output] from all state-output-pairs that use state = b5ValueNext (e.g. use 1 in ) ......................................... + /* eg:[ [ 'a9','1','â'] ]*/ const b6ActionIdObj: ActionStateOutput[] = this.getActionStateOutputArrayFromActionState(jsonObj, b5ValueNext); /* eg:[ [ 'a9','1','â'] ]*/ + // ........................................................................................................................................................................................... + + // Data of Block Nr 1 ....................................................................................................................................................................... + // create array[Keycode,Keyname,action id,actionIndex,output] and array[Keyname,action id,behavior,modifier,output] ......................................................................... + /* eg: ['49','K_SPACE','a0','0','Â'] */ const b1KeycodeObj: KeylayoutFileData[] = this.getKeyActionOutputArrayFromActionStateOutputArray(jsonObj, b6ActionIdObj); + /* eg: ['K_SPACE','a0','0','NCAPS','Â'] */ const b1ModifierKeyObj: KeylayoutFileData[] = this.getKeyBehaviorModOutputArrayFromKeyActionBehaviorOutputArray(jsonObj, b1KeycodeObj, isCapsused); + // ........................................................................................................................................................................................... + + for (let n1 = 0; n1 < b2PrevDeadkeyModifierObj.length; n1++) { + for (let n2 = 0; n2 < b2PrevDeadkeyModifierObj[n1].length; n2++) { + for (let n3 = 0; n3 < b2PrevDeadkeyObj.length; n3++) { + for (let n4 = 0; n4 < b4DeadkeyModifierObj.length; n4++) { + for (let n5 = 0; n5 < b4DeadkeyModifierObj[n4].length; n5++) { + for (let n6 = 0; n6 < b4DeadkeyObj.length; n6++) { + for (let n7 = 0; n7 < b1ModifierKeyObj.length; n7++) { + + ruleObj = new Rule( + /* ruleType */ "C3", + /* modifierPrevDeadkey*/ this.createKmnModifier(b2PrevDeadkeyModifierObj[n1][n2], isCapsused), + /* prevDeadkey */ this.mapUkeleleKeycodeToVK(Number(b2PrevDeadkeyObj[n3].key)), + /* idPrevDeadkey */ dkCounterC3++, + /* unique A */ 0, + + /* modifierDeadkey */ this.createKmnModifier(b4DeadkeyModifierObj[n4][n5], isCapsused), + /* deadkey */ this.mapUkeleleKeycodeToVK(Number(b4DeadkeyObj[n6].key)), + /* dk for C2*/ 0, + /* unique B */ 0, + + /* modifierKey*/ b1ModifierKeyObj[n7].modifier, + /* key */ b1ModifierKeyObj[n7].key, + /* output */ new TextEncoder().encode(b1ModifierKeyObj[n7].outchar), + ); + if ((b1ModifierKeyObj[n7].outchar !== undefined) + && (b1ModifierKeyObj[n7].outchar !== "undefined") + && (b1ModifierKeyObj[n7].outchar !== "")) { + rules.push(ruleObj); + } + } + } + } + } + } + } + } + } + } + } + } else { + this.callbacks.reportMessage(ConverterMessages.Error_UnsupportedCharactersDetected({ + inputFilename: jsonObj.keyboard['name'] + ".keylayout", + keymapIndex: jsonObj.keyboard.keyMapSet[0].keyMap[i]['index'], + output: jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['output'], + key: jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['code'], + KeyName: this.mapUkeleleKeycodeToVK(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['code']) + })); + return null; + } + } + } + } + dataUkelele.rules = rules; + return this.reviewRuleInputData(dataUkelele); + } + + /** + * @brief member function to review data in array of rules of dataUkelele: remove duplicate rules and mark first occurance of a rule in rules + * @param dataUkelele: an object containing the name of the in/output file, an array of behaviors and an array of Rules + * @return an object containing the name of the input file, an array of behaviors and the revised array of Rule[] + */ + public reviewRuleInputData(dataUkelele: ProcessedData): ProcessedData { + + // check for duplicate C2 and C3 rules in rules (e.g. [NCAPS RALT K_8] > dk(C12) ): create a separate array of unique rules, + // then compare to rules and mark first occurrence of a rule in rules + + let uniqueCountDkB = 0; + const uniqueTextRules: string[][] = []; + + const rules: Rule[] = dataUkelele.rules; + + //------------------------------------ C2: dk ---------------------------------- + // first rule is always unique + rules[0].uniqueDeadkey = uniqueCountDkB; + rules[0].idDeadkey = uniqueCountDkB; + uniqueCountDkB++; + + for (let i = 0; i < rules.length; i++) { + + + if (((rules[i].modifierDeadkey !== undefined) && (rules[i].modifierDeadkey !== "")) + && ((rules[i].deadkey !== undefined) && (rules[i].deadkey !== ""))) { + let IsFirstUsedHereDk: boolean = true; + + // check if not used before + for (let j = 0; j < i; j++) { + if ((rules[i].modifierDeadkey === rules[j].modifierDeadkey) + && (rules[i].deadkey === rules[j].deadkey)) { + IsFirstUsedHereDk = IsFirstUsedHereDk && false; + } + } + + if (IsFirstUsedHereDk) { + rules[i].uniqueDeadkey = uniqueCountDkB; + uniqueTextRules.push([ + rules[i].modifierDeadkey, + rules[i].deadkey, + String(uniqueCountDkB)]); + uniqueCountDkB++; + } + } + } + + //----------------------------------- C3: prev-dk ---------------------------------- + let uniqueCountDkA = 0; + + // first rule is always unique + rules[0].uniquePrevDeadkey = uniqueCountDkA; + uniqueCountDkA++; + + for (let i = 0; i < rules.length; i++) { + if ((rules[i].modifierPrevDeadkey !== "") && (rules[i].prevDeadkey !== "")) { + let isFirstUsedHerePrevDk: boolean = true; + + // check if not used before + for (let j = 0; j < i; j++) { + if ((rules[i].modifierPrevDeadkey === rules[j].modifierPrevDeadkey) + && (rules[i].prevDeadkey === rules[j].prevDeadkey)) { + isFirstUsedHerePrevDk = isFirstUsedHerePrevDk && false; + } + } + + // check if first part of C3 rule contains a rule that is already defined in C2 + if (isFirstUsedHerePrevDk) { + rules[i].uniquePrevDeadkey = uniqueCountDkA; + uniqueCountDkA++; + for (let k = 0; k < uniqueTextRules.length; k++) { + if ((uniqueTextRules[k][0] === rules[i].modifierDeadkey) && (uniqueTextRules[k][1] === rules[i].deadkey)) { + rules[i].uniqueDeadkey = Number(uniqueTextRules[k][2]); + } + } + } + + if (isFirstUsedHerePrevDk) { + rules[i].uniqueDeadkey = uniqueCountDkB; + uniqueTextRules.push([ + rules[i].modifierPrevDeadkey, + rules[i].prevDeadkey, + String(uniqueCountDkB) + ]); + uniqueCountDkB++; + } + } + } + + // loop through rules and mark first occurence each rule of uniqueTextRules + for (let i = 0; i < rules.length; i++) { + for (let j = 0; j < uniqueTextRules.length; j++) { + if ((rules[i].modifierPrevDeadkey === uniqueTextRules[j][0]) && (rules[i].prevDeadkey === uniqueTextRules[j][1])) { + rules[i].idPrevDeadkey = Number(uniqueTextRules[j][2]); + } + if ((rules[i].modifierDeadkey === uniqueTextRules[j][0]) && (rules[i].deadkey === uniqueTextRules[j][1])) { + rules[i].idDeadkey = Number(uniqueTextRules[j][2]); + } + } + } + dataUkelele.rules = rules; + return dataUkelele; + } + + /** + * @brief member function to create a kmn modifier from a keylayout modifier + * @param keylayoutModifier :string - modifier used in a .keylayout file + * @param isCAPSused : boolean flag to indicate if CAPS is used in a keylayout file or not + * @return string - a modifier value suitable for use in a .kmn-file + */ + public createKmnModifier(keylayoutModifier: string, isCAPSused: boolean): string { + + const kmnModifier: string[] = []; + const modifierState = keylayoutModifier.split(" "); + + for (const modifier of modifierState) { + const modifierUppercase = modifier.toUpperCase(); + + if (isCAPSused && (keylayoutModifier).toUpperCase().indexOf("CAPS?") > 0) { + kmnModifier.push("NCAPS"); + } + if (isCAPSused && (keylayoutModifier).toUpperCase().indexOf("CAPS") === -1) { + kmnModifier.push("NCAPS"); + } + + // if we find a modifier containing a '?' e.g. SHIFT? it means the modifier is not necessary. + // If it is not necessary we don't write this modifier + if (modifierUppercase.includes('?') && modifierUppercase !== 'CAPS?') { + kmnModifier.push(""); + } + // if we find 'caps?' => caps is not necessary. + // If caps is not necessary and isCAPSused we need to write out NCAPS. + else if (isCAPSused && modifierUppercase === 'CAPS?') { + kmnModifier.push("NCAPS"); + } + else if (!isCAPSused && modifierUppercase === 'CAPS?') { + kmnModifier.push(""); + } + else if (modifierUppercase === 'CAPS' || modifierUppercase === 'CAPS?') { + kmnModifier.push("CAPS"); + } + else if (isCAPSused && (modifierUppercase === 'NCAPS')) { + kmnModifier.push("NCAPS"); + } + else if (modifierUppercase === 'ANYSHIFT' || modifierUppercase === 'SHIFT') { + kmnModifier.push("SHIFT"); + } + else if (modifierUppercase === "LEFTSHIFT" || modifierUppercase === "LSHIFT") { + kmnModifier.push("SHIFT"); + } + else if (modifierUppercase === "RIGHTSHIFT" || modifierUppercase === "RSHIFT") { + kmnModifier.push("SHIFT"); + } + else if (modifierUppercase === 'ANYCONTROL' || modifierUppercase === 'CONTROL') { + kmnModifier.push("CTRL"); + } + else if (modifierUppercase === "LEFTCONTROL" || modifierUppercase === "LCONTROL") { + kmnModifier.push("LCTRL"); + } + else if (modifierUppercase === "RIGHTCONTROL" || modifierUppercase === "RCONTROL") { + kmnModifier.push("RCTRL"); + } + else if (modifierUppercase === "LEFTOPTION" || modifierUppercase === "LOPTION") { + kmnModifier.push("LALT"); + } + else if (modifierUppercase === "RIGHTOPTION" || modifierUppercase === "ROPTION") { + kmnModifier.push("RALT"); + } + else if (modifierUppercase === 'ANYOPTION' || modifierUppercase === 'OPTION') { + kmnModifier.push("RALT"); + } + // to enable the use of other modifiers (leave upper/lowecase as in .keylayout) + // e.g. 'shift command' -> 'NCAPS SHIFT command'; 'wrongModifierName' -> 'wrongModifierName' + else { + if (!this.isAcceptableKeymanModifier(modifier)) + kmnModifier.push(modifier); + } + } + + // remove duplicate and empty entries and make sure NCAPS is at the beginning + const uniqueModifier: string[] = kmnModifier.filter(function (item, pos, self) { + return ((self.indexOf(item) === pos) && (item !== "")); + }); + + return uniqueModifier.flat().toString().replace(/,/g, " "); + } + + /** + * @brief member function to check if CAPS is used throughout a keylayout file or not + * @param keylayoutModifier the modifier string used in the .keylayout-file + * @return "caps" or undefined if "caps" is not found + */ + public checkIfCapsIsUsed(keylayoutModifier: string[][]): boolean { + if (!keylayoutModifier) + return false; + // make sure we always have a whitespace before and after each modifier( to distinguish from caps? ) + return (" " + keylayoutModifier.flat().join(" ").toUpperCase() + " ").indexOf(" CAPS ") >= 0; + } + + /** + * @brief member function to check if a modifier can be used in Keyman + * @param keylayoutModifier the modifier string used in the .keylayout-file + * @return true if the modifier can be used in keyman; false if not + */ + public isAcceptableKeymanModifier(keylayoutModifier: string): boolean { + if (keylayoutModifier === null) + return false; + const modifierSingle = keylayoutModifier.toUpperCase().split(" "); + for (const mod of modifierSingle) { + if (!mod.match(/^(NCAPS|CAPS|SHIFT|ALT|RALT|LALT|CTRL|LCTRL|RCTRL|)$/)) { + return false; + } + } + return true; + } + + /** + * @brief member function to map Ukelele keycodes to Windows Keycodes + * @param pos Ukelele (=mac) keycodes + * @return VK + */ + public mapUkeleleKeycodeToVK(pos: number): string { + const vk = [ + "K_A" /* A */, + "K_S" /* S */, + "K_D" /* D */, + "K_F" /* F */, + "K_H" /* H */, + "K_G" /* G */, + "K_Z" /* Z */, + "K_X" /* X */, + "K_C" /* C */, + "K_V" /* V */, + "K_BKQUOTE" /* ^ */, + "K_B" /* B */, + "K_Q" /* Q */, + "K_W" /* W */, + "K_E" /* E */, + "K_R" /* R */, + "K_Y" /* Y */, + "K_T" /* T */, + "K_1" /* 1 */, + "K_2" /* 2 */, + "K_3" /* 3 */, + "K_4" /* 4 */, + "K_6" /* 6 */, + "K_5" /* 5 */, + "K_EQUAL" /* ´ */, + "K_9" /* 9 */, + "K_7" /* 7 */, + "K_HYPHEN" /* ß */, + "K_8" /* 8 */, + "K_0" /* 0 */, + "K_RBRKT" /* ] */, + "K_O" /* O */, + "K_U" /* U */, + "K_LBRKT" /* [ */, + "K_I" /* I */, + "K_P" /* P */, + "K_ENTER", + "K_L" /* L */, + "K_J" /* J */, + "K_QUOTE" /* " */, + "K_K" /* K */, + "K_COLON" /* : */, + "K_BKSLASH" /* \ */, // 42 for ISO correct?? + "K_COMMA" /* , */, + "K_SLASH" /* / */, + "K_N" /* N */, + "K_M" /* M */, + "K_PERIOD" /* . */, + "K_oE2" /* \ */, // 48 for ANSI correct?? + "K_SPACE" /* \ */ + ]; + + if (!(pos >= 0 && pos <= 0x31) || (pos === null) || (pos === undefined)) { + return ""; + } else { + return vk[pos]; + } + } + + /** + * @brief member function to return an index for a given actionID + * @param data :any - an object containing all data read from a .keylayout file + * @param search :string - value 'id' to be found + * @return a number specifying the index of an actionId + */ + public getActionIndexFromActionId(data: any, search: string): number { + for (let i = 0; i < data.keyboard.actions.action.length; i++) { + if (data.keyboard.actions.action[i]['id'] === search) { + return i; + } + } + return -1; + } + + /** + * @brief member function to find the actionID of a certain state-next pair + * @param data :any an object containing all data read from a .keylayout file + * @param search :string value 'next' to be found + * @return a string containing the actionId of a certain state(none)-next pair + */ + public getActionIdFromActionNext(data: any, search: string): string { + if (search !== "none") { + for (let i = 0; i < data.keyboard.actions.action.length; i++) { + for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { + if (data.keyboard.actions.action[i].when[j]['next'] === search) { + return data.keyboard.actions.action[i]['id']; + } + } + } + } + return ""; + } + + /** + * @brief member function to create an array of (modifier) behaviors for a given keycode in [{keycode,modifier}] + * @param data : any - an object containing all data read from a .keylayout file + * @param search : KeylayoutFileData[] - an array[{keycode,modifier}] to be found + * @return a string[] containing modifiers + */ + public getModifierArrayFromKeyModifierArray(data: any, search: KeylayoutFileData[]): string[] { + const returnString1D: string[] = []; + for (let i = 0; i < search.length; i++) { + returnString1D.push(data[search[i].behavior]); + } + return returnString1D; + } + + + /** + * @brief member function to find the output for a certain actionID for state 'none' + * @param data :any an object containing all data read from a .keylayout file + * @param search :string an actionId to be found + * @return a string containing the output character + */ + public getOutputFromActionIdNone(data: any, search: string): string { + let OutputValue: string = ""; + for (let i = 0; i < data.keyboard.actions.action.length; i++) { + if (data.keyboard.actions.action[i]['id'] === search) { + for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { + if (data.keyboard.actions.action[i].when[j]['state'] === "none") { + if (data.keyboard.actions.action[i].when[j]['output'] !== undefined) { + OutputValue = data.keyboard.actions.action[i].when[j]['output']; + } + } + } + } + } + return OutputValue; + } + + /** + * @brief member function to return array of [Keycode,Keyname,actionId,actionIDIndex, output] for a given actionID in of [ actionID,state,output] + * @param data :any - an object containing all data read from a .keylayout file + * @param search :idStateOutputObject[] - array of [{ actionID,state,output }] + * @return a KeylayoutFileData[] containing [{Keycode,Keyname,actionId,actionID, output}] + */ + public getKeyActionOutputArrayFromActionStateOutputArray(data: any, search: ActionStateOutput[]): KeylayoutFileData[] { + + if ((search === undefined) || (search === null)) + return []; + + const keyActionOutput = []; + + for (let k = 0; k < search.length; k++) { + for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { + for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { + if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['action'] === search[k].id && + data.keyboard.keyMapSet[0].keyMap[i].key[j]['code'] <= XkbToKmnConverter.MAX_KEY_IDENTIFIER) { + const singleDataSet = { + keyCode: data.keyboard.keyMapSet[0].keyMap[i].key[j]['code'], + key: this.mapUkeleleKeycodeToVK(Number(data.keyboard.keyMapSet[0].keyMap[i].key[j]['code'])), + actionId: data.keyboard.keyMapSet[0].keyMap[i].key[j]['action'], + behavior: data.keyboard.keyMapSet[0].keyMap[i]['index'], + outchar: search[k].output + }; + keyActionOutput.push(singleDataSet); + } + } + } + } + return keyActionOutput; + } + + /** + * @brief member function to get an array of all actionId-output pairs for a certain state + * @param data : any an object containing all data read from a .keylayout file + * @param search : string a 'state' to be found + * @return an array: idStateOutputObject[] containing all [{actionId, state, output}] for a certain state + */ + public getActionStateOutputArrayFromActionState(data: any, search: string): ActionStateOutput[] { + const actionStateOutput: ActionStateOutput[] = []; + + for (let i = 0; i < data.keyboard.actions.action.length; i++) { + for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { + if (data.keyboard.actions.action[i].when[j]['state'] === search) { + if (data.keyboard.actions.action[i].when[j]['output'] !== undefined) { + const singleDataSet = { + id: data.keyboard.actions.action[i]['id'], + state: data.keyboard.actions.action[i].when[j]['state'], + output: data.keyboard.actions.action[i].when[j]['output'] + }; + actionStateOutput.push(singleDataSet); + } + } + } + } + return actionStateOutput; + } + + /** + * @brief member function to create an 2D array of [KeyName,actionId,behavior,modifier,output] + * @param data : any an object containing all data read from a .keylayout file + * @param search : array of [{keycode,keyname,actionId,behavior,output}] to be found + * @param isCAPSused : boolean flag to indicate if CAPS is used in a keylayout file or not + * @return an array: KeylayoutFileData[] containing [{KeyName,actionId,behavior,modifier,output}] + */ + public getKeyBehaviorModOutputArrayFromKeyActionBehaviorOutputArray(data: any, search: KeylayoutFileData[], isCAPSused: boolean): KeylayoutFileData[] { + const keyBehaviorModOutput = []; + if (!((search === undefined) || (search === null) || (search.length === 0))) { + for (let i = 0; i < search.length; i++) { + const behaviorIdx: number = Number(search[i].behavior); + for (let j = 0; j < data.keyboard.modifierMap.keyMapSelect[behaviorIdx].modifier.length; j++) { + const singleDataSet = { + actionId: search[i].actionId, + key: search[i].key, + behavior: search[i].behavior, + modifier: this.createKmnModifier(data.keyboard.modifierMap.keyMapSelect[behaviorIdx].modifier[j]['keys'], isCAPSused), + outchar: search[i].outchar, + }; + keyBehaviorModOutput.push(singleDataSet); + } + } + } + // remove duplicates + const uniquekeyBehaviorModOutput = keyBehaviorModOutput.reduce((unique, o) => { + if (!unique.some(obj => + obj.actionId === o.actionId && + obj.key === o.key && + obj.behavior === o.behavior && + obj.modifier === o.modifier && + obj.outchar === o.outchar + )) { + unique.push(o); + } + return unique; + }, []); + return uniquekeyBehaviorModOutput; + } + + /** + * @brief member function to create an array of [actionID, output, behavior,keyname,modifier] for a given actionId + * @param data : any - an object containing all data read from a .keylayout file + * @param modi : any - an array of modifiers + * @param search : string - an actionId to be found + * @param outchar : string - the output character + * @param isCAPSused : boolean - flag to indicate if CAPS is used in a keylayout file or not + * @return an array: KeylayoutFileData[] containing [{actionID,output, behavior,keyname,modifier}] + */ + public getActionOutputBehaviorKeyModiFromActionIDStateOutput(data: any, modi: string[][], search: string, outchar: string, isCapsused: boolean): KeylayoutFileData[] { + const actionOutputBehaviorKeyModi = []; + if ((!modi) || (search === "") || (search === undefined)) { + return []; + } + // loop behaviors (in ukelele it is possible to define multiple modifier combinations that behave in the same way) + for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { + for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { + if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['action'] === search) { + for (let k = 0; k < modi[data.keyboard.keyMapSet[0].keyMap[i]['index']].length; k++) { + const behaviorIdx: number = data.keyboard.keyMapSet[0].keyMap[i]['index']; + const singleDataSet = { + outchar: outchar, + actionId: data.keyboard.keyMapSet[0].keyMap[i].key[j]['action'], + behavior: data.keyboard.keyMapSet[0].keyMap[i]['index'], + key: this.mapUkeleleKeycodeToVK(Number(data.keyboard.keyMapSet[0].keyMap[i].key[j]['code'])), + modifier: this.createKmnModifier(modi[behaviorIdx][k], isCapsused), + }; + actionOutputBehaviorKeyModi.push(singleDataSet); + } + } + } + } + + //............................................................................. + + // remove duplicates + const uniqueactionOutputBehaviorKey = actionOutputBehaviorKeyModi.reduce((unique, o) => { + if (!unique.some(obj => + obj.outchar === o.outchar && + obj.actionId === o.actionId && + obj.behavior === o.behavior && + obj.key === o.key && + obj.modifier === o.modifier + )) { + unique.push(o); + } + return unique; + }, []); + + return uniqueactionOutputBehaviorKey; + } + + /** + * @brief member function to create an array of [{keycode,behavior}] for a given actionId + * @param data : any - an object containing all data read from a .keylayout file + * @param search : string - an actionId to be found + * @return an array: KeylayoutFileData[] containing [{keycode,behavior}] + */ + public getKeyModifierArrayFromActionID(data: any, search: string): KeylayoutFileData[] { + const mapIndexObject1D: KeylayoutFileData[] = []; + for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { + for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { + if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['action'] === search) { + const singleDataSet = { + key: data.keyboard.keyMapSet[0].keyMap[i].key[j]['code'], + behavior: String(i), + }; + mapIndexObject1D.push(singleDataSet); + } + } + } + return mapIndexObject1D; + } + + /** @internal */ + public convertBound = { + convert: this.convert.bind(this), + }; +} + diff --git a/developer/src/kmc-convert/test/data/Test.xkb b/developer/src/kmc-convert/test/data/Test.xkb new file mode 100644 index 00000000000..76fd91b4db6 --- /dev/null +++ b/developer/src/kmc-convert/test/data/Test.xkb @@ -0,0 +1,596 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts index 0eb23c88b46..e7adb37f759 100644 --- a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts +++ b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts @@ -70,21 +70,96 @@ describe('KmnFileWriter', function () { describe('convertToUnicodeCharacter ', function () { const sutW = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); [ + + ["<", '<'], + ["a", 'a'], + ["ሴ", 'ሴ'], + ["W̊", "W̊"], + ['😎', '😎'], + ["ab", 'ab'], + ["ሴЖ", 'ሴЖ'], + ["ẘẈ", "ẘẈ"], + ["😎😆", '😎😆'], + ["aሴ😆", 'aሴ😆'], + /* + ["U+0061", 'a'], + ["U+1234", 'ሴ'], + ["U+1E9A", "ẚ"], + ["U+1F60A", '😊'], + ["U+0001", '\u0001'], + ["U+1000000;", undefined], + */ + ["a", 'a'], + ["ሴ", 'ሴ'], + ["ẘ", "ẘ"], + ["😏", '😏'], + ["", '\u0002'], + ["�", undefined], + ["a", 'a'], + ["ሴ", 'ሴ'], + ["ẛ", "ẛ"], + ["😆", '😆'], + ["", '\u0003'], + ["󴉀", '󴉀'], + ["@", undefined], + [">", '>'], + ["<", '<'], + [""", '"'], + ["'", "'"], + [">", undefined], + ["␤", '␤'], + ["␕", '␕'], + ["", ''], + ["", ''], + [undefined, undefined], + [null, undefined], + /* + ["U+", undefined], + ['U+', undefined], + ['U+U+', undefined], + ['U+D799', '힙'], + ['U+D800', undefined], + ['U+D83D', undefined], + ['U+DFFF', undefined], + ['U+10FFFF', '􏿿'], + ['U+E000', ''], + ['U+1000000', undefined], + */ + ['&', '&'], + ['&;', '&;'], + ['&&', '&&'], + ['&&;', '&&;'], + ["&#&#", undefined], + ["&#x&#x", undefined], + ["&#", undefined], + ["&#;", undefined], + ["&#x", undefined], + ["&#x;", undefined], + ['&##', undefined], + ['&##;', undefined], + ["􏿿", "􏿿"], + ["􏿿", "􏿿"], + ["�", undefined], + ["�", undefined], + ['Ӓ56', undefined], + +//.................................................................. + ["a", 'a'], ["ሴ", 'ሴ'], ["😎", '😎'], ["", '\u0002'], - ["�",undefined ], + ["�", undefined], ["a", 'a'], ["ሴ", 'ሴ'], ["😆", '😆'], ["", '\u0003'], ["󴉀", '󴉀'], - ["U+0061", 'a'], + /*["U+0061", 'a'], ["U+1234", 'ሴ'], ["U+1F60E", '😎'], ["U+0001", '\u0001'], - ["U+1000000;", undefined], + ["U+1000000;", undefined],*/ ["@", undefined], ["a", 'a'], ["ሴ", 'ሴ'], diff --git a/developer/src/kmc-convert/test/kmnXKB-file-writer.tests.ts b/developer/src/kmc-convert/test/kmnXKB-file-writer.tests.ts new file mode 100644 index 00000000000..d2ecf597c45 --- /dev/null +++ b/developer/src/kmc-convert/test/kmnXKB-file-writer.tests.ts @@ -0,0 +1,524 @@ +/* + * Keyman is copyright (C) SIL Global. MIT License. + * + * Created by S. Schmitt on 2025-05-12 + * + * Tests for XkbToKmnConverter, XkbFileReader, KmnXKBFileWriter + * + */ + +import 'mocha'; +import { assert } from 'chai'; +import KEYMAN_VERSION from "@keymanapp/keyman-version"; +import { compilerTestCallbacks, compilerTestOptions, makePathToFixture } from './helpers/index.js'; +import { XkbToKmnConverter, ProcessedData, Rule } from '../src/xkb-to-kmn/xkb-to-kmn-converter.js'; +import { KmnXKBFileWriter } from '../src/xkb-to-kmn/kmnXKB-file-writer.js'; +import { XkbFileReader } from '../src/xkb-to-kmn/xkb-file-reader.js'; + +describe('KmnXKBFileWriter', function () { + + before(function () { + compilerTestCallbacks.clear(); + }); + + describe("writeDataRules() ", function () { + const inputFilename = makePathToFixture('../data/Test.xkb'); + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sutR = new XkbFileReader(compilerTestCallbacks); + const sutW = new KmnXKBFileWriter(compilerTestCallbacks, compilerTestOptions); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + const converted = sut.convertBound.convert(read, inputFilename.replace(/\.xkb$/, '.kmn')); + + it('writeDataRules() should return true (no error) if written', async function () { + const result = sutW.writeDataRules(converted); + assert.isTrue(result.length > 0); + }); + + }); + + describe("writeKmnFileHeader() ", function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sutR = new XkbFileReader(compilerTestCallbacks); + const sutW = new KmnXKBFileWriter(compilerTestCallbacks, compilerTestOptions); + const inputFilename = makePathToFixture('../data/Test.xkb'); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + const converted = sut.convertBound.convert(read, inputFilename.replace(/\.xkb$/, '.kmn')); + + const outExpectedFirst: string = + "c ..................................................................................................................\n" + + "c ..................................................................................................................\n" + + "c Keyman keyboard generated by kmn-convert version: " + KEYMAN_VERSION.VERSION + "\n" + + "c from Ukelele file: "; + + const outExpectedLast: string = + "\n" + + "c ..................................................................................................................\n" + + "c ..................................................................................................................\n" + + "\n" + + "store(&TARGETS) 'desktop'\n" + + "\n" + + "begin Unicode > use(main)\n\n" + + "group(main) using keys\n\n" + + "\n"; + + it(('writeKmnFileHeader should return store text with filename ').padEnd(62, " ") + 'on correct input', async function () { + const writtenCorrectName = sutW.writeKmnFileHeader(converted); + assert.equal(writtenCorrectName, (outExpectedFirst + converted.keylayoutFilename + outExpectedLast)); + }); + }); + + describe('convertToUnicodeCharacter ', function () { + const sutW = new KmnXKBFileWriter(compilerTestCallbacks, compilerTestOptions); + [ + + ["<", '<'], + ["a", 'a'], + ["ሴ", 'ሴ'], + ["W̊", "W̊"], + ['😎', '😎'], + ["ab", 'ab'], + ["ሴЖ", 'ሴЖ'], + ["ẘẈ", "ẘẈ"], + ["😎😆", '😎😆'], + ["aሴ😆", 'aሴ😆'], + /* + ["U+0061", 'a'], + ["U+1234", 'ሴ'], + ["U+1E9A", "ẚ"], + ["U+1F60A", '😊'], + ["U+0001", '\u0001'], + ["U+1000000;", undefined], + */ + ["a", 'a'], + ["ሴ", 'ሴ'], + ["ẘ", "ẘ"], + ["😏", '😏'], + ["", '\u0002'], + ["�", undefined], + ["a", 'a'], + ["ሴ", 'ሴ'], + ["ẛ", "ẛ"], + ["😆", '😆'], + ["", '\u0003'], + ["󴉀", '󴉀'], + ["@", undefined], + [">", '>'], + ["<", '<'], + [""", '"'], + ["'", "'"], + [">", undefined], + ["␤", '␤'], + ["␕", '␕'], + ["", ''], + ["", ''], + [undefined, undefined], + [null, undefined], + /* + ["U+", undefined], + ['U+', undefined], + ['U+U+', undefined], + ['U+D799', '힙'], + ['U+D800', undefined], + ['U+D83D', undefined], + ['U+DFFF', undefined], + ['U+10FFFF', '􏿿'], + ['U+E000', ''], + ['U+1000000', undefined], + */ + ['&', '&'], + ['&;', '&;'], + ['&&', '&&'], + ['&&;', '&&;'], + ["&#&#", undefined], + ["&#x&#x", undefined], + ["&#", undefined], + ["&#;", undefined], + ["&#x", undefined], + ["&#x;", undefined], + ['&##', undefined], + ['&##;', undefined], + ["􏿿", "􏿿"], + ["􏿿", "􏿿"], + ["�", undefined], + ["�", undefined], + ['Ӓ56', undefined], + +//.................................................................. + + ["a", 'a'], + ["ሴ", 'ሴ'], + ["😎", '😎'], + ["", '\u0002'], + ["�", undefined], + ["a", 'a'], + ["ሴ", 'ሴ'], + ["😆", '😆'], + ["", '\u0003'], + ["󴉀", '󴉀'], + /*["U+0061", 'a'], + ["U+1234", 'ሴ'], + ["U+1F60E", '😎'], + ["U+0001", '\u0001'], + ["U+1000000;", undefined],*/ + ["@", undefined], + ["a", 'a'], + ["ሴ", 'ሴ'], + ['😎', '😎'], + ["W̊", "W̊"], + ["ab", 'ab'], + ["", ''], + ["␤", '␤'], + ["␕", '␕'], + ["", ''], + [undefined, undefined], + [null, undefined] + ].forEach(function (values) { + it(('should convert "' + values[0] + '"').padEnd(25, " ") + 'to "' + values[1] + '"', async function () { + const result = sutW.convertToUnicodeCharacter(values[0] as string); + assert.equal(result, values[1]); + }); + }); + }); + + describe('reviewRules messages', function () { + const sutW = new KmnXKBFileWriter(compilerTestCallbacks, compilerTestOptions); + [ + [[new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'UNAVAILABLE', 'K_A', new TextEncoder().encode('A'))], + [''], + [''], + ['c WARNING: unavailable modifier : here: ']], + + [[new Rule("C1", '', '', 0, 0, 'CAPS', 'K_EQUAL', 0, 0, 'UNAVAILABLE', 'K_B', new TextEncoder().encode('B'))], + [''], + [''], + ['c WARNING: unavailable modifier : here: ']], + + [[new Rule("C2", '', '', 0, 0, 'CAPS', 'K_EQUAL', 0, 0, 'UNAVAILABLE', 'K_C', new TextEncoder().encode('C'),)], + [''], + [''], + ['c WARNING: unavailable modifier : here: ']], + + [[new Rule("C2", '', '', 0, 0, 'UNAVAILABLE_dk', 'K_EQUAL', 0, 0, 'UNAVAILABLE', 'K_C', new TextEncoder().encode('C'),)], + [''], + ['c WARNING: unavailable modifier : here: '], + ['c WARNING: unavailable modifier : here: ']], + + [[new Rule("C3", 'UNAVAILABLE_prev_dk', 'K_D', 0, 0, 'UNAVAILABLE_dk', 'K_EQUAL', 0, 0, 'SHIFT', 'K_C', new TextEncoder().encode('D'),)], + ['c WARNING: unavailable modifier : here: '], + ['c WARNING: unavailable modifier : here: '], + ['c WARNING: unavailable superior rule ( [UNAVAILABLE_dk K_EQUAL] > dk(B0) ) : here: ']], + + [[new Rule("C3", 'UNAVAILABLE_prev_dk', 'K_D', 0, 0, 'UNAVAILABLE_dk', 'K_EQUAL', 0, 0, 'UNAVAIL', 'K_C', new TextEncoder().encode('D'),)], + ['c WARNING: unavailable modifier : here: '], + ['c WARNING: unavailable modifier : here: '], + ['c WARNING: unavailable modifier : here: ']], + + [[new Rule("C3", 'CAPS', 'K_D', 0, 0, 'RALT', 'K_EQUAL', 0, 0, 'SHIFT', 'K_C', new TextEncoder().encode('D'),)], + [''], + [''], + ['']], + + [[new Rule("C3", 'X', 'K_X', 0, 0, 'Y', 'K_Y', 0, 0, 'SHIFT', 'K_Z', new TextEncoder().encode('D'),)], + ['c WARNING: unavailable modifier : here: '], + ['c WARNING: unavailable modifier : here: '], + ['c WARNING: unavailable superior rule ( [Y K_Y] > dk(B0) ) : here: ']], + + ].forEach(function (values: any, index: number) { + it(('rule " ' + values[0][0].ruleType + ' "') + 'should create "' + values[1] + ' | ' + values[2] + ' | ' + values[3] + '"', async function () { + const result: string[] = sutW.reviewRules(values[0], 0); + assert.equal(result[0], values[1][0]); + assert.equal(result[1], values[2][0]); + assert.equal(result[2], values[3][0]); + }); + }); + }); + + describe('reviewRules messages duplicate and ambiguous', function () { + const sutW = new KmnXKBFileWriter(compilerTestCallbacks, compilerTestOptions); + [ + //all + [[ + new Rule("C3", 'LALT', 'K_A', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), + new Rule("C3", 'LALT', 'K_A', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')),], + ['c WARNING: duplicate rule: earlier: [LALT K_A] > dk(C0) here: '], + ["c WARNING: duplicate rule: earlier: dk(B0) + [SHIFT K_B] > dk(B0) here: "], + ["c WARNING: duplicate rule: earlier: dk(B0) + [CAPS K_C] > 'X' here: "]], + + //6-6 dup + [[ + new Rule("C3", 'LALT', 'K_A', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), + new Rule("C3", 'CTRL', 'K_D', 0, 0, 'NCAPS', 'K_E', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')),], + [''], + [""], + ["c WARNING: duplicate rule: earlier: dk(B0) + [CAPS K_C] > 'X' here: "]], + + //6-6 amb + [[ + new Rule("C3", 'LALT', 'K_A', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), + new Rule("C3", 'CTRL', 'K_D', 0, 0, 'NCAPS', 'K_E', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('Y')),], + [''], + [""], + ["c WARNING: ambiguous rule: earlier: dk(B0) + [CAPS K_C] > 'X' here: "]], + + // 5-5 amb + [[ + new Rule("C3", 'LALT', 'K_A', 0, 0, 'NCAPS', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), + new Rule("C3", 'LALT', 'K_A', 0, 0, 'NCAPS', 'K_B', 0, 1, 'RALT', 'K_F', new TextEncoder().encode('X')),], + ['c WARNING: duplicate rule: earlier: [LALT K_A] > dk(C0) here: '], + ["c WARNING: ambiguous rule: earlier: dk(B0) + [NCAPS K_B] > dk(B0) here: "], [''], + ], + + // 5-5 dup + [[ + new Rule("C3", 'LALT', 'K_A', 0, 0, 'NCAPS', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), + new Rule("C3", 'LALT', 'K_A', 0, 0, 'NCAPS', 'K_B', 0, 0, 'RALT', 'K_F', new TextEncoder().encode('X')),], + ['c WARNING: duplicate rule: earlier: [LALT K_A] > dk(C0) here: '], + ["c WARNING: duplicate rule: earlier: dk(B0) + [NCAPS K_B] > dk(B0) here: "], + ['']], + + // 4-2 amb + [[ + new Rule("C3", 'LALT', 'K_A', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), + new Rule("C2", '', '', 0, 0, 'LALT', 'K_A', 0, 0, 'RALT', 'K_F', new TextEncoder().encode('X')),], + ['c WARNING: ambiguous rule: later: [LALT K_A] > dk(C0) here: '], + [''], + ['']], + + // 4-4 amb + [[ + new Rule("C3", 'LALT', 'K_A', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), + new Rule("C3", 'LALT', 'K_A', 1, 1, 'NCAPS', 'K_E', 0, 0, 'RALT', 'K_F', new TextEncoder().encode('Y')),], + ['c WARNING: ambiguous rule: earlier: [LALT K_A] > dk(C0) here: '], + [""], + [''],], + + // 4-4 dup + [[ + new Rule("C3", 'LALT', 'K_A', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), + new Rule("C3", 'LALT', 'K_A', 0, 0, 'NCAPS', 'K_E', 0, 0, 'RALT', 'K_F', new TextEncoder().encode('X')),], + ['c WARNING: duplicate rule: earlier: [LALT K_A] > dk(C0) here: '], + [''], + ['']], + + // 4-2 amb + [[ + new Rule("C3", 'LALT', 'K_A', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), + new Rule("C2", '', '', 0, 0, 'LALT', 'K_A', 0, 0, 'RALT', 'K_F', new TextEncoder().encode('Y')),], + ['c WARNING: ambiguous rule: later: [LALT K_A] > dk(C0) here: '], + [''], + ['']], + + // 6-3 dup + [[ + new Rule("C2", '', '', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), + new Rule("C3", 'CTRL', 'K_D', 0, 0, 'NCAPS', 'K_E', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')),], + [''], + ["c WARNING: duplicate rule: earlier: dk(C0) + [CAPS K_C] > 'X' here: "], + [''],], + + // 6-3 amb + [[ + new Rule("C2", '', '', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), + new Rule("C3", 'CTRL', 'K_D', 0, 0, 'NCAPS', 'K_E', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('Y')),], + [''], + ["c WARNING: ambiguous rule: earlier: dk(C0) + [CAPS K_C] > 'X' here: "], + [''],], + + // 2-4 amb + [[ + new Rule("C2", '', '', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), + new Rule("C3", 'SHIFT', 'K_B', 0, 0, 'NCAPS', 'K_E', 0, 0, 'RALT', 'K_F', new TextEncoder().encode('Y')),], + ['c WARNING: ambiguous rule: earlier: [SHIFT K_B] > dk(A0) here: '], + [''], + ['']], + + //2-2 amb + [[ + new Rule("C2", '', '', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), + new Rule("C2", '', '', 0, 0, 'SHIFT', 'K_B', 1, 1, 'RALT', 'K_F', new TextEncoder().encode('Y')),], + [''], + ['c WARNING: ambiguous rule: earlier: [SHIFT K_B] > dk(C0) here: '], + ['']], + + // 2-2 dup + [[ + new Rule("C2", '', '', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), + new Rule("C2", '', '', 0, 0, 'SHIFT', 'K_B', 0, 0, 'RALT', 'K_F', new TextEncoder().encode('Y')),], + [''], + ['c WARNING: duplicate rule: earlier: [SHIFT K_B] > dk(C0) here: '], + ['']], + + // 3-3 dup + [[ + new Rule("C2", '', '', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), + new Rule("C2", '', '', 0, 0, 'NCAPS', 'K_E', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')),], + [''], + [''], + ["c WARNING: duplicate rule: earlier: dk(A0) + [CAPS K_C] > 'X' here: "]], + + // 3-3 amb + [[ + new Rule("C2", '', '', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), + new Rule("C2", '', '', 0, 0, 'NCAPS', 'K_E', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('Y')),], + [''], + [''], + ["c WARNING: ambiguous rule: earlier: dk(A0) + [CAPS K_C] > 'X' here: "]], + + // 2-1 amb + [[ + new Rule("C2", '', '', 0, 0, 'RALT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), + new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'RALT', 'K_B', new TextEncoder().encode('Y'))], + [''], + [''], + ['c WARNING: ambiguous rule: later: [RALT K_B] > dk(A0) here: ']], + + // 1-1 amb + [[ + new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), + new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('Y'))], + [''], + [''], + ["c WARNING: ambiguous rule: earlier: [CAPS K_C] > 'X' here: "]], + + // 1-1 amb + [[ + new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), + new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X'))], + [''], + [''], + ["c WARNING: duplicate rule: earlier: [CAPS K_C] > 'X' here: "]], + + ].forEach(function (values: any, index: number) { + it('rule ' + values[0][0].ruleType + ' should create " ' + ' "' + values[1] + ' | ' + values[2] + ' | ' + values[3] + '"', async function () { + const result: string[] = sutW.reviewRules(values[0], 1); + assert.equal(result[0], values[1][0]); + assert.equal(result[1], values[2][0]); + assert.equal(result[2], values[3][0]); + }); + }); + }); + + describe('reviewRules messages duplicate and ambiguous with Extra warning', function () { + const sutW = new KmnXKBFileWriter(compilerTestCallbacks, compilerTestOptions); + [[[ + new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'RALT', 'K_B', new TextEncoder().encode('X')), + new Rule("C2", '', '', 0, 0, 'RALT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('Y')), + new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'RALT', 'K_B', new TextEncoder().encode('Z')) + ], + [''], + [''], + ["c WARNING: ambiguous rule: later: [RALT K_B] > dk(A0) ambiguous rule: earlier: [RALT K_B] > 'X' here: PLEASE CHECK THE FOLLOWING RULE AS IT WILL NOT BE WRITTEN ! "]], + ].forEach(function (values: any, index: number) { + it(('rule ' + values[0][0].ruleType + ' should create " ' + ' "') + values[1] + ' | ' + values[2] + ' | ' + values[3] + '"', async function () { + const result: string[] = sutW.reviewRules(values[0], 2); + assert.equal(result[0], values[1][0]); + assert.equal(result[1], values[2][0]); + assert.equal(result[2], values[3][0]); + }); + }); + }); + + describe('write from intermediate data array', function () { + const sutW = new KmnXKBFileWriter(compilerTestCallbacks, compilerTestOptions); + [ + [ + [ /* see ../data/Test_C0.xkb */ + new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_A', new TextEncoder().encode('a')), + new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_A', new TextEncoder().encode('A')), + new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_S', new TextEncoder().encode('s')), + new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_D', new TextEncoder().encode('d')) + ], + ["+ [NCAPS K_A] > 'a'\n" + + "+ [CAPS K_A] > 'A'\n\n" + + "+ [NCAPS K_S] > 's'\n\n" + + "+ [NCAPS K_D] > 'd'\n"] + ], + [ + [ /* see ../data/Test_C1.xkb */ + new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_S', new TextEncoder().encode('s')), + new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_S', new TextEncoder().encode('S')) + ], + ["+ [NCAPS K_S] > 's'\n" + + "+ [CAPS K_S] > 'S'\n"] + ], + [ + [ /* see ../data/Test_C2.xkb */ + new Rule("C2", '', '', 0, 0, 'NCAPS', 'K_U', 1, 1, 'CAPS', 'K_A', new TextEncoder().encode('Â')) + ], + ["+ [NCAPS K_U] > dk(A1)\n" + + "dk(A1) + [CAPS K_A] > 'Â'\n\n"] + ], + [ + [ /* see ../data/Test_C3.xkb */ + new Rule("C3", 'NCAPS SHIFT', 'K_D', 2, 1, 'NCAPS', 'K_U', 1, 2, 'CAPS', 'K_A', new TextEncoder().encode('Â')) + ], + ["+ [NCAPS SHIFT K_D] > dk(A2)\n" + + "dk(A2) + [NCAPS K_U] > dk(B1)\n" + + "dk(B1) + [CAPS K_A] > 'Â'\n\n" + ] + ], + [ + [ /* see ../data/Test_C0_C1_C2_C3.xkb */ + new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_A', new TextEncoder().encode('A')), + new Rule("C2", '', '', 0, 0, 'NCAPS RALT', 'K_EQUAL', 1, 1, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_S', new TextEncoder().encode('S')), + new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'NCAPS RALT', 'K_U', new TextEncoder().encode('S')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 1, 'CAPS', 'K_S', 2, 6, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'CAPS', 'K_U', 3, 3, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'NCAPS RALT', 'K_S', 4, 4, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'NCAPS RALT', 'K_U', 5, 5, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_S', new TextEncoder().encode('S')), + new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'NCAPS RALT', 'K_U', new TextEncoder().encode('S')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'CAPS', 'K_S', 2, 0, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'CAPS', 'K_U', 3, 0, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'NCAPS RALT', 'K_S', 4, 0, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'NCAPS RALT', 'K_U', 5, 0, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_U', new TextEncoder().encode('U')), + ], + ["+ [CAPS K_A] > 'A'\n" + + "+ [CAPS K_S] > 'S'\n\n" + + "+ [NCAPS RALT K_U] > 'S'\n" + + "+ [CAPS K_U] > 'U'\n" + + "+ [NCAPS RALT K_EQUAL] > dk(A1)\n" + + "dk(A1) + [CAPS K_D] > 'Â'\n\n" + + "+ [NCAPS RALT K_8] > dk(A6)\n" + + "dk(A6) + [CAPS K_S] > dk(B2)\n" + + "dk(B2) + [CAPS K_D] > 'Â'\n\n" + + "dk(A6) + [CAPS K_U] > dk(B3)\n" + + "dk(B3) + [CAPS K_D] > 'Â'\n\n" + + "dk(A6) + [NCAPS RALT K_S] > dk(B4)\n" + + "dk(B4) + [CAPS K_D] > 'Â'\n\n" + + "dk(A6) + [NCAPS RALT K_U] > dk(B5)\n" + + "dk(B5) + [CAPS K_D] > 'Â'\n\n"] + ], + [ + [ /* see ../data/Test_C3_several.xkb */ + new Rule("C3", 'NCAPS RALT', 'K_8', 3, 1, 'CAPS', 'K_U', 1, 3, 'NCAPS', 'K_A', new TextEncoder().encode('â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 3, 0, 'CAPS', 'K_U', 1, 0, 'NCAPS RALT', 'K_A', new TextEncoder().encode('â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 3, 0, 'NCAPS RALT', 'K_U', 2, 2, 'NCAPS', 'K_A', new TextEncoder().encode('â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 3, 0, 'NCAPS RALT', 'K_U', 2, 0, 'NCAPS RALT', 'K_A', new TextEncoder().encode('â')) + ], + ["+ [NCAPS RALT K_8] > dk(A3)\n" + + "dk(A3) + [CAPS K_U] > dk(B1)\n" + + "dk(B1) + [NCAPS K_A] > 'â'\n\n" + + "dk(B1) + [NCAPS RALT K_A] > 'â'\n\n" + + "dk(A3) + [NCAPS RALT K_U] > dk(B2)\n" + + "dk(B2) + [NCAPS K_A] > 'â'\n\n" + + "dk(B2) + [NCAPS RALT K_A] > 'â'\n\n" + ] + ], + ].forEach(function (values: any) { + it(('an array of Rules should create a set of kmn rules '), async function () { + const data: ProcessedData = { + keylayoutFilename: "", + kmnFilename: "", + modifiers: [[]], + rules: values[0] + }; + const result1 = sutW.writeDataRules(data); + assert.isTrue(result1 === values[1][0]); + }); + }); + }); + +}); diff --git a/developer/src/kmc-convert/test/xkb-file-reader.tests.ts b/developer/src/kmc-convert/test/xkb-file-reader.tests.ts new file mode 100644 index 00000000000..1d99e622b0d --- /dev/null +++ b/developer/src/kmc-convert/test/xkb-file-reader.tests.ts @@ -0,0 +1,52 @@ +/* + * Keyman is copyright (C) SIL Global. MIT License. + * + * Created by S. Schmitt on 2025-05-12 + * + * Tests for KeylayoutToKmnConverter, XkbFileReader, KmnFileWriter + * + */ + +import 'mocha'; +import { assert } from 'chai'; +import { compilerTestCallbacks, makePathToFixture } from './helpers/index.js'; +import { XkbFileReader } from '../src/xkb-to-kmn/xkb-file-reader.js'; + +describe('XkbFileReader', function () { + + before(function () { + compilerTestCallbacks.clear(); + }); + + describe("read() ", function () { + const sutR = new XkbFileReader(compilerTestCallbacks); + + it('read() should return filled array on correct input', async function () { + const inputFilename = makePathToFixture('../data/Test.xkb'); + const result = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + assert.isNotEmpty(result); + }); + + it('read() should return empty array on empty input', async function () { + const result = sutR.read(compilerTestCallbacks.loadFile("")); + assert.isNull(result); + }); + + it('read() should return empty array on space as input', async function () { + const result = sutR.read(compilerTestCallbacks.loadFile(" ")); + assert.isNull(result); + }); + + it('read() should return empty array on unavailable file name', async function () { + const inputFilenameUnavailable = makePathToFixture('../data/X.xkb'); + const result = sutR.read(compilerTestCallbacks.loadFile(inputFilenameUnavailable)); + assert.isNull(result); + }); + + it('read() should return empty array on typo in path', async function () { + const result = sutR.read(compilerTestCallbacks.loadFile(makePathToFixture('../data|Test.xkb'))); + assert.isNull(result); + }); + }); + +}); diff --git a/developer/src/kmc-convert/test/xkb-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/xkb-to-kmn-converter.tests.ts new file mode 100644 index 00000000000..1226b85c85e --- /dev/null +++ b/developer/src/kmc-convert/test/xkb-to-kmn-converter.tests.ts @@ -0,0 +1,824 @@ +/* + * Keyman is copyright (C) SIL Global. MIT License. + * + * Created by S. Schmitt on 2025-05-12 + * + * Tests for XkbToKmnConverter, XkbFileReader, KmnFileWriter + * + */ +import 'mocha'; +import { assert } from 'chai'; +import * as NodeAssert from 'node:assert'; +import { compilerTestCallbacks, compilerTestOptions, makePathToFixture } from './helpers/index.js'; +import { ActionStateOutput, KeylayoutFileData, XkbToKmnConverter, Rule } from '../src/xkb-to-kmn/xkb-to-kmn-converter.js'; +import { XkbFileReader } from '../src/xkb-to-kmn/xkb-file-reader.js'; +import { ConverterMessages } from '../src/converter-messages.js'; + +describe('XkbToKmnConverter', function () { + + before(function () { + compilerTestCallbacks.clear(); + }); + + describe('RunSpecialTestFiles', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + [ + [makePathToFixture('../data/Test_C0.keylayout')], + [makePathToFixture('../data/Test_C1.keylayout')], + [makePathToFixture('../data/Test_C2.keylayout')], + [makePathToFixture('../data/Test_C2_several.keylayout')], + [makePathToFixture('../data/Test_C3.keylayout')], + [makePathToFixture('../data/Test_C3_several.keylayout')], + [makePathToFixture('../data/Test_C0_C1_C2_C3.keylayout')], + [makePathToFixture('../data/Test_maxKeyCode.keylayout')], + [makePathToFixture('../data/Test_messages.keylayout')], + [makePathToFixture('../data/Test_messages_controlCharacter.keylayout')], + [makePathToFixture('../data/Test_messages_superior_C2.keylayout')], + [makePathToFixture('../data/Test_messages_superior_C3.keylayout')], + [makePathToFixture('../data/Test_duplicate_missing_keycode.keylayout')], + [makePathToFixture('../data/Test_modifier.keylayout')], + [makePathToFixture('../data/Test_modifierNoCaps.keylayout')], + [makePathToFixture('../data/Test_differentAmountOfKeysInBehaviours.keylayout')], + [makePathToFixture('../data/Test_duplicate_missing_keys.keylayout')], + [makePathToFixture('../data/Test_duplicate_keys.keylayout')], + [makePathToFixture('../data/Test_ambiguous_keys.keylayout')], + [makePathToFixture('../data/Test_nr_elements.keylayout')], + [makePathToFixture('../data/Test.keylayout')], + [makePathToFixture('../data/Test_differentEncodings.keylayout')], + [makePathToFixture('../data/Test_ExtraWarning.keylayout')], + ].forEach(function (files) { + it(files + " should give no errors ", async function () { + sut.run(files[0]); + assert.isTrue(compilerTestCallbacks.messages.length === 0); + }); + }); + }); + + describe('RunTestFiles resulting in errors ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + [ + [makePathToFixture('../data/Test_DifferentAmountOfMapSelectInKeyMapERROR.keylayout')], + [makePathToFixture('../data/Test_MissingkeyERROR.keylayout')], + [makePathToFixture('../data/Test_MissingkeyMapERROR.keylayout')], + [makePathToFixture('../data/Test_MissingLayoutsERROR.keylayout')], + [makePathToFixture('../data/Test_MissingmodifierMapERROR.keylayout')], + [makePathToFixture('../data/Test_MissingkeyMapSetERROR.keylayout')], + [makePathToFixture('../data/Test_MissingActionsERROR.keylayout')], + [makePathToFixture('../data/Test_MissingTerminatorsERROR.keylayout')], + [makePathToFixture('../data/Test_MissingAllERROR.keylayout')], + ].forEach(function (files) { + it(files + " should give an error ", async function () { + sut.run(files[0]); + assert.isTrue(compilerTestCallbacks.messages.length > 0); + }); + }); + }); + + describe('RunSpecialTestFiles - create Error: unsupported characters', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + [ + [makePathToFixture('../data/Test_characters.keylayout')], + ].forEach(function (files) { + it(files + " should give Error: unsupported characters ", async function () { + sut.run(files[0]); + assert.isTrue(compilerTestCallbacks.messages.length === 1); + }); + }); + }); + + describe('RunSpecialTestFiles - create Error: undefined action', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + [ + [makePathToFixture('../data/Test_undefinedAction.keylayout')], + ].forEach(function (files) { + it(files + " should give Error: undefined action detected", async function () { + sut.run(files[0]); + assert.isTrue(compilerTestCallbacks.messages.length === 1); + assert.equal(compilerTestCallbacks.messages[0].code, 5292040); + }); + }); + }); + + describe('run() ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + + it('run() should throw on null input file name and null output file name', async function () { + // note, could use 'chai as promised' library to make this more fluent: + const result = sut.run(null, null); + assert.isNotNull(result); + assert.equal(compilerTestCallbacks.messages.length, 1); + assert.deepEqual(compilerTestCallbacks.messages[0], ConverterMessages.Error_FileNotFound({ inputFilename: null })); + }); + + it('run() should throw on null input file name and empty output file name', async function () { + const result = sut.run(null, ''); + assert.isNotNull(result); + assert.equal(compilerTestCallbacks.messages.length, 1); + assert.deepEqual(compilerTestCallbacks.messages[0], ConverterMessages.Error_FileNotFound({ inputFilename: null })); + }); + + it('run() should throw on null input file name and unknown output file name', async function () { + const result = sut.run(null, 'X'); + assert.isNotNull(result); + assert.equal(compilerTestCallbacks.messages.length, 1); + assert.deepEqual(compilerTestCallbacks.messages[0], ConverterMessages.Error_FileNotFound({ inputFilename: null })); + }); + + it('run() should throw on unavailable input file name and null output file name', async function () { + const inputFilename = makePathToFixture('../data/Unavailable.keylayout'); + const result = sut.run(inputFilename, null); + assert.isNotNull(result); + assert.equal(compilerTestCallbacks.messages.length, 2); + assert.deepEqual(compilerTestCallbacks.messages[0], ConverterMessages.Error_UnableToRead()); + assert.equal(compilerTestCallbacks.messages[1].code, 5292037); + }); + }); + + describe('Run kmc-convert with or without outputfile name', async function () { + this.timeout(5000); // allow longer time for this test + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const infile = '../data/Test.keylayout'; + [ + [makePathToFixture('../data/Test.kmn')], + [makePathToFixture('')], + [], + [null], + [makePathToFixture('../data/test_OtherOutputName.kmn')], + [makePathToFixture('../data/OutputXName.bb')], + ].forEach(function (files) { + it(infile + " should run ", async function () { + await NodeAssert.doesNotReject(async () => sut.run(makePathToFixture(infile), files[0])); + assert.equal(compilerTestCallbacks.messages.length, 0); + }); + }); + }); + + describe('convert() ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sutR = new XkbFileReader(compilerTestCallbacks); + + // ProcessedData from usable file + const inputFilename = makePathToFixture('../data/Test.keylayout'); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + const converted = sut.convertBound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); + + // ProcessedData from unavailable file + const inputFilenameUnavailable = makePathToFixture('../data/X.keylayout'); + const readUnavailable = sutR.read(compilerTestCallbacks.loadFile(inputFilenameUnavailable)); + const convertedUnavailable = sut.convertBound.convert(readUnavailable, inputFilenameUnavailable.replace(/\.keylayout$/, '.kmn')); + + // ProcessedData from empty file + const inputFilenameEmpty = makePathToFixture(''); + const readEmpty = sutR.read(compilerTestCallbacks.loadFile(inputFilenameEmpty)); + const convertedEmpty = sut.convertBound.convert(readEmpty, inputFilenameEmpty); + + it('should return converted array on correct input', async function () { + assert.isTrue(converted.rules.length !== 0); + }); + + it('should return empty on empty name as input', async function () { + assert.isNull(convertedUnavailable); + }); + + it('should return empty on empty input', async function () { + assert.isNull(convertedEmpty); + }); + + it('should return empty on only modifiers as input', async function () { + const convertedMod = sut.convertBound.convert({ + keylayoutFilename: '', + modifiers: [['caps'], ['Shift'], ['command']], + rules: [] + }, ''); + assert.isNull(convertedMod); + }); + + it('should return empty on only rules as input', async function () { + const convertedRule = sut.convertBound.convert({ + keylayoutFilename: '', + modifiers: [], + rules: [['C0', '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_A', 'A']] + }, ''); + assert.isNull(convertedRule); + }); + + it('should return empty array of rules on null input', async function () { + const convertedRule = sut.convertBound.convert(null, 'ABC.kmn'); + assert.isNull(convertedRule); + }); + }); + + describe('createKmnModifier ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + [ + [' ', true, 'NCAPS'], + [' ', false, ''], + + ['NCAPS', true, 'NCAPS'], + ['NCAPS', false, ''], + ['caps', true, 'CAPS'], + ['CAPS', true, 'CAPS'], + ['CAPS?', true, 'NCAPS'], + ['CAPS', false, 'CAPS'], + ['CAPS?', false, ''], + ['CAPS? NCAPS', true, 'NCAPS'], + ['CAPS NCAPS', true, 'CAPS NCAPS'], + ['caps ncaps', true, 'CAPS NCAPS'], + ['NCAPS shift', true, 'NCAPS SHIFT'], + ['shift', true, 'NCAPS SHIFT'], + ['leftshift', true, 'NCAPS SHIFT'], + ['rightShift', true, 'NCAPS SHIFT'], + ['shift', false, 'SHIFT'], + ['leftshift', false, 'SHIFT'], + ['rightShift', false, 'SHIFT'], + ['shift rightShift?', true, 'NCAPS SHIFT'], + ['rightShift?', true, 'NCAPS'], + ['shift Shift?', true, 'NCAPS SHIFT'], + ['shift rightShift? caps? rightOption? rightControl', true, 'NCAPS SHIFT RCTRL'], + ['leftshift rightShift? caps? rightOption? rightControl', true, 'NCAPS SHIFT RCTRL'], + ['anycontrol', true, 'NCAPS CTRL'], + ['shift?', true, 'NCAPS'], + ['?', true, 'NCAPS'], + ['?', false, ''], + ['', true, 'NCAPS'], + [' ', false, ''], + ['wrongModifierName', false, 'wrongModifierName'], + ['shift', false, 'SHIFT'], + ['shift command', true, 'NCAPS SHIFT command'], + ['rshift', true, 'NCAPS SHIFT'], + ['rshift', false, 'SHIFT'], + ['rightshift', true, 'NCAPS SHIFT'], + ['riGhtsHift', true, 'NCAPS SHIFT'], + ['LEFTCONTROL', true, 'NCAPS LCTRL'], + ['RCONTROL', true, 'NCAPS RCTRL'], + ['leftoption', true, 'NCAPS LALT'], + ['loption', true, 'NCAPS LALT'], + ['rightoption', true, 'NCAPS RALT'], + ['roption', true, 'NCAPS RALT'], + ].forEach(function (values) { + it(('should convert "' + values[0] + '"').padEnd(36, " ") + 'to "' + values[2] + '"', async function () { + const result = sut.createKmnModifier(values[0] as string, values[1] as boolean); + assert.equal(result, values[2]); + }); + }); + }); + + describe('isAcceptableKeymanModifier ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + [ + ['NCAPS', true], + ['NxCAPS', false], + ['SHIFT', true], + ['ALT', true], + ['RALT', true], + ['LALT', true], + ['CTRL', true], + ['LCTRL', true], + ['RCTRL', true], + ['LCTRL CAPS', true], + ['LCTRL X', false], + ['', true], + [null, false], + ].forEach(function (values) { + it(("isAcceptableKeymanModifier(" + values[0] + ")").padEnd(38, " ") + ' should return ' + values[1], async function () { + const result = sut.isAcceptableKeymanModifier(values[0] as string); + assert.equal(result, values[1]); + }); + }); + }); + + describe('mapUkeleleKeycodeToVK ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + [ + [0x00, 'K_A'], + [0x31, 'K_SPACE'], + [0x18, 'K_EQUAL'], + [0x10, 'K_Y'], + [0x18, 'K_EQUAL'], + [0x21, 'K_LBRKT'], + [0x999, ''], + [-1, ''], + [null, ''], + [undefined, ''], + [, ''], + ].forEach(function (values) { + it(("mapUkeleleKeycodeToVK(" + values[0] + ")").padEnd(26, " ") + "should return " + "'" + values[1] + "'", async function () { + const result = sut.mapUkeleleKeycodeToVK(values[0] as number); + assert.equal(result, values[1]); + }); + }); + }); + + describe('checkIfCapsIsUsed ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + [ + [[['caps', 'xxx'], ['yyy']], true], + [[['Caps', 'xxx'], ['yyy']], true], + [[['CaPs', 'xxx'], ['yyy']], true], + [[['Caps?', 'xxx'], ['yyy']], false], + [[['zzz', 'xxx'], ['Caps?']], false], + [[['caps?', 'xxx'], ['yyy']], false], + [[['zzz', 'xxx'], ['yyy']], false], + [[['shift', 'xxx'], ['caps']], true], + [[['shift', 'caps'], ['yyy']], true], + [[['caps', 'xxx'], ['caps']], true], + [[['', 'someWordWithCaps'], ['']], false], + [null, false], + [[], false], + [[['', ''], ['']], false], + [[[' ', ' '], [' ']], false], + ].forEach(function (values) { + it(("checkIfCapsIsUsed(" + values[0] + ")").padEnd(40, " ") + "should return " + "'" + values[1] + "'", async function () { + const result = sut.checkIfCapsIsUsed(values[0] as string[][]); + assert.isTrue(result === values[1]); + }); + }); + }); + + describe('getModifierArrayFromKeyModifierArray ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sutR = new XkbFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/Test.keylayout'); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + const converted = sut.convertBound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); + [ + [[{ key: '0', behavior: 0 }], [['', 'shift? caps? ']]], + [[{ key: '0', behavior: 2 }], [['shift? leftShift caps? ', 'anyShift caps?', 'shift leftShift caps ', 'shift? rightShift caps? ']]], + [[{ key: '0', behavior: 999 }], [null]], + [[{ key: '999', behavior: null }], [null]], + [[{ key: '0', behavior: -999 }], [null]], + [[{ key: '0', behavior: null }], [null]], + [[], []], + + ].forEach(function (values) { + it((values[1] !== null) ? + ("getModifierArrayFromKeyModifierArray('" + JSON.stringify(values[0]) + "')").padEnd(68, " ") + " should return '" + JSON.stringify(values[1]) + "'" : + ("getModifierArrayFromKeyModifierArray('" + JSON.stringify(values[0]) + "')").padEnd(68, " ") + " should return '" + "null" + "'", async function () { + const result = sut.getModifierArrayFromKeyModifierArray(converted.modifiers, values[0] as KeylayoutFileData[]); + assert.deepStrictEqual(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); + }); + + describe('getKeyModifierArrayFromActionID ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sutR = new XkbFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/Test.keylayout'); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + [ + ['A_16', [{ "key": "32", "behavior": "5" }]], + ['A_19', [{ "key": "45", "behavior": "5" }]], + ['A_18', [{ "key": "24", "behavior": "0" }, { "key": "24", "behavior": "5" }]], + ['unknown', []], + [undefined, []], + [null, []], + [' ', []], + ['', []], + ].forEach(function (values) { + let outstring = '[ '; + for (let i = 0; i < values[1].length; i++) { + outstring = outstring + "[ " + JSON.stringify(values[1][i]) + "], "; + } + it(("getKeyModifierArrayFromActionID('" + values[0] + "')").padEnd(57, " ") + ' should return ' + outstring.substring(0, outstring.lastIndexOf(']') + 2) + " ]", async function () { + const result = sut.getKeyModifierArrayFromActionID(read, String(values[0])); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); + }); + + describe('getActionIdFromActionNext ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sutR = new XkbFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/Test.keylayout'); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + [ + ['none', ''], + ['0', ''], + ['A_18', ''], + ['1', 'A_16'], + ['2', 'A_8'], + ['3', 'A_17'], + ['', ''], + [' ', ''], + ['99', ''], + [null, ''], + [undefined, ''], + ['unknown', ''], + ].forEach(function (values) { + it(("getActionIdFromActionNext('" + values[0] + "')").padEnd(49, " ") + ' should return ' + "'" + values[1] + "'", async function () { + const result = sut.getActionIdFromActionNext(read, String(values[0])); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); + }); + + describe('getActionIndexFromActionId ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sutR = new XkbFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/Test.keylayout'); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + [ + ['none', -1], + ['A_16', 8], + ['A_18', 10], + ['A_19', 11], + ['0', -1], + ['', -1], + [' ', -1], + [null, -1], + [undefined, -1], + ['unknown', -1], + ].forEach(function (values) { + it(("getActionIndexFromActionId('" + values[0] + "')").padEnd(50, " ") + ' should return ' + values[1], async function () { + const result = sut.getActionIndexFromActionId(read, String(values[0])); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); + }); + + describe('getOutputFromActionIdNone ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sutR = new XkbFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/Test.keylayout'); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + [ + ['A_14', 'u'], + ['', ''], + [' ', ''], + ['A_18', ''], + ['unknown', ''], + ].forEach(function (values) { + it( + ("getOutputFromActionIdNone('" + values[0] + "')").padEnd(56, " ") + ' should return ' + "'" + values[1] + "'", async function () { + const result = sut.getOutputFromActionIdNone(read, String(values[0])); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); + + [[null, ''], + [undefined, ''], + [99, ''], + ].forEach(function (values) { + it(("getOutputFromActionIdNone('" + values[0] + "')").padEnd(56, " ") + ' should return ' + values[1], async function () { + const result = sut.getOutputFromActionIdNone(read, String(values[0])); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); + }); + + describe('getKeybehaviorModOutputArrayFromKeyActionbehaviorOutputArray ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sutR = new XkbFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/Test.keylayout'); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + + const b1KeycodeArr: KeylayoutFileData[] = [ + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '0', outchar: 'ˆ' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '1', outchar: 'ˆ' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '2', outchar: 'ˆ' }, + { keyCode: '6', key: 'K_Z', actionId: 'A_0', behavior: '4', outchar: 'ˆ' }, + { keyCode: '25', key: 'K_9', actionId: 'A_0', behavior: '4', outchar: 'ˆ' }, + { keyCode: '43', key: 'K_COMMA', actionId: 'A_0', behavior: '4', outchar: 'ˆ' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '3', outchar: 'ˆ' }, + { keyCode: '0', key: 'K_A', actionId: 'A_1', behavior: '2', outchar: 'Â' }, + { keyCode: '0', key: 'K_A', actionId: 'A_1', behavior: '1', outchar: 'Â' }, + { keyCode: '14', key: 'K_E', actionId: 'A_10', behavior: '0', outchar: 'ê' }, + { keyCode: '34', key: 'K_I', actionId: 'A_11', behavior: '0', outchar: 'î' }, + { keyCode: '31', key: 'K_O', actionId: 'A_13', behavior: '0', outchar: 'ô' }, + { keyCode: '32', key: 'K_U', actionId: 'A_14', behavior: '0', outchar: 'û' }, + { keyCode: '14', key: 'K_E', actionId: 'A_2', behavior: '2', outchar: 'Ê' }, + { keyCode: '14', key: 'K_E', actionId: 'A_2', behavior: '1', outchar: 'Ê' }, + { keyCode: '34', key: 'K_I', actionId: 'A_3', behavior: '2', outchar: 'Î' }, + { keyCode: '34', key: 'K_I', actionId: 'A_3', behavior: '1', outchar: 'Î' }, + { keyCode: '31', key: 'K_O', actionId: 'A_5', behavior: '2', outchar: 'Ô' }, + { keyCode: '31', key: 'K_O', actionId: 'A_5', behavior: '1', outchar: 'Ô' }, + { keyCode: '32', key: 'K_U', actionId: 'A_6', behavior: '2', outchar: 'Û' }, + { keyCode: '32', key: 'K_U', actionId: 'A_6', behavior: '1', outchar: 'Û' }, + { keyCode: '0', key: 'K_A', actionId: 'A_9', behavior: '0', outchar: 'â' } + + ]; + const b1ModifierKeyArr: KeylayoutFileData[] = [ + { actionId: 'A_0', key: 'K_SPACE', behavior: '0', modifier: 'NCAPS', outchar: 'ˆ' }, + { actionId: 'A_0', key: 'K_SPACE', behavior: '1', modifier: 'CAPS', outchar: 'ˆ' }, + { actionId: 'A_0', key: 'K_SPACE', behavior: '2', modifier: 'NCAPS SHIFT', outchar: 'ˆ' }, + { actionId: 'A_0', key: 'K_SPACE', behavior: '2', modifier: 'SHIFT CAPS', outchar: 'ˆ' }, + { actionId: 'A_0', key: 'K_Z', behavior: '4', modifier: 'NCAPS SHIFT RALT', outchar: 'ˆ' }, + { actionId: 'A_0', key: 'K_9', behavior: '4', modifier: 'NCAPS SHIFT RALT', outchar: 'ˆ' }, + { actionId: 'A_0', key: 'K_COMMA', behavior: '4', modifier: 'NCAPS SHIFT RALT', outchar: 'ˆ' }, + { actionId: 'A_0', key: 'K_SPACE', behavior: '3', modifier: 'NCAPS RALT CTRL', outchar: 'ˆ' }, + { actionId: 'A_0', key: 'K_SPACE', behavior: '3', modifier: 'NCAPS CTRL', outchar: 'ˆ' }, + { actionId: 'A_1', key: 'K_A', behavior: '2', modifier: 'NCAPS SHIFT', outchar: 'Â' }, + { actionId: 'A_1', key: 'K_A', behavior: '2', modifier: 'SHIFT CAPS', outchar: 'Â' }, + { actionId: 'A_1', key: 'K_A', behavior: '1', modifier: 'CAPS', outchar: 'Â' }, + { actionId: 'A_10', key: 'K_E', behavior: '0', modifier: 'NCAPS', outchar: 'ê' }, + { actionId: 'A_11', key: 'K_I', behavior: '0', modifier: 'NCAPS', outchar: 'î' }, + { actionId: 'A_13', key: 'K_O', behavior: '0', modifier: 'NCAPS', outchar: 'ô' }, + { actionId: 'A_14', key: 'K_U', behavior: '0', modifier: 'NCAPS', outchar: 'û' }, + { actionId: 'A_2', key: 'K_E', behavior: '2', modifier: 'NCAPS SHIFT', outchar: 'Ê' }, + { actionId: 'A_2', key: 'K_E', behavior: '2', modifier: 'SHIFT CAPS', outchar: 'Ê' }, + { actionId: 'A_2', key: 'K_E', behavior: '1', modifier: 'CAPS', outchar: 'Ê' }, + { actionId: 'A_3', key: 'K_I', behavior: '2', modifier: 'NCAPS SHIFT', outchar: 'Î' }, + { actionId: 'A_3', key: 'K_I', behavior: '2', modifier: 'SHIFT CAPS', outchar: 'Î' }, + { actionId: 'A_3', key: 'K_I', behavior: '1', modifier: 'CAPS', outchar: 'Î' }, + { actionId: 'A_5', key: 'K_O', behavior: '2', modifier: 'NCAPS SHIFT', outchar: 'Ô' }, + { actionId: 'A_5', key: 'K_O', behavior: '2', modifier: 'SHIFT CAPS', outchar: 'Ô' }, + { actionId: 'A_5', key: 'K_O', behavior: '1', modifier: 'CAPS', outchar: 'Ô' }, + { actionId: 'A_6', key: 'K_U', behavior: '2', modifier: 'NCAPS SHIFT', outchar: 'Û' }, + { actionId: 'A_6', key: 'K_U', behavior: '2', modifier: 'SHIFT CAPS', outchar: 'Û' }, + { actionId: 'A_6', key: 'K_U', behavior: '1', modifier: 'CAPS', outchar: 'Û' }, + { actionId: 'A_9', key: 'K_A', behavior: '0', modifier: 'NCAPS', outchar: 'â' } + ]; + + [[b1KeycodeArr, b1ModifierKeyArr], + [[{ keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '0', modifier: '0', outchar: 'ˆ' }], [{ actionId: 'A_0', key: 'K_SPACE', behavior: '0', modifier: 'NCAPS', outchar: 'ˆ' }]], + [[{ keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '0', modifier: '', outchar: 'ˆ' }], [{ actionId: 'A_0', key: 'K_SPACE', behavior: '0', modifier: 'NCAPS', outchar: 'ˆ' }]], + [[{ keyCode: '49', key: 'K_SPACE', actionId: '', behavior: '0', modifier: '0', outchar: 'ˆ' }], [{ actionId: '', key: 'K_SPACE', behavior: '0', modifier: 'NCAPS', outchar: 'ˆ' }]], + [[{ keyCode: '49', key: '', actionId: 'A_0', behavior: '0', modifier: '0', outchar: 'ˆ' }], [{ actionId: 'A_0', key: '', behavior: '0', modifier: 'NCAPS', outchar: 'ˆ' }]], + [[{ keyCode: '', key: 'K_SPACE', actionId: 'A_0', behavior: '0', modifier: '0', outchar: 'ˆ' }], [{ actionId: 'A_0', key: 'K_SPACE', behavior: '0', modifier: 'NCAPS', outchar: 'ˆ' }]], + [[{ keyCode: '', key: '', actionId: '', behavior: '0', modifier: '', outchar: '' }], [{ actionId: '', key: '', behavior: '0', modifier: 'NCAPS', outchar: '' }]], + ].forEach(function (values) { + const isCapsUsed = true; + const stringIn = "getKeybehaviorModOutputArrayFromKeyActionbehaviorOutputArray(['" + "', '" + "', '" + values[0][0].keyCode + "', '" + values[0][0].key + "', '" + values[0][0].actionId + "', '" + values[0][0].modifier + "', '" + values[0][0].outchar + "'])"; + const stringOut = "['" + "', '" + "', '" + values[1][0].key + "', '" + values[1][0].actionId + "', '" + "', '" + values[1][0].modifier + "', '" + values[1][0].outchar + "']"; + + it((JSON.stringify(values[1]).length > 60) ? 'an array of objects should return an array of objects' : + stringIn.padEnd(74, " ") + ' should return ' + stringOut, async function () { + const result = sut.getKeyBehaviorModOutputArrayFromKeyActionBehaviorOutputArray(read, values[0], isCapsUsed); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); + + [[{ keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '0', modifier: '0', outchar: 'ˆ' }, { actionId: 'A_0', key: 'K_SPACE', behavior: '0', modifier: '', outchar: 'ˆ' }], + [{ keyCode: '', key: 'K_SPACE', actionId: 'A_0', behavior: '0', modifier: '0', outchar: 'ˆ' }, { actionId: 'A_0', key: 'K_SPACE', behavior: '0', modifier: '', outchar: 'ˆ' }], + [{ keyCode: '', key: '', actionId: '', behavior: '0', modifier: '', outchar: '' }, { actionId: '', key: '', behavior: '0', modifier: '', outchar: '' }], + ].forEach(function (values) { + const isCapsUsed = false; + const stringIn = "getKeybehaviorModOutputArrayFromKeyActionbehaviorOutputArray([ '" + values[0].keyCode + "', '" + values[0].key + "', '" + values[0].actionId + "', '" + values[0].modifier + "', '" + values[0].outchar + "'])"; + const stringOut = "['" + values[1].actionId + "', '" + "', '" + values[1].modifier + "', '" + values[1].key + "', '" + values[1].outchar + "']"; + + it(stringIn.padEnd(74, " ") + ' should return ' + stringOut, async function () { + const result = sut.getKeyBehaviorModOutputArrayFromKeyActionBehaviorOutputArray(read, [values[0]], isCapsUsed); + assert.equal(JSON.stringify(result), JSON.stringify([values[1]])); + }); + }); + + [[[], []], + [undefined, []], + [null, []], + ].forEach(function (values) { + const isCaps = true; + it(("getKeybehaviorModOutputArrayFromKeyActionbehaviorOutputArray([" + values[0] + "])").padEnd(74, " ") + ' should return ' + "[" + values[1] + "]", async function () { + const result = sut.getKeyBehaviorModOutputArrayFromKeyActionBehaviorOutputArray(read, values[0], isCaps); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); + }); + + describe('getActionStateOutputArrayFromActionState ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sutR = new XkbFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/Test.keylayout'); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + [['1', [ + { "id": "A_0", "state": "1", "output": "ˆ" }, + { "id": "A_1", "state": "1", "output": "Â" }, + { "id": "A_10", "state": "1", "output": "ê" }, + { "id": "A_11", "state": "1", "output": "î" }, + { "id": "A_13", "state": "1", "output": "ô" }, + { "id": "A_14", "state": "1", "output": "û" }, + { "id": "A_2", "state": "1", "output": "Ê" }, + { "id": "A_3", "state": "1", "output": "Î" }, + { "id": "A_5", "state": "1", "output": "Ô" }, + { "id": "A_6", "state": "1", "output": "Û" }, + { "id": "A_9", "state": "1", "output": "â" } + ],], + ['2', [ + { "id": "A_0", "state": "2", "output": "`" }, + { "id": "A_1", "state": "2", "output": "À" }, + { "id": "A_10", "state": "2", "output": "è" }, + { "id": "A_11", "state": "2", "output": "ì" }, + { "id": "A_13", "state": "2", "output": "ò" }, + { "id": "A_14", "state": "2", "output": "ù" }, + { "id": "A_2", "state": "2", "output": "È" }, + { "id": "A_3", "state": "2", "output": "Ì" }, + { "id": "A_5", "state": "2", "output": "Ò" }, + { "id": "A_6", "state": "2", "output": "Ù" }, + { "id": "A_9", "state": "2", "output": "à" } + ],], + ['789', [],], + ['', [],], + [' ', [],], + [123, [],], + [null, [],], + [undefined, [],], + ].forEach(function (values) { + it((JSON.stringify(values[1]).length > 30) ? + ("getActionStateOutputArrayFromActionState('" + values[0] + "')").padEnd(60, " ") + ' should return an array of objects' : + ("getActionStateOutputArrayFromActionState('" + values[0] + "')").padEnd(60, " ") + ' should return ' + "'" + JSON.stringify(values[1]) + "'", async function () { + const result = sut.getActionStateOutputArrayFromActionState(read, String(values[0])); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); + }); + + describe('getActionOutputbehaviorKeyModiFromActionIDStateOutput ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sutR = new XkbFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/Test.keylayout'); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + const converted = sut.convertBound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); + [ + ['A_1', 'A', true, + [{ "outchar": "A", "actionId": "A_1", "behavior": "1", "key": "K_A", "modifier": "CAPS" }, + { "outchar": "A", "actionId": "A_1", "behavior": "2", "key": "K_A", "modifier": "NCAPS SHIFT" }, + { "outchar": "A", "actionId": "A_1", "behavior": "2", "key": "K_A", "modifier": "SHIFT CAPS" }] + ], + ['A_1', 'A', false, + [{ "outchar": "A", "actionId": "A_1", "behavior": "1", "key": "K_A", "modifier": "CAPS" }, + { "outchar": "A", "actionId": "A_1", "behavior": "2", "key": "K_A", "modifier": "SHIFT" }, + { "outchar": "A", "actionId": "A_1", "behavior": "2", "key": "K_A", "modifier": "SHIFT CAPS" }] + ], + ['A_9', 'a', true, [{ "outchar": "a", "actionId": "A_9", "behavior": "0", "key": "K_A", "modifier": "NCAPS" }]], + ['A_9', 'a', false, [{ "outchar": "a", "actionId": "A_9", "behavior": "0", "key": "K_A", "modifier": "" }]], + ['A_9', 'a', , [{ "outchar": "a", "actionId": "A_9", "behavior": "0", "key": "K_A", "modifier": "" }]], + ['A_9', '', true, [{ "outchar": "", "actionId": "A_9", "behavior": "0", "key": "K_A", "modifier": "NCAPS" }]], + ['A_9', '', false, [{ "outchar": "", "actionId": "A_9", "behavior": "0", "key": "K_A", "modifier": "" }]], + ['', 'a', true, []], + ['', 'a', false, []], + ['', '', , []], + ].forEach(function (values) { + it((JSON.stringify(values[3]).length > 35) ? + ("getActionOutputbehaviorKeyModiFromActionIDStateOutput('" + values[0] + "', '" + values[1] + "', " + values[2] + ")").padEnd(67, " ") + ' should return an array of objects' : + ("getActionOutputbehaviorKeyModiFromActionIDStateOutput('" + values[0] + "', '" + values[1] + "', " + values[2] + ")").padEnd(67, " ") + ' should return ' + "'" + JSON.stringify(values[3]) + "'", async function () { + const result = sut.getActionOutputBehaviorKeyModiFromActionIDStateOutput(read, converted.modifiers, String(values[0]), String(values[1]), Boolean(values[2])); + assert.equal(JSON.stringify(result), JSON.stringify(values[3])); + }); + }); + }); + + describe('getKeyActionOutputArrayFromActionStateOutputArray ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sutR = new XkbFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/Test.keylayout'); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + + const b6ActionIdArr: ActionStateOutput[] = [ + { "id": "A_0", "state": "1", "output": "ˆ" }, + { "id": "A_1", "state": "1", "output": "Â" }, + { "id": "A_10", "state": "1", "output": "ê" }, + { "id": "A_11", "state": "1", "output": "î" }, + { "id": "A_13", "state": "1", "output": "ô" }, + { "id": "A_14", "state": "1", "output": "û" }, + { "id": "A_2", "state": "1", "output": "Ê" }, + { "id": "A_3", "state": "1", "output": "Î" }, + { "id": "A_5", "state": "1", "output": "Ô" }, + { "id": "A_6", "state": "1", "output": "Û" }, + { "id": "A_9", "state": "1", "output": "â" } + ]; + + const b1KeycodeArr: KeylayoutFileData[] = [ + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '0', outchar: 'ˆ' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '1', outchar: 'ˆ' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '2', outchar: 'ˆ' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '3', outchar: 'ˆ' }, + { keyCode: '6', key: 'K_Z', actionId: 'A_0', behavior: '4', outchar: 'ˆ' }, + { keyCode: '25', key: 'K_9', actionId: 'A_0', behavior: '4', outchar: 'ˆ' }, + { keyCode: '43', key: 'K_COMMA', actionId: 'A_0', behavior: '4', outchar: 'ˆ' }, + { keyCode: '0', key: 'K_A', actionId: 'A_1', behavior: '1', outchar: 'Â' }, + { keyCode: '0', key: 'K_A', actionId: 'A_1', behavior: '2', outchar: 'Â' }, + { keyCode: '14', key: 'K_E', actionId: 'A_10', behavior: '0', outchar: 'ê' }, + { keyCode: '34', key: 'K_I', actionId: 'A_11', behavior: '0', outchar: 'î' }, + { keyCode: '31', key: 'K_O', actionId: 'A_13', behavior: '0', outchar: 'ô' }, + { keyCode: '32', key: 'K_U', actionId: 'A_14', behavior: '0', outchar: 'û' }, + { keyCode: '14', key: 'K_E', actionId: 'A_2', behavior: '1', outchar: 'Ê' }, + { keyCode: '14', key: 'K_E', actionId: 'A_2', behavior: '2', outchar: 'Ê' }, + { keyCode: '34', key: 'K_I', actionId: 'A_3', behavior: '1', outchar: 'Î' }, + { keyCode: '34', key: 'K_I', actionId: 'A_3', behavior: '2', outchar: 'Î' }, + { keyCode: '31', key: 'K_O', actionId: 'A_5', behavior: '1', outchar: 'Ô' }, + { keyCode: '31', key: 'K_O', actionId: 'A_5', behavior: '2', outchar: 'Ô' }, + { keyCode: '32', key: 'K_U', actionId: 'A_6', behavior: '1', outchar: 'Û' }, + { keyCode: '32', key: 'K_U', actionId: 'A_6', behavior: '2', outchar: 'Û' }, + { keyCode: '0', key: 'K_A', actionId: 'A_9', behavior: '0', outchar: 'â' } + ]; + + [[b6ActionIdArr, b1KeycodeArr], + ].forEach(function (values) { + it(("getKeyActionOutputArrayFromActionStateOutputArray([['" + JSON.stringify(values[0]) + "'],..])").padEnd(73, " ") + '1 should return an array of objects', async function () { + const result = sut.getKeyActionOutputArrayFromActionStateOutputArray(read, values[0] as ActionStateOutput[]); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); + + const oneEntryResult = [ + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '0', outchar: 'ˆ' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '1', outchar: 'ˆ' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '2', outchar: 'ˆ' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '3', outchar: 'ˆ' }, + { keyCode: '6', key: 'K_Z', actionId: 'A_0', behavior: '4', outchar: 'ˆ' }, + { keyCode: '25', key: 'K_9', actionId: 'A_0', behavior: '4', outchar: 'ˆ' }, + { keyCode: '43', key: 'K_COMMA', actionId: 'A_0', behavior: '4', outchar: 'ˆ' } + ]; + + const oneEntryResultNoOutput = [ + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '0', outchar: '' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '1', outchar: '' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '2', outchar: '' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '3', outchar: '' }, + { keyCode: '6', key: 'K_Z', actionId: 'A_0', behavior: '4', outchar: '' }, + { keyCode: '25', key: 'K_9', actionId: 'A_0', behavior: '4', outchar: '' }, + { keyCode: '43', key: 'K_COMMA', actionId: 'A_0', behavior: '4', outchar: '' }, + ]; + + [[[{ "id": "A_0", "state": "1", "output": "ˆ" }], oneEntryResult], + [[{ "id": "A_0", "state": "1", "output": "" }], oneEntryResultNoOutput], + [[{ "id": "A_0", "state": "", "output": "ˆ" }], oneEntryResult], + ].forEach(function (values) { + it(("getKeyActionOutputArrayFromActionStateOutputArray(['" + JSON.stringify(values[0]) + "'])").padEnd(73, " ") + ' should return an array of objects', async function () { + const result = sut.getKeyActionOutputArrayFromActionStateOutputArray(read, values[0] as ActionStateOutput[]); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); + + [[[{ "id": "", "state": "1", "output": "ˆ" }], []], + [[{ "id": "", "state": "", "output": "" }], []], + [[{ "id": " ", "state": " ", "output": "" }], []], + + ].forEach(function (values) { + it(("getKeyActionOutputArrayFromActionStateOutputArray(" + JSON.stringify(values[0]) + ")").padEnd(73, " ") + ' should return ' + "'[" + JSON.stringify(values[1]) + "]'", async function () { + const result = sut.getKeyActionOutputArrayFromActionStateOutputArray(read, values[0] as ActionStateOutput[]); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); + + [[, []], + [undefined, []], + [null, []], + ].forEach(function (values) { + it(("getKeyActionOutputArrayFromActionStateOutputArray(" + JSON.stringify(values[0]) + ")").padEnd(73, " ") + ' should return ' + "'[" + JSON.stringify(values[1]) + "]'", async function () { + const result = sut.getKeyActionOutputArrayFromActionStateOutputArray(read, values[0] as ActionStateOutput[]); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); + }); + + describe('createRuleData ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sutR = new XkbFileReader(compilerTestCallbacks); + [ + [ + ['../data/Test_C0.keylayout'], + [new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_A', new TextEncoder().encode('a')), + new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_A', new TextEncoder().encode('A')), + new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_S', new TextEncoder().encode('s')), + new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_D', new TextEncoder().encode('d'))] + ], + [ + ['../data/Test_C1.keylayout'], + [new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_S', new TextEncoder().encode('s')), + new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_S', new TextEncoder().encode('S'))] + ], + [ + ['../data/Test_C2.keylayout'], + [new Rule("C2", '', '', 0, 0, 'NCAPS', 'K_U', 1, 1, 'CAPS', 'K_A', new TextEncoder().encode('Â'))], + ], + [ + ['../data/Test_C3.keylayout'], + [new Rule("C3", 'NCAPS SHIFT', 'K_D', 2, 1, 'NCAPS', 'K_U', 1, 2, 'CAPS', 'K_A', new TextEncoder().encode('Â'))] + ], + + [ + ['../data/Test_C3_several.keylayout'], + [new Rule("C3", 'NCAPS RALT', 'K_8', 3, 1, 'CAPS', 'K_U', 1, 3, 'NCAPS', 'K_A', new TextEncoder().encode('â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 3, 0, 'CAPS', 'K_U', 1, 0, 'NCAPS RALT', 'K_A', new TextEncoder().encode('â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 3, 0, 'NCAPS RALT', 'K_U', 2, 2, 'NCAPS', 'K_A', new TextEncoder().encode('â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 3, 0, 'NCAPS RALT', 'K_U', 2, 0, 'NCAPS RALT', 'K_A', new TextEncoder().encode('â'))] + ], + [ + ['../data/Test_C0_C1_C2_C3.keylayout'], + [new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_A', new TextEncoder().encode('A')), + new Rule("C2", '', '', 0, 0, 'NCAPS RALT', 'K_EQUAL', 1, 1, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_S', new TextEncoder().encode('S')), + new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'NCAPS RALT', 'K_U', new TextEncoder().encode('S')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 1, 'CAPS', 'K_S', 2, 6, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'CAPS', 'K_U', 3, 3, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'NCAPS RALT', 'K_S', 4, 4, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'NCAPS RALT', 'K_U', 5, 5, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_S', new TextEncoder().encode('S')), + new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'NCAPS RALT', 'K_U', new TextEncoder().encode('S')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'CAPS', 'K_S', 2, 0, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'CAPS', 'K_U', 3, 0, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'NCAPS RALT', 'K_S', 4, 0, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'NCAPS RALT', 'K_U', 5, 0, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_U', new TextEncoder().encode('U')),] + ], + ].forEach(function (values: any) { + it('data of \'' + values[0] + "' passed into createRuleData() " + 'should create an array of rules', async function () { + const inputFilename = makePathToFixture(values[0][0]); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + const processedData = sut.convertBound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); + assert.deepEqual(processedData.rules[0], values[1][0]); + }); + }); + }); + +}); From 5e24cc136d467c2c9dfeb848ed96d9a45d6593c5 Mon Sep 17 00:00:00 2001 From: Sabine Date: Mon, 27 Apr 2026 08:53:15 +0200 Subject: [PATCH 233/251] feat(developer): remove tests for xkb-kmn --- .../test/kmnXKB-file-writer.tests.ts | 524 ----------- .../kmc-convert/test/xkb-file-reader.tests.ts | 52 -- .../test/xkb-to-kmn-converter.tests.ts | 824 ------------------ 3 files changed, 1400 deletions(-) delete mode 100644 developer/src/kmc-convert/test/kmnXKB-file-writer.tests.ts delete mode 100644 developer/src/kmc-convert/test/xkb-file-reader.tests.ts delete mode 100644 developer/src/kmc-convert/test/xkb-to-kmn-converter.tests.ts diff --git a/developer/src/kmc-convert/test/kmnXKB-file-writer.tests.ts b/developer/src/kmc-convert/test/kmnXKB-file-writer.tests.ts deleted file mode 100644 index d2ecf597c45..00000000000 --- a/developer/src/kmc-convert/test/kmnXKB-file-writer.tests.ts +++ /dev/null @@ -1,524 +0,0 @@ -/* - * Keyman is copyright (C) SIL Global. MIT License. - * - * Created by S. Schmitt on 2025-05-12 - * - * Tests for XkbToKmnConverter, XkbFileReader, KmnXKBFileWriter - * - */ - -import 'mocha'; -import { assert } from 'chai'; -import KEYMAN_VERSION from "@keymanapp/keyman-version"; -import { compilerTestCallbacks, compilerTestOptions, makePathToFixture } from './helpers/index.js'; -import { XkbToKmnConverter, ProcessedData, Rule } from '../src/xkb-to-kmn/xkb-to-kmn-converter.js'; -import { KmnXKBFileWriter } from '../src/xkb-to-kmn/kmnXKB-file-writer.js'; -import { XkbFileReader } from '../src/xkb-to-kmn/xkb-file-reader.js'; - -describe('KmnXKBFileWriter', function () { - - before(function () { - compilerTestCallbacks.clear(); - }); - - describe("writeDataRules() ", function () { - const inputFilename = makePathToFixture('../data/Test.xkb'); - const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const sutR = new XkbFileReader(compilerTestCallbacks); - const sutW = new KmnXKBFileWriter(compilerTestCallbacks, compilerTestOptions); - const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); - const converted = sut.convertBound.convert(read, inputFilename.replace(/\.xkb$/, '.kmn')); - - it('writeDataRules() should return true (no error) if written', async function () { - const result = sutW.writeDataRules(converted); - assert.isTrue(result.length > 0); - }); - - }); - - describe("writeKmnFileHeader() ", function () { - const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const sutR = new XkbFileReader(compilerTestCallbacks); - const sutW = new KmnXKBFileWriter(compilerTestCallbacks, compilerTestOptions); - const inputFilename = makePathToFixture('../data/Test.xkb'); - const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); - const converted = sut.convertBound.convert(read, inputFilename.replace(/\.xkb$/, '.kmn')); - - const outExpectedFirst: string = - "c ..................................................................................................................\n" - + "c ..................................................................................................................\n" - + "c Keyman keyboard generated by kmn-convert version: " + KEYMAN_VERSION.VERSION + "\n" - + "c from Ukelele file: "; - - const outExpectedLast: string = - "\n" - + "c ..................................................................................................................\n" - + "c ..................................................................................................................\n" - + "\n" - + "store(&TARGETS) 'desktop'\n" - + "\n" - + "begin Unicode > use(main)\n\n" - + "group(main) using keys\n\n" - + "\n"; - - it(('writeKmnFileHeader should return store text with filename ').padEnd(62, " ") + 'on correct input', async function () { - const writtenCorrectName = sutW.writeKmnFileHeader(converted); - assert.equal(writtenCorrectName, (outExpectedFirst + converted.keylayoutFilename + outExpectedLast)); - }); - }); - - describe('convertToUnicodeCharacter ', function () { - const sutW = new KmnXKBFileWriter(compilerTestCallbacks, compilerTestOptions); - [ - - ["<", '<'], - ["a", 'a'], - ["ሴ", 'ሴ'], - ["W̊", "W̊"], - ['😎', '😎'], - ["ab", 'ab'], - ["ሴЖ", 'ሴЖ'], - ["ẘẈ", "ẘẈ"], - ["😎😆", '😎😆'], - ["aሴ😆", 'aሴ😆'], - /* - ["U+0061", 'a'], - ["U+1234", 'ሴ'], - ["U+1E9A", "ẚ"], - ["U+1F60A", '😊'], - ["U+0001", '\u0001'], - ["U+1000000;", undefined], - */ - ["a", 'a'], - ["ሴ", 'ሴ'], - ["ẘ", "ẘ"], - ["😏", '😏'], - ["", '\u0002'], - ["�", undefined], - ["a", 'a'], - ["ሴ", 'ሴ'], - ["ẛ", "ẛ"], - ["😆", '😆'], - ["", '\u0003'], - ["󴉀", '󴉀'], - ["@", undefined], - [">", '>'], - ["<", '<'], - [""", '"'], - ["'", "'"], - [">", undefined], - ["␤", '␤'], - ["␕", '␕'], - ["", ''], - ["", ''], - [undefined, undefined], - [null, undefined], - /* - ["U+", undefined], - ['U+', undefined], - ['U+U+', undefined], - ['U+D799', '힙'], - ['U+D800', undefined], - ['U+D83D', undefined], - ['U+DFFF', undefined], - ['U+10FFFF', '􏿿'], - ['U+E000', ''], - ['U+1000000', undefined], - */ - ['&', '&'], - ['&;', '&;'], - ['&&', '&&'], - ['&&;', '&&;'], - ["&#&#", undefined], - ["&#x&#x", undefined], - ["&#", undefined], - ["&#;", undefined], - ["&#x", undefined], - ["&#x;", undefined], - ['&##', undefined], - ['&##;', undefined], - ["􏿿", "􏿿"], - ["􏿿", "􏿿"], - ["�", undefined], - ["�", undefined], - ['Ӓ56', undefined], - -//.................................................................. - - ["a", 'a'], - ["ሴ", 'ሴ'], - ["😎", '😎'], - ["", '\u0002'], - ["�", undefined], - ["a", 'a'], - ["ሴ", 'ሴ'], - ["😆", '😆'], - ["", '\u0003'], - ["󴉀", '󴉀'], - /*["U+0061", 'a'], - ["U+1234", 'ሴ'], - ["U+1F60E", '😎'], - ["U+0001", '\u0001'], - ["U+1000000;", undefined],*/ - ["@", undefined], - ["a", 'a'], - ["ሴ", 'ሴ'], - ['😎', '😎'], - ["W̊", "W̊"], - ["ab", 'ab'], - ["", ''], - ["␤", '␤'], - ["␕", '␕'], - ["", ''], - [undefined, undefined], - [null, undefined] - ].forEach(function (values) { - it(('should convert "' + values[0] + '"').padEnd(25, " ") + 'to "' + values[1] + '"', async function () { - const result = sutW.convertToUnicodeCharacter(values[0] as string); - assert.equal(result, values[1]); - }); - }); - }); - - describe('reviewRules messages', function () { - const sutW = new KmnXKBFileWriter(compilerTestCallbacks, compilerTestOptions); - [ - [[new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'UNAVAILABLE', 'K_A', new TextEncoder().encode('A'))], - [''], - [''], - ['c WARNING: unavailable modifier : here: ']], - - [[new Rule("C1", '', '', 0, 0, 'CAPS', 'K_EQUAL', 0, 0, 'UNAVAILABLE', 'K_B', new TextEncoder().encode('B'))], - [''], - [''], - ['c WARNING: unavailable modifier : here: ']], - - [[new Rule("C2", '', '', 0, 0, 'CAPS', 'K_EQUAL', 0, 0, 'UNAVAILABLE', 'K_C', new TextEncoder().encode('C'),)], - [''], - [''], - ['c WARNING: unavailable modifier : here: ']], - - [[new Rule("C2", '', '', 0, 0, 'UNAVAILABLE_dk', 'K_EQUAL', 0, 0, 'UNAVAILABLE', 'K_C', new TextEncoder().encode('C'),)], - [''], - ['c WARNING: unavailable modifier : here: '], - ['c WARNING: unavailable modifier : here: ']], - - [[new Rule("C3", 'UNAVAILABLE_prev_dk', 'K_D', 0, 0, 'UNAVAILABLE_dk', 'K_EQUAL', 0, 0, 'SHIFT', 'K_C', new TextEncoder().encode('D'),)], - ['c WARNING: unavailable modifier : here: '], - ['c WARNING: unavailable modifier : here: '], - ['c WARNING: unavailable superior rule ( [UNAVAILABLE_dk K_EQUAL] > dk(B0) ) : here: ']], - - [[new Rule("C3", 'UNAVAILABLE_prev_dk', 'K_D', 0, 0, 'UNAVAILABLE_dk', 'K_EQUAL', 0, 0, 'UNAVAIL', 'K_C', new TextEncoder().encode('D'),)], - ['c WARNING: unavailable modifier : here: '], - ['c WARNING: unavailable modifier : here: '], - ['c WARNING: unavailable modifier : here: ']], - - [[new Rule("C3", 'CAPS', 'K_D', 0, 0, 'RALT', 'K_EQUAL', 0, 0, 'SHIFT', 'K_C', new TextEncoder().encode('D'),)], - [''], - [''], - ['']], - - [[new Rule("C3", 'X', 'K_X', 0, 0, 'Y', 'K_Y', 0, 0, 'SHIFT', 'K_Z', new TextEncoder().encode('D'),)], - ['c WARNING: unavailable modifier : here: '], - ['c WARNING: unavailable modifier : here: '], - ['c WARNING: unavailable superior rule ( [Y K_Y] > dk(B0) ) : here: ']], - - ].forEach(function (values: any, index: number) { - it(('rule " ' + values[0][0].ruleType + ' "') + 'should create "' + values[1] + ' | ' + values[2] + ' | ' + values[3] + '"', async function () { - const result: string[] = sutW.reviewRules(values[0], 0); - assert.equal(result[0], values[1][0]); - assert.equal(result[1], values[2][0]); - assert.equal(result[2], values[3][0]); - }); - }); - }); - - describe('reviewRules messages duplicate and ambiguous', function () { - const sutW = new KmnXKBFileWriter(compilerTestCallbacks, compilerTestOptions); - [ - //all - [[ - new Rule("C3", 'LALT', 'K_A', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), - new Rule("C3", 'LALT', 'K_A', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')),], - ['c WARNING: duplicate rule: earlier: [LALT K_A] > dk(C0) here: '], - ["c WARNING: duplicate rule: earlier: dk(B0) + [SHIFT K_B] > dk(B0) here: "], - ["c WARNING: duplicate rule: earlier: dk(B0) + [CAPS K_C] > 'X' here: "]], - - //6-6 dup - [[ - new Rule("C3", 'LALT', 'K_A', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), - new Rule("C3", 'CTRL', 'K_D', 0, 0, 'NCAPS', 'K_E', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')),], - [''], - [""], - ["c WARNING: duplicate rule: earlier: dk(B0) + [CAPS K_C] > 'X' here: "]], - - //6-6 amb - [[ - new Rule("C3", 'LALT', 'K_A', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), - new Rule("C3", 'CTRL', 'K_D', 0, 0, 'NCAPS', 'K_E', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('Y')),], - [''], - [""], - ["c WARNING: ambiguous rule: earlier: dk(B0) + [CAPS K_C] > 'X' here: "]], - - // 5-5 amb - [[ - new Rule("C3", 'LALT', 'K_A', 0, 0, 'NCAPS', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), - new Rule("C3", 'LALT', 'K_A', 0, 0, 'NCAPS', 'K_B', 0, 1, 'RALT', 'K_F', new TextEncoder().encode('X')),], - ['c WARNING: duplicate rule: earlier: [LALT K_A] > dk(C0) here: '], - ["c WARNING: ambiguous rule: earlier: dk(B0) + [NCAPS K_B] > dk(B0) here: "], [''], - ], - - // 5-5 dup - [[ - new Rule("C3", 'LALT', 'K_A', 0, 0, 'NCAPS', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), - new Rule("C3", 'LALT', 'K_A', 0, 0, 'NCAPS', 'K_B', 0, 0, 'RALT', 'K_F', new TextEncoder().encode('X')),], - ['c WARNING: duplicate rule: earlier: [LALT K_A] > dk(C0) here: '], - ["c WARNING: duplicate rule: earlier: dk(B0) + [NCAPS K_B] > dk(B0) here: "], - ['']], - - // 4-2 amb - [[ - new Rule("C3", 'LALT', 'K_A', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), - new Rule("C2", '', '', 0, 0, 'LALT', 'K_A', 0, 0, 'RALT', 'K_F', new TextEncoder().encode('X')),], - ['c WARNING: ambiguous rule: later: [LALT K_A] > dk(C0) here: '], - [''], - ['']], - - // 4-4 amb - [[ - new Rule("C3", 'LALT', 'K_A', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), - new Rule("C3", 'LALT', 'K_A', 1, 1, 'NCAPS', 'K_E', 0, 0, 'RALT', 'K_F', new TextEncoder().encode('Y')),], - ['c WARNING: ambiguous rule: earlier: [LALT K_A] > dk(C0) here: '], - [""], - [''],], - - // 4-4 dup - [[ - new Rule("C3", 'LALT', 'K_A', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), - new Rule("C3", 'LALT', 'K_A', 0, 0, 'NCAPS', 'K_E', 0, 0, 'RALT', 'K_F', new TextEncoder().encode('X')),], - ['c WARNING: duplicate rule: earlier: [LALT K_A] > dk(C0) here: '], - [''], - ['']], - - // 4-2 amb - [[ - new Rule("C3", 'LALT', 'K_A', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), - new Rule("C2", '', '', 0, 0, 'LALT', 'K_A', 0, 0, 'RALT', 'K_F', new TextEncoder().encode('Y')),], - ['c WARNING: ambiguous rule: later: [LALT K_A] > dk(C0) here: '], - [''], - ['']], - - // 6-3 dup - [[ - new Rule("C2", '', '', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), - new Rule("C3", 'CTRL', 'K_D', 0, 0, 'NCAPS', 'K_E', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')),], - [''], - ["c WARNING: duplicate rule: earlier: dk(C0) + [CAPS K_C] > 'X' here: "], - [''],], - - // 6-3 amb - [[ - new Rule("C2", '', '', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), - new Rule("C3", 'CTRL', 'K_D', 0, 0, 'NCAPS', 'K_E', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('Y')),], - [''], - ["c WARNING: ambiguous rule: earlier: dk(C0) + [CAPS K_C] > 'X' here: "], - [''],], - - // 2-4 amb - [[ - new Rule("C2", '', '', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), - new Rule("C3", 'SHIFT', 'K_B', 0, 0, 'NCAPS', 'K_E', 0, 0, 'RALT', 'K_F', new TextEncoder().encode('Y')),], - ['c WARNING: ambiguous rule: earlier: [SHIFT K_B] > dk(A0) here: '], - [''], - ['']], - - //2-2 amb - [[ - new Rule("C2", '', '', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), - new Rule("C2", '', '', 0, 0, 'SHIFT', 'K_B', 1, 1, 'RALT', 'K_F', new TextEncoder().encode('Y')),], - [''], - ['c WARNING: ambiguous rule: earlier: [SHIFT K_B] > dk(C0) here: '], - ['']], - - // 2-2 dup - [[ - new Rule("C2", '', '', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), - new Rule("C2", '', '', 0, 0, 'SHIFT', 'K_B', 0, 0, 'RALT', 'K_F', new TextEncoder().encode('Y')),], - [''], - ['c WARNING: duplicate rule: earlier: [SHIFT K_B] > dk(C0) here: '], - ['']], - - // 3-3 dup - [[ - new Rule("C2", '', '', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), - new Rule("C2", '', '', 0, 0, 'NCAPS', 'K_E', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')),], - [''], - [''], - ["c WARNING: duplicate rule: earlier: dk(A0) + [CAPS K_C] > 'X' here: "]], - - // 3-3 amb - [[ - new Rule("C2", '', '', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), - new Rule("C2", '', '', 0, 0, 'NCAPS', 'K_E', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('Y')),], - [''], - [''], - ["c WARNING: ambiguous rule: earlier: dk(A0) + [CAPS K_C] > 'X' here: "]], - - // 2-1 amb - [[ - new Rule("C2", '', '', 0, 0, 'RALT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), - new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'RALT', 'K_B', new TextEncoder().encode('Y'))], - [''], - [''], - ['c WARNING: ambiguous rule: later: [RALT K_B] > dk(A0) here: ']], - - // 1-1 amb - [[ - new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), - new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('Y'))], - [''], - [''], - ["c WARNING: ambiguous rule: earlier: [CAPS K_C] > 'X' here: "]], - - // 1-1 amb - [[ - new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), - new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X'))], - [''], - [''], - ["c WARNING: duplicate rule: earlier: [CAPS K_C] > 'X' here: "]], - - ].forEach(function (values: any, index: number) { - it('rule ' + values[0][0].ruleType + ' should create " ' + ' "' + values[1] + ' | ' + values[2] + ' | ' + values[3] + '"', async function () { - const result: string[] = sutW.reviewRules(values[0], 1); - assert.equal(result[0], values[1][0]); - assert.equal(result[1], values[2][0]); - assert.equal(result[2], values[3][0]); - }); - }); - }); - - describe('reviewRules messages duplicate and ambiguous with Extra warning', function () { - const sutW = new KmnXKBFileWriter(compilerTestCallbacks, compilerTestOptions); - [[[ - new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'RALT', 'K_B', new TextEncoder().encode('X')), - new Rule("C2", '', '', 0, 0, 'RALT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('Y')), - new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'RALT', 'K_B', new TextEncoder().encode('Z')) - ], - [''], - [''], - ["c WARNING: ambiguous rule: later: [RALT K_B] > dk(A0) ambiguous rule: earlier: [RALT K_B] > 'X' here: PLEASE CHECK THE FOLLOWING RULE AS IT WILL NOT BE WRITTEN ! "]], - ].forEach(function (values: any, index: number) { - it(('rule ' + values[0][0].ruleType + ' should create " ' + ' "') + values[1] + ' | ' + values[2] + ' | ' + values[3] + '"', async function () { - const result: string[] = sutW.reviewRules(values[0], 2); - assert.equal(result[0], values[1][0]); - assert.equal(result[1], values[2][0]); - assert.equal(result[2], values[3][0]); - }); - }); - }); - - describe('write from intermediate data array', function () { - const sutW = new KmnXKBFileWriter(compilerTestCallbacks, compilerTestOptions); - [ - [ - [ /* see ../data/Test_C0.xkb */ - new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_A', new TextEncoder().encode('a')), - new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_A', new TextEncoder().encode('A')), - new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_S', new TextEncoder().encode('s')), - new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_D', new TextEncoder().encode('d')) - ], - ["+ [NCAPS K_A] > 'a'\n" + - "+ [CAPS K_A] > 'A'\n\n" + - "+ [NCAPS K_S] > 's'\n\n" + - "+ [NCAPS K_D] > 'd'\n"] - ], - [ - [ /* see ../data/Test_C1.xkb */ - new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_S', new TextEncoder().encode('s')), - new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_S', new TextEncoder().encode('S')) - ], - ["+ [NCAPS K_S] > 's'\n" + - "+ [CAPS K_S] > 'S'\n"] - ], - [ - [ /* see ../data/Test_C2.xkb */ - new Rule("C2", '', '', 0, 0, 'NCAPS', 'K_U', 1, 1, 'CAPS', 'K_A', new TextEncoder().encode('Â')) - ], - ["+ [NCAPS K_U] > dk(A1)\n" + - "dk(A1) + [CAPS K_A] > 'Â'\n\n"] - ], - [ - [ /* see ../data/Test_C3.xkb */ - new Rule("C3", 'NCAPS SHIFT', 'K_D', 2, 1, 'NCAPS', 'K_U', 1, 2, 'CAPS', 'K_A', new TextEncoder().encode('Â')) - ], - ["+ [NCAPS SHIFT K_D] > dk(A2)\n" + - "dk(A2) + [NCAPS K_U] > dk(B1)\n" + - "dk(B1) + [CAPS K_A] > 'Â'\n\n" - ] - ], - [ - [ /* see ../data/Test_C0_C1_C2_C3.xkb */ - new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_A', new TextEncoder().encode('A')), - new Rule("C2", '', '', 0, 0, 'NCAPS RALT', 'K_EQUAL', 1, 1, 'CAPS', 'K_D', new TextEncoder().encode('Â')), - new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_S', new TextEncoder().encode('S')), - new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'NCAPS RALT', 'K_U', new TextEncoder().encode('S')), - new Rule("C3", 'NCAPS RALT', 'K_8', 6, 1, 'CAPS', 'K_S', 2, 6, 'CAPS', 'K_D', new TextEncoder().encode('Â')), - new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'CAPS', 'K_U', 3, 3, 'CAPS', 'K_D', new TextEncoder().encode('Â')), - new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'NCAPS RALT', 'K_S', 4, 4, 'CAPS', 'K_D', new TextEncoder().encode('Â')), - new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'NCAPS RALT', 'K_U', 5, 5, 'CAPS', 'K_D', new TextEncoder().encode('Â')), - new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_S', new TextEncoder().encode('S')), - new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'NCAPS RALT', 'K_U', new TextEncoder().encode('S')), - new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'CAPS', 'K_S', 2, 0, 'CAPS', 'K_D', new TextEncoder().encode('Â')), - new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'CAPS', 'K_U', 3, 0, 'CAPS', 'K_D', new TextEncoder().encode('Â')), - new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'NCAPS RALT', 'K_S', 4, 0, 'CAPS', 'K_D', new TextEncoder().encode('Â')), - new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'NCAPS RALT', 'K_U', 5, 0, 'CAPS', 'K_D', new TextEncoder().encode('Â')), - new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_U', new TextEncoder().encode('U')), - ], - ["+ [CAPS K_A] > 'A'\n" + - "+ [CAPS K_S] > 'S'\n\n" + - "+ [NCAPS RALT K_U] > 'S'\n" + - "+ [CAPS K_U] > 'U'\n" + - "+ [NCAPS RALT K_EQUAL] > dk(A1)\n" + - "dk(A1) + [CAPS K_D] > 'Â'\n\n" + - "+ [NCAPS RALT K_8] > dk(A6)\n" + - "dk(A6) + [CAPS K_S] > dk(B2)\n" + - "dk(B2) + [CAPS K_D] > 'Â'\n\n" + - "dk(A6) + [CAPS K_U] > dk(B3)\n" + - "dk(B3) + [CAPS K_D] > 'Â'\n\n" + - "dk(A6) + [NCAPS RALT K_S] > dk(B4)\n" + - "dk(B4) + [CAPS K_D] > 'Â'\n\n" + - "dk(A6) + [NCAPS RALT K_U] > dk(B5)\n" + - "dk(B5) + [CAPS K_D] > 'Â'\n\n"] - ], - [ - [ /* see ../data/Test_C3_several.xkb */ - new Rule("C3", 'NCAPS RALT', 'K_8', 3, 1, 'CAPS', 'K_U', 1, 3, 'NCAPS', 'K_A', new TextEncoder().encode('â')), - new Rule("C3", 'NCAPS RALT', 'K_8', 3, 0, 'CAPS', 'K_U', 1, 0, 'NCAPS RALT', 'K_A', new TextEncoder().encode('â')), - new Rule("C3", 'NCAPS RALT', 'K_8', 3, 0, 'NCAPS RALT', 'K_U', 2, 2, 'NCAPS', 'K_A', new TextEncoder().encode('â')), - new Rule("C3", 'NCAPS RALT', 'K_8', 3, 0, 'NCAPS RALT', 'K_U', 2, 0, 'NCAPS RALT', 'K_A', new TextEncoder().encode('â')) - ], - ["+ [NCAPS RALT K_8] > dk(A3)\n" + - "dk(A3) + [CAPS K_U] > dk(B1)\n" + - "dk(B1) + [NCAPS K_A] > 'â'\n\n" + - "dk(B1) + [NCAPS RALT K_A] > 'â'\n\n" + - "dk(A3) + [NCAPS RALT K_U] > dk(B2)\n" + - "dk(B2) + [NCAPS K_A] > 'â'\n\n" + - "dk(B2) + [NCAPS RALT K_A] > 'â'\n\n" - ] - ], - ].forEach(function (values: any) { - it(('an array of Rules should create a set of kmn rules '), async function () { - const data: ProcessedData = { - keylayoutFilename: "", - kmnFilename: "", - modifiers: [[]], - rules: values[0] - }; - const result1 = sutW.writeDataRules(data); - assert.isTrue(result1 === values[1][0]); - }); - }); - }); - -}); diff --git a/developer/src/kmc-convert/test/xkb-file-reader.tests.ts b/developer/src/kmc-convert/test/xkb-file-reader.tests.ts deleted file mode 100644 index 1d99e622b0d..00000000000 --- a/developer/src/kmc-convert/test/xkb-file-reader.tests.ts +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Keyman is copyright (C) SIL Global. MIT License. - * - * Created by S. Schmitt on 2025-05-12 - * - * Tests for KeylayoutToKmnConverter, XkbFileReader, KmnFileWriter - * - */ - -import 'mocha'; -import { assert } from 'chai'; -import { compilerTestCallbacks, makePathToFixture } from './helpers/index.js'; -import { XkbFileReader } from '../src/xkb-to-kmn/xkb-file-reader.js'; - -describe('XkbFileReader', function () { - - before(function () { - compilerTestCallbacks.clear(); - }); - - describe("read() ", function () { - const sutR = new XkbFileReader(compilerTestCallbacks); - - it('read() should return filled array on correct input', async function () { - const inputFilename = makePathToFixture('../data/Test.xkb'); - const result = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); - assert.isNotEmpty(result); - }); - - it('read() should return empty array on empty input', async function () { - const result = sutR.read(compilerTestCallbacks.loadFile("")); - assert.isNull(result); - }); - - it('read() should return empty array on space as input', async function () { - const result = sutR.read(compilerTestCallbacks.loadFile(" ")); - assert.isNull(result); - }); - - it('read() should return empty array on unavailable file name', async function () { - const inputFilenameUnavailable = makePathToFixture('../data/X.xkb'); - const result = sutR.read(compilerTestCallbacks.loadFile(inputFilenameUnavailable)); - assert.isNull(result); - }); - - it('read() should return empty array on typo in path', async function () { - const result = sutR.read(compilerTestCallbacks.loadFile(makePathToFixture('../data|Test.xkb'))); - assert.isNull(result); - }); - }); - -}); diff --git a/developer/src/kmc-convert/test/xkb-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/xkb-to-kmn-converter.tests.ts deleted file mode 100644 index 1226b85c85e..00000000000 --- a/developer/src/kmc-convert/test/xkb-to-kmn-converter.tests.ts +++ /dev/null @@ -1,824 +0,0 @@ -/* - * Keyman is copyright (C) SIL Global. MIT License. - * - * Created by S. Schmitt on 2025-05-12 - * - * Tests for XkbToKmnConverter, XkbFileReader, KmnFileWriter - * - */ -import 'mocha'; -import { assert } from 'chai'; -import * as NodeAssert from 'node:assert'; -import { compilerTestCallbacks, compilerTestOptions, makePathToFixture } from './helpers/index.js'; -import { ActionStateOutput, KeylayoutFileData, XkbToKmnConverter, Rule } from '../src/xkb-to-kmn/xkb-to-kmn-converter.js'; -import { XkbFileReader } from '../src/xkb-to-kmn/xkb-file-reader.js'; -import { ConverterMessages } from '../src/converter-messages.js'; - -describe('XkbToKmnConverter', function () { - - before(function () { - compilerTestCallbacks.clear(); - }); - - describe('RunSpecialTestFiles', function () { - const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); - [ - [makePathToFixture('../data/Test_C0.keylayout')], - [makePathToFixture('../data/Test_C1.keylayout')], - [makePathToFixture('../data/Test_C2.keylayout')], - [makePathToFixture('../data/Test_C2_several.keylayout')], - [makePathToFixture('../data/Test_C3.keylayout')], - [makePathToFixture('../data/Test_C3_several.keylayout')], - [makePathToFixture('../data/Test_C0_C1_C2_C3.keylayout')], - [makePathToFixture('../data/Test_maxKeyCode.keylayout')], - [makePathToFixture('../data/Test_messages.keylayout')], - [makePathToFixture('../data/Test_messages_controlCharacter.keylayout')], - [makePathToFixture('../data/Test_messages_superior_C2.keylayout')], - [makePathToFixture('../data/Test_messages_superior_C3.keylayout')], - [makePathToFixture('../data/Test_duplicate_missing_keycode.keylayout')], - [makePathToFixture('../data/Test_modifier.keylayout')], - [makePathToFixture('../data/Test_modifierNoCaps.keylayout')], - [makePathToFixture('../data/Test_differentAmountOfKeysInBehaviours.keylayout')], - [makePathToFixture('../data/Test_duplicate_missing_keys.keylayout')], - [makePathToFixture('../data/Test_duplicate_keys.keylayout')], - [makePathToFixture('../data/Test_ambiguous_keys.keylayout')], - [makePathToFixture('../data/Test_nr_elements.keylayout')], - [makePathToFixture('../data/Test.keylayout')], - [makePathToFixture('../data/Test_differentEncodings.keylayout')], - [makePathToFixture('../data/Test_ExtraWarning.keylayout')], - ].forEach(function (files) { - it(files + " should give no errors ", async function () { - sut.run(files[0]); - assert.isTrue(compilerTestCallbacks.messages.length === 0); - }); - }); - }); - - describe('RunTestFiles resulting in errors ', function () { - const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); - [ - [makePathToFixture('../data/Test_DifferentAmountOfMapSelectInKeyMapERROR.keylayout')], - [makePathToFixture('../data/Test_MissingkeyERROR.keylayout')], - [makePathToFixture('../data/Test_MissingkeyMapERROR.keylayout')], - [makePathToFixture('../data/Test_MissingLayoutsERROR.keylayout')], - [makePathToFixture('../data/Test_MissingmodifierMapERROR.keylayout')], - [makePathToFixture('../data/Test_MissingkeyMapSetERROR.keylayout')], - [makePathToFixture('../data/Test_MissingActionsERROR.keylayout')], - [makePathToFixture('../data/Test_MissingTerminatorsERROR.keylayout')], - [makePathToFixture('../data/Test_MissingAllERROR.keylayout')], - ].forEach(function (files) { - it(files + " should give an error ", async function () { - sut.run(files[0]); - assert.isTrue(compilerTestCallbacks.messages.length > 0); - }); - }); - }); - - describe('RunSpecialTestFiles - create Error: unsupported characters', function () { - const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); - [ - [makePathToFixture('../data/Test_characters.keylayout')], - ].forEach(function (files) { - it(files + " should give Error: unsupported characters ", async function () { - sut.run(files[0]); - assert.isTrue(compilerTestCallbacks.messages.length === 1); - }); - }); - }); - - describe('RunSpecialTestFiles - create Error: undefined action', function () { - const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); - [ - [makePathToFixture('../data/Test_undefinedAction.keylayout')], - ].forEach(function (files) { - it(files + " should give Error: undefined action detected", async function () { - sut.run(files[0]); - assert.isTrue(compilerTestCallbacks.messages.length === 1); - assert.equal(compilerTestCallbacks.messages[0].code, 5292040); - }); - }); - }); - - describe('run() ', function () { - const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); - - it('run() should throw on null input file name and null output file name', async function () { - // note, could use 'chai as promised' library to make this more fluent: - const result = sut.run(null, null); - assert.isNotNull(result); - assert.equal(compilerTestCallbacks.messages.length, 1); - assert.deepEqual(compilerTestCallbacks.messages[0], ConverterMessages.Error_FileNotFound({ inputFilename: null })); - }); - - it('run() should throw on null input file name and empty output file name', async function () { - const result = sut.run(null, ''); - assert.isNotNull(result); - assert.equal(compilerTestCallbacks.messages.length, 1); - assert.deepEqual(compilerTestCallbacks.messages[0], ConverterMessages.Error_FileNotFound({ inputFilename: null })); - }); - - it('run() should throw on null input file name and unknown output file name', async function () { - const result = sut.run(null, 'X'); - assert.isNotNull(result); - assert.equal(compilerTestCallbacks.messages.length, 1); - assert.deepEqual(compilerTestCallbacks.messages[0], ConverterMessages.Error_FileNotFound({ inputFilename: null })); - }); - - it('run() should throw on unavailable input file name and null output file name', async function () { - const inputFilename = makePathToFixture('../data/Unavailable.keylayout'); - const result = sut.run(inputFilename, null); - assert.isNotNull(result); - assert.equal(compilerTestCallbacks.messages.length, 2); - assert.deepEqual(compilerTestCallbacks.messages[0], ConverterMessages.Error_UnableToRead()); - assert.equal(compilerTestCallbacks.messages[1].code, 5292037); - }); - }); - - describe('Run kmc-convert with or without outputfile name', async function () { - this.timeout(5000); // allow longer time for this test - const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const infile = '../data/Test.keylayout'; - [ - [makePathToFixture('../data/Test.kmn')], - [makePathToFixture('')], - [], - [null], - [makePathToFixture('../data/test_OtherOutputName.kmn')], - [makePathToFixture('../data/OutputXName.bb')], - ].forEach(function (files) { - it(infile + " should run ", async function () { - await NodeAssert.doesNotReject(async () => sut.run(makePathToFixture(infile), files[0])); - assert.equal(compilerTestCallbacks.messages.length, 0); - }); - }); - }); - - describe('convert() ', function () { - const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const sutR = new XkbFileReader(compilerTestCallbacks); - - // ProcessedData from usable file - const inputFilename = makePathToFixture('../data/Test.keylayout'); - const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); - const converted = sut.convertBound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); - - // ProcessedData from unavailable file - const inputFilenameUnavailable = makePathToFixture('../data/X.keylayout'); - const readUnavailable = sutR.read(compilerTestCallbacks.loadFile(inputFilenameUnavailable)); - const convertedUnavailable = sut.convertBound.convert(readUnavailable, inputFilenameUnavailable.replace(/\.keylayout$/, '.kmn')); - - // ProcessedData from empty file - const inputFilenameEmpty = makePathToFixture(''); - const readEmpty = sutR.read(compilerTestCallbacks.loadFile(inputFilenameEmpty)); - const convertedEmpty = sut.convertBound.convert(readEmpty, inputFilenameEmpty); - - it('should return converted array on correct input', async function () { - assert.isTrue(converted.rules.length !== 0); - }); - - it('should return empty on empty name as input', async function () { - assert.isNull(convertedUnavailable); - }); - - it('should return empty on empty input', async function () { - assert.isNull(convertedEmpty); - }); - - it('should return empty on only modifiers as input', async function () { - const convertedMod = sut.convertBound.convert({ - keylayoutFilename: '', - modifiers: [['caps'], ['Shift'], ['command']], - rules: [] - }, ''); - assert.isNull(convertedMod); - }); - - it('should return empty on only rules as input', async function () { - const convertedRule = sut.convertBound.convert({ - keylayoutFilename: '', - modifiers: [], - rules: [['C0', '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_A', 'A']] - }, ''); - assert.isNull(convertedRule); - }); - - it('should return empty array of rules on null input', async function () { - const convertedRule = sut.convertBound.convert(null, 'ABC.kmn'); - assert.isNull(convertedRule); - }); - }); - - describe('createKmnModifier ', function () { - const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); - [ - [' ', true, 'NCAPS'], - [' ', false, ''], - - ['NCAPS', true, 'NCAPS'], - ['NCAPS', false, ''], - ['caps', true, 'CAPS'], - ['CAPS', true, 'CAPS'], - ['CAPS?', true, 'NCAPS'], - ['CAPS', false, 'CAPS'], - ['CAPS?', false, ''], - ['CAPS? NCAPS', true, 'NCAPS'], - ['CAPS NCAPS', true, 'CAPS NCAPS'], - ['caps ncaps', true, 'CAPS NCAPS'], - ['NCAPS shift', true, 'NCAPS SHIFT'], - ['shift', true, 'NCAPS SHIFT'], - ['leftshift', true, 'NCAPS SHIFT'], - ['rightShift', true, 'NCAPS SHIFT'], - ['shift', false, 'SHIFT'], - ['leftshift', false, 'SHIFT'], - ['rightShift', false, 'SHIFT'], - ['shift rightShift?', true, 'NCAPS SHIFT'], - ['rightShift?', true, 'NCAPS'], - ['shift Shift?', true, 'NCAPS SHIFT'], - ['shift rightShift? caps? rightOption? rightControl', true, 'NCAPS SHIFT RCTRL'], - ['leftshift rightShift? caps? rightOption? rightControl', true, 'NCAPS SHIFT RCTRL'], - ['anycontrol', true, 'NCAPS CTRL'], - ['shift?', true, 'NCAPS'], - ['?', true, 'NCAPS'], - ['?', false, ''], - ['', true, 'NCAPS'], - [' ', false, ''], - ['wrongModifierName', false, 'wrongModifierName'], - ['shift', false, 'SHIFT'], - ['shift command', true, 'NCAPS SHIFT command'], - ['rshift', true, 'NCAPS SHIFT'], - ['rshift', false, 'SHIFT'], - ['rightshift', true, 'NCAPS SHIFT'], - ['riGhtsHift', true, 'NCAPS SHIFT'], - ['LEFTCONTROL', true, 'NCAPS LCTRL'], - ['RCONTROL', true, 'NCAPS RCTRL'], - ['leftoption', true, 'NCAPS LALT'], - ['loption', true, 'NCAPS LALT'], - ['rightoption', true, 'NCAPS RALT'], - ['roption', true, 'NCAPS RALT'], - ].forEach(function (values) { - it(('should convert "' + values[0] + '"').padEnd(36, " ") + 'to "' + values[2] + '"', async function () { - const result = sut.createKmnModifier(values[0] as string, values[1] as boolean); - assert.equal(result, values[2]); - }); - }); - }); - - describe('isAcceptableKeymanModifier ', function () { - const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); - [ - ['NCAPS', true], - ['NxCAPS', false], - ['SHIFT', true], - ['ALT', true], - ['RALT', true], - ['LALT', true], - ['CTRL', true], - ['LCTRL', true], - ['RCTRL', true], - ['LCTRL CAPS', true], - ['LCTRL X', false], - ['', true], - [null, false], - ].forEach(function (values) { - it(("isAcceptableKeymanModifier(" + values[0] + ")").padEnd(38, " ") + ' should return ' + values[1], async function () { - const result = sut.isAcceptableKeymanModifier(values[0] as string); - assert.equal(result, values[1]); - }); - }); - }); - - describe('mapUkeleleKeycodeToVK ', function () { - const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); - [ - [0x00, 'K_A'], - [0x31, 'K_SPACE'], - [0x18, 'K_EQUAL'], - [0x10, 'K_Y'], - [0x18, 'K_EQUAL'], - [0x21, 'K_LBRKT'], - [0x999, ''], - [-1, ''], - [null, ''], - [undefined, ''], - [, ''], - ].forEach(function (values) { - it(("mapUkeleleKeycodeToVK(" + values[0] + ")").padEnd(26, " ") + "should return " + "'" + values[1] + "'", async function () { - const result = sut.mapUkeleleKeycodeToVK(values[0] as number); - assert.equal(result, values[1]); - }); - }); - }); - - describe('checkIfCapsIsUsed ', function () { - const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); - [ - [[['caps', 'xxx'], ['yyy']], true], - [[['Caps', 'xxx'], ['yyy']], true], - [[['CaPs', 'xxx'], ['yyy']], true], - [[['Caps?', 'xxx'], ['yyy']], false], - [[['zzz', 'xxx'], ['Caps?']], false], - [[['caps?', 'xxx'], ['yyy']], false], - [[['zzz', 'xxx'], ['yyy']], false], - [[['shift', 'xxx'], ['caps']], true], - [[['shift', 'caps'], ['yyy']], true], - [[['caps', 'xxx'], ['caps']], true], - [[['', 'someWordWithCaps'], ['']], false], - [null, false], - [[], false], - [[['', ''], ['']], false], - [[[' ', ' '], [' ']], false], - ].forEach(function (values) { - it(("checkIfCapsIsUsed(" + values[0] + ")").padEnd(40, " ") + "should return " + "'" + values[1] + "'", async function () { - const result = sut.checkIfCapsIsUsed(values[0] as string[][]); - assert.isTrue(result === values[1]); - }); - }); - }); - - describe('getModifierArrayFromKeyModifierArray ', function () { - const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const sutR = new XkbFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); - const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); - const converted = sut.convertBound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); - [ - [[{ key: '0', behavior: 0 }], [['', 'shift? caps? ']]], - [[{ key: '0', behavior: 2 }], [['shift? leftShift caps? ', 'anyShift caps?', 'shift leftShift caps ', 'shift? rightShift caps? ']]], - [[{ key: '0', behavior: 999 }], [null]], - [[{ key: '999', behavior: null }], [null]], - [[{ key: '0', behavior: -999 }], [null]], - [[{ key: '0', behavior: null }], [null]], - [[], []], - - ].forEach(function (values) { - it((values[1] !== null) ? - ("getModifierArrayFromKeyModifierArray('" + JSON.stringify(values[0]) + "')").padEnd(68, " ") + " should return '" + JSON.stringify(values[1]) + "'" : - ("getModifierArrayFromKeyModifierArray('" + JSON.stringify(values[0]) + "')").padEnd(68, " ") + " should return '" + "null" + "'", async function () { - const result = sut.getModifierArrayFromKeyModifierArray(converted.modifiers, values[0] as KeylayoutFileData[]); - assert.deepStrictEqual(JSON.stringify(result), JSON.stringify(values[1])); - }); - }); - }); - - describe('getKeyModifierArrayFromActionID ', function () { - const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const sutR = new XkbFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); - const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); - [ - ['A_16', [{ "key": "32", "behavior": "5" }]], - ['A_19', [{ "key": "45", "behavior": "5" }]], - ['A_18', [{ "key": "24", "behavior": "0" }, { "key": "24", "behavior": "5" }]], - ['unknown', []], - [undefined, []], - [null, []], - [' ', []], - ['', []], - ].forEach(function (values) { - let outstring = '[ '; - for (let i = 0; i < values[1].length; i++) { - outstring = outstring + "[ " + JSON.stringify(values[1][i]) + "], "; - } - it(("getKeyModifierArrayFromActionID('" + values[0] + "')").padEnd(57, " ") + ' should return ' + outstring.substring(0, outstring.lastIndexOf(']') + 2) + " ]", async function () { - const result = sut.getKeyModifierArrayFromActionID(read, String(values[0])); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); - }); - }); - }); - - describe('getActionIdFromActionNext ', function () { - const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const sutR = new XkbFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); - const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); - [ - ['none', ''], - ['0', ''], - ['A_18', ''], - ['1', 'A_16'], - ['2', 'A_8'], - ['3', 'A_17'], - ['', ''], - [' ', ''], - ['99', ''], - [null, ''], - [undefined, ''], - ['unknown', ''], - ].forEach(function (values) { - it(("getActionIdFromActionNext('" + values[0] + "')").padEnd(49, " ") + ' should return ' + "'" + values[1] + "'", async function () { - const result = sut.getActionIdFromActionNext(read, String(values[0])); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); - }); - }); - }); - - describe('getActionIndexFromActionId ', function () { - const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const sutR = new XkbFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); - const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); - [ - ['none', -1], - ['A_16', 8], - ['A_18', 10], - ['A_19', 11], - ['0', -1], - ['', -1], - [' ', -1], - [null, -1], - [undefined, -1], - ['unknown', -1], - ].forEach(function (values) { - it(("getActionIndexFromActionId('" + values[0] + "')").padEnd(50, " ") + ' should return ' + values[1], async function () { - const result = sut.getActionIndexFromActionId(read, String(values[0])); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); - }); - }); - }); - - describe('getOutputFromActionIdNone ', function () { - const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const sutR = new XkbFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); - const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); - [ - ['A_14', 'u'], - ['', ''], - [' ', ''], - ['A_18', ''], - ['unknown', ''], - ].forEach(function (values) { - it( - ("getOutputFromActionIdNone('" + values[0] + "')").padEnd(56, " ") + ' should return ' + "'" + values[1] + "'", async function () { - const result = sut.getOutputFromActionIdNone(read, String(values[0])); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); - }); - }); - - [[null, ''], - [undefined, ''], - [99, ''], - ].forEach(function (values) { - it(("getOutputFromActionIdNone('" + values[0] + "')").padEnd(56, " ") + ' should return ' + values[1], async function () { - const result = sut.getOutputFromActionIdNone(read, String(values[0])); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); - }); - }); - }); - - describe('getKeybehaviorModOutputArrayFromKeyActionbehaviorOutputArray ', function () { - const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const sutR = new XkbFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); - const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); - - const b1KeycodeArr: KeylayoutFileData[] = [ - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '0', outchar: 'ˆ' }, - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '1', outchar: 'ˆ' }, - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '2', outchar: 'ˆ' }, - { keyCode: '6', key: 'K_Z', actionId: 'A_0', behavior: '4', outchar: 'ˆ' }, - { keyCode: '25', key: 'K_9', actionId: 'A_0', behavior: '4', outchar: 'ˆ' }, - { keyCode: '43', key: 'K_COMMA', actionId: 'A_0', behavior: '4', outchar: 'ˆ' }, - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '3', outchar: 'ˆ' }, - { keyCode: '0', key: 'K_A', actionId: 'A_1', behavior: '2', outchar: 'Â' }, - { keyCode: '0', key: 'K_A', actionId: 'A_1', behavior: '1', outchar: 'Â' }, - { keyCode: '14', key: 'K_E', actionId: 'A_10', behavior: '0', outchar: 'ê' }, - { keyCode: '34', key: 'K_I', actionId: 'A_11', behavior: '0', outchar: 'î' }, - { keyCode: '31', key: 'K_O', actionId: 'A_13', behavior: '0', outchar: 'ô' }, - { keyCode: '32', key: 'K_U', actionId: 'A_14', behavior: '0', outchar: 'û' }, - { keyCode: '14', key: 'K_E', actionId: 'A_2', behavior: '2', outchar: 'Ê' }, - { keyCode: '14', key: 'K_E', actionId: 'A_2', behavior: '1', outchar: 'Ê' }, - { keyCode: '34', key: 'K_I', actionId: 'A_3', behavior: '2', outchar: 'Î' }, - { keyCode: '34', key: 'K_I', actionId: 'A_3', behavior: '1', outchar: 'Î' }, - { keyCode: '31', key: 'K_O', actionId: 'A_5', behavior: '2', outchar: 'Ô' }, - { keyCode: '31', key: 'K_O', actionId: 'A_5', behavior: '1', outchar: 'Ô' }, - { keyCode: '32', key: 'K_U', actionId: 'A_6', behavior: '2', outchar: 'Û' }, - { keyCode: '32', key: 'K_U', actionId: 'A_6', behavior: '1', outchar: 'Û' }, - { keyCode: '0', key: 'K_A', actionId: 'A_9', behavior: '0', outchar: 'â' } - - ]; - const b1ModifierKeyArr: KeylayoutFileData[] = [ - { actionId: 'A_0', key: 'K_SPACE', behavior: '0', modifier: 'NCAPS', outchar: 'ˆ' }, - { actionId: 'A_0', key: 'K_SPACE', behavior: '1', modifier: 'CAPS', outchar: 'ˆ' }, - { actionId: 'A_0', key: 'K_SPACE', behavior: '2', modifier: 'NCAPS SHIFT', outchar: 'ˆ' }, - { actionId: 'A_0', key: 'K_SPACE', behavior: '2', modifier: 'SHIFT CAPS', outchar: 'ˆ' }, - { actionId: 'A_0', key: 'K_Z', behavior: '4', modifier: 'NCAPS SHIFT RALT', outchar: 'ˆ' }, - { actionId: 'A_0', key: 'K_9', behavior: '4', modifier: 'NCAPS SHIFT RALT', outchar: 'ˆ' }, - { actionId: 'A_0', key: 'K_COMMA', behavior: '4', modifier: 'NCAPS SHIFT RALT', outchar: 'ˆ' }, - { actionId: 'A_0', key: 'K_SPACE', behavior: '3', modifier: 'NCAPS RALT CTRL', outchar: 'ˆ' }, - { actionId: 'A_0', key: 'K_SPACE', behavior: '3', modifier: 'NCAPS CTRL', outchar: 'ˆ' }, - { actionId: 'A_1', key: 'K_A', behavior: '2', modifier: 'NCAPS SHIFT', outchar: 'Â' }, - { actionId: 'A_1', key: 'K_A', behavior: '2', modifier: 'SHIFT CAPS', outchar: 'Â' }, - { actionId: 'A_1', key: 'K_A', behavior: '1', modifier: 'CAPS', outchar: 'Â' }, - { actionId: 'A_10', key: 'K_E', behavior: '0', modifier: 'NCAPS', outchar: 'ê' }, - { actionId: 'A_11', key: 'K_I', behavior: '0', modifier: 'NCAPS', outchar: 'î' }, - { actionId: 'A_13', key: 'K_O', behavior: '0', modifier: 'NCAPS', outchar: 'ô' }, - { actionId: 'A_14', key: 'K_U', behavior: '0', modifier: 'NCAPS', outchar: 'û' }, - { actionId: 'A_2', key: 'K_E', behavior: '2', modifier: 'NCAPS SHIFT', outchar: 'Ê' }, - { actionId: 'A_2', key: 'K_E', behavior: '2', modifier: 'SHIFT CAPS', outchar: 'Ê' }, - { actionId: 'A_2', key: 'K_E', behavior: '1', modifier: 'CAPS', outchar: 'Ê' }, - { actionId: 'A_3', key: 'K_I', behavior: '2', modifier: 'NCAPS SHIFT', outchar: 'Î' }, - { actionId: 'A_3', key: 'K_I', behavior: '2', modifier: 'SHIFT CAPS', outchar: 'Î' }, - { actionId: 'A_3', key: 'K_I', behavior: '1', modifier: 'CAPS', outchar: 'Î' }, - { actionId: 'A_5', key: 'K_O', behavior: '2', modifier: 'NCAPS SHIFT', outchar: 'Ô' }, - { actionId: 'A_5', key: 'K_O', behavior: '2', modifier: 'SHIFT CAPS', outchar: 'Ô' }, - { actionId: 'A_5', key: 'K_O', behavior: '1', modifier: 'CAPS', outchar: 'Ô' }, - { actionId: 'A_6', key: 'K_U', behavior: '2', modifier: 'NCAPS SHIFT', outchar: 'Û' }, - { actionId: 'A_6', key: 'K_U', behavior: '2', modifier: 'SHIFT CAPS', outchar: 'Û' }, - { actionId: 'A_6', key: 'K_U', behavior: '1', modifier: 'CAPS', outchar: 'Û' }, - { actionId: 'A_9', key: 'K_A', behavior: '0', modifier: 'NCAPS', outchar: 'â' } - ]; - - [[b1KeycodeArr, b1ModifierKeyArr], - [[{ keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '0', modifier: '0', outchar: 'ˆ' }], [{ actionId: 'A_0', key: 'K_SPACE', behavior: '0', modifier: 'NCAPS', outchar: 'ˆ' }]], - [[{ keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '0', modifier: '', outchar: 'ˆ' }], [{ actionId: 'A_0', key: 'K_SPACE', behavior: '0', modifier: 'NCAPS', outchar: 'ˆ' }]], - [[{ keyCode: '49', key: 'K_SPACE', actionId: '', behavior: '0', modifier: '0', outchar: 'ˆ' }], [{ actionId: '', key: 'K_SPACE', behavior: '0', modifier: 'NCAPS', outchar: 'ˆ' }]], - [[{ keyCode: '49', key: '', actionId: 'A_0', behavior: '0', modifier: '0', outchar: 'ˆ' }], [{ actionId: 'A_0', key: '', behavior: '0', modifier: 'NCAPS', outchar: 'ˆ' }]], - [[{ keyCode: '', key: 'K_SPACE', actionId: 'A_0', behavior: '0', modifier: '0', outchar: 'ˆ' }], [{ actionId: 'A_0', key: 'K_SPACE', behavior: '0', modifier: 'NCAPS', outchar: 'ˆ' }]], - [[{ keyCode: '', key: '', actionId: '', behavior: '0', modifier: '', outchar: '' }], [{ actionId: '', key: '', behavior: '0', modifier: 'NCAPS', outchar: '' }]], - ].forEach(function (values) { - const isCapsUsed = true; - const stringIn = "getKeybehaviorModOutputArrayFromKeyActionbehaviorOutputArray(['" + "', '" + "', '" + values[0][0].keyCode + "', '" + values[0][0].key + "', '" + values[0][0].actionId + "', '" + values[0][0].modifier + "', '" + values[0][0].outchar + "'])"; - const stringOut = "['" + "', '" + "', '" + values[1][0].key + "', '" + values[1][0].actionId + "', '" + "', '" + values[1][0].modifier + "', '" + values[1][0].outchar + "']"; - - it((JSON.stringify(values[1]).length > 60) ? 'an array of objects should return an array of objects' : - stringIn.padEnd(74, " ") + ' should return ' + stringOut, async function () { - const result = sut.getKeyBehaviorModOutputArrayFromKeyActionBehaviorOutputArray(read, values[0], isCapsUsed); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); - }); - }); - - [[{ keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '0', modifier: '0', outchar: 'ˆ' }, { actionId: 'A_0', key: 'K_SPACE', behavior: '0', modifier: '', outchar: 'ˆ' }], - [{ keyCode: '', key: 'K_SPACE', actionId: 'A_0', behavior: '0', modifier: '0', outchar: 'ˆ' }, { actionId: 'A_0', key: 'K_SPACE', behavior: '0', modifier: '', outchar: 'ˆ' }], - [{ keyCode: '', key: '', actionId: '', behavior: '0', modifier: '', outchar: '' }, { actionId: '', key: '', behavior: '0', modifier: '', outchar: '' }], - ].forEach(function (values) { - const isCapsUsed = false; - const stringIn = "getKeybehaviorModOutputArrayFromKeyActionbehaviorOutputArray([ '" + values[0].keyCode + "', '" + values[0].key + "', '" + values[0].actionId + "', '" + values[0].modifier + "', '" + values[0].outchar + "'])"; - const stringOut = "['" + values[1].actionId + "', '" + "', '" + values[1].modifier + "', '" + values[1].key + "', '" + values[1].outchar + "']"; - - it(stringIn.padEnd(74, " ") + ' should return ' + stringOut, async function () { - const result = sut.getKeyBehaviorModOutputArrayFromKeyActionBehaviorOutputArray(read, [values[0]], isCapsUsed); - assert.equal(JSON.stringify(result), JSON.stringify([values[1]])); - }); - }); - - [[[], []], - [undefined, []], - [null, []], - ].forEach(function (values) { - const isCaps = true; - it(("getKeybehaviorModOutputArrayFromKeyActionbehaviorOutputArray([" + values[0] + "])").padEnd(74, " ") + ' should return ' + "[" + values[1] + "]", async function () { - const result = sut.getKeyBehaviorModOutputArrayFromKeyActionBehaviorOutputArray(read, values[0], isCaps); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); - }); - }); - }); - - describe('getActionStateOutputArrayFromActionState ', function () { - const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const sutR = new XkbFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); - const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); - [['1', [ - { "id": "A_0", "state": "1", "output": "ˆ" }, - { "id": "A_1", "state": "1", "output": "Â" }, - { "id": "A_10", "state": "1", "output": "ê" }, - { "id": "A_11", "state": "1", "output": "î" }, - { "id": "A_13", "state": "1", "output": "ô" }, - { "id": "A_14", "state": "1", "output": "û" }, - { "id": "A_2", "state": "1", "output": "Ê" }, - { "id": "A_3", "state": "1", "output": "Î" }, - { "id": "A_5", "state": "1", "output": "Ô" }, - { "id": "A_6", "state": "1", "output": "Û" }, - { "id": "A_9", "state": "1", "output": "â" } - ],], - ['2', [ - { "id": "A_0", "state": "2", "output": "`" }, - { "id": "A_1", "state": "2", "output": "À" }, - { "id": "A_10", "state": "2", "output": "è" }, - { "id": "A_11", "state": "2", "output": "ì" }, - { "id": "A_13", "state": "2", "output": "ò" }, - { "id": "A_14", "state": "2", "output": "ù" }, - { "id": "A_2", "state": "2", "output": "È" }, - { "id": "A_3", "state": "2", "output": "Ì" }, - { "id": "A_5", "state": "2", "output": "Ò" }, - { "id": "A_6", "state": "2", "output": "Ù" }, - { "id": "A_9", "state": "2", "output": "à" } - ],], - ['789', [],], - ['', [],], - [' ', [],], - [123, [],], - [null, [],], - [undefined, [],], - ].forEach(function (values) { - it((JSON.stringify(values[1]).length > 30) ? - ("getActionStateOutputArrayFromActionState('" + values[0] + "')").padEnd(60, " ") + ' should return an array of objects' : - ("getActionStateOutputArrayFromActionState('" + values[0] + "')").padEnd(60, " ") + ' should return ' + "'" + JSON.stringify(values[1]) + "'", async function () { - const result = sut.getActionStateOutputArrayFromActionState(read, String(values[0])); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); - }); - }); - }); - - describe('getActionOutputbehaviorKeyModiFromActionIDStateOutput ', function () { - const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const sutR = new XkbFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); - const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); - const converted = sut.convertBound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); - [ - ['A_1', 'A', true, - [{ "outchar": "A", "actionId": "A_1", "behavior": "1", "key": "K_A", "modifier": "CAPS" }, - { "outchar": "A", "actionId": "A_1", "behavior": "2", "key": "K_A", "modifier": "NCAPS SHIFT" }, - { "outchar": "A", "actionId": "A_1", "behavior": "2", "key": "K_A", "modifier": "SHIFT CAPS" }] - ], - ['A_1', 'A', false, - [{ "outchar": "A", "actionId": "A_1", "behavior": "1", "key": "K_A", "modifier": "CAPS" }, - { "outchar": "A", "actionId": "A_1", "behavior": "2", "key": "K_A", "modifier": "SHIFT" }, - { "outchar": "A", "actionId": "A_1", "behavior": "2", "key": "K_A", "modifier": "SHIFT CAPS" }] - ], - ['A_9', 'a', true, [{ "outchar": "a", "actionId": "A_9", "behavior": "0", "key": "K_A", "modifier": "NCAPS" }]], - ['A_9', 'a', false, [{ "outchar": "a", "actionId": "A_9", "behavior": "0", "key": "K_A", "modifier": "" }]], - ['A_9', 'a', , [{ "outchar": "a", "actionId": "A_9", "behavior": "0", "key": "K_A", "modifier": "" }]], - ['A_9', '', true, [{ "outchar": "", "actionId": "A_9", "behavior": "0", "key": "K_A", "modifier": "NCAPS" }]], - ['A_9', '', false, [{ "outchar": "", "actionId": "A_9", "behavior": "0", "key": "K_A", "modifier": "" }]], - ['', 'a', true, []], - ['', 'a', false, []], - ['', '', , []], - ].forEach(function (values) { - it((JSON.stringify(values[3]).length > 35) ? - ("getActionOutputbehaviorKeyModiFromActionIDStateOutput('" + values[0] + "', '" + values[1] + "', " + values[2] + ")").padEnd(67, " ") + ' should return an array of objects' : - ("getActionOutputbehaviorKeyModiFromActionIDStateOutput('" + values[0] + "', '" + values[1] + "', " + values[2] + ")").padEnd(67, " ") + ' should return ' + "'" + JSON.stringify(values[3]) + "'", async function () { - const result = sut.getActionOutputBehaviorKeyModiFromActionIDStateOutput(read, converted.modifiers, String(values[0]), String(values[1]), Boolean(values[2])); - assert.equal(JSON.stringify(result), JSON.stringify(values[3])); - }); - }); - }); - - describe('getKeyActionOutputArrayFromActionStateOutputArray ', function () { - const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const sutR = new XkbFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); - const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); - - const b6ActionIdArr: ActionStateOutput[] = [ - { "id": "A_0", "state": "1", "output": "ˆ" }, - { "id": "A_1", "state": "1", "output": "Â" }, - { "id": "A_10", "state": "1", "output": "ê" }, - { "id": "A_11", "state": "1", "output": "î" }, - { "id": "A_13", "state": "1", "output": "ô" }, - { "id": "A_14", "state": "1", "output": "û" }, - { "id": "A_2", "state": "1", "output": "Ê" }, - { "id": "A_3", "state": "1", "output": "Î" }, - { "id": "A_5", "state": "1", "output": "Ô" }, - { "id": "A_6", "state": "1", "output": "Û" }, - { "id": "A_9", "state": "1", "output": "â" } - ]; - - const b1KeycodeArr: KeylayoutFileData[] = [ - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '0', outchar: 'ˆ' }, - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '1', outchar: 'ˆ' }, - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '2', outchar: 'ˆ' }, - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '3', outchar: 'ˆ' }, - { keyCode: '6', key: 'K_Z', actionId: 'A_0', behavior: '4', outchar: 'ˆ' }, - { keyCode: '25', key: 'K_9', actionId: 'A_0', behavior: '4', outchar: 'ˆ' }, - { keyCode: '43', key: 'K_COMMA', actionId: 'A_0', behavior: '4', outchar: 'ˆ' }, - { keyCode: '0', key: 'K_A', actionId: 'A_1', behavior: '1', outchar: 'Â' }, - { keyCode: '0', key: 'K_A', actionId: 'A_1', behavior: '2', outchar: 'Â' }, - { keyCode: '14', key: 'K_E', actionId: 'A_10', behavior: '0', outchar: 'ê' }, - { keyCode: '34', key: 'K_I', actionId: 'A_11', behavior: '0', outchar: 'î' }, - { keyCode: '31', key: 'K_O', actionId: 'A_13', behavior: '0', outchar: 'ô' }, - { keyCode: '32', key: 'K_U', actionId: 'A_14', behavior: '0', outchar: 'û' }, - { keyCode: '14', key: 'K_E', actionId: 'A_2', behavior: '1', outchar: 'Ê' }, - { keyCode: '14', key: 'K_E', actionId: 'A_2', behavior: '2', outchar: 'Ê' }, - { keyCode: '34', key: 'K_I', actionId: 'A_3', behavior: '1', outchar: 'Î' }, - { keyCode: '34', key: 'K_I', actionId: 'A_3', behavior: '2', outchar: 'Î' }, - { keyCode: '31', key: 'K_O', actionId: 'A_5', behavior: '1', outchar: 'Ô' }, - { keyCode: '31', key: 'K_O', actionId: 'A_5', behavior: '2', outchar: 'Ô' }, - { keyCode: '32', key: 'K_U', actionId: 'A_6', behavior: '1', outchar: 'Û' }, - { keyCode: '32', key: 'K_U', actionId: 'A_6', behavior: '2', outchar: 'Û' }, - { keyCode: '0', key: 'K_A', actionId: 'A_9', behavior: '0', outchar: 'â' } - ]; - - [[b6ActionIdArr, b1KeycodeArr], - ].forEach(function (values) { - it(("getKeyActionOutputArrayFromActionStateOutputArray([['" + JSON.stringify(values[0]) + "'],..])").padEnd(73, " ") + '1 should return an array of objects', async function () { - const result = sut.getKeyActionOutputArrayFromActionStateOutputArray(read, values[0] as ActionStateOutput[]); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); - }); - }); - - const oneEntryResult = [ - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '0', outchar: 'ˆ' }, - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '1', outchar: 'ˆ' }, - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '2', outchar: 'ˆ' }, - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '3', outchar: 'ˆ' }, - { keyCode: '6', key: 'K_Z', actionId: 'A_0', behavior: '4', outchar: 'ˆ' }, - { keyCode: '25', key: 'K_9', actionId: 'A_0', behavior: '4', outchar: 'ˆ' }, - { keyCode: '43', key: 'K_COMMA', actionId: 'A_0', behavior: '4', outchar: 'ˆ' } - ]; - - const oneEntryResultNoOutput = [ - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '0', outchar: '' }, - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '1', outchar: '' }, - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '2', outchar: '' }, - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '3', outchar: '' }, - { keyCode: '6', key: 'K_Z', actionId: 'A_0', behavior: '4', outchar: '' }, - { keyCode: '25', key: 'K_9', actionId: 'A_0', behavior: '4', outchar: '' }, - { keyCode: '43', key: 'K_COMMA', actionId: 'A_0', behavior: '4', outchar: '' }, - ]; - - [[[{ "id": "A_0", "state": "1", "output": "ˆ" }], oneEntryResult], - [[{ "id": "A_0", "state": "1", "output": "" }], oneEntryResultNoOutput], - [[{ "id": "A_0", "state": "", "output": "ˆ" }], oneEntryResult], - ].forEach(function (values) { - it(("getKeyActionOutputArrayFromActionStateOutputArray(['" + JSON.stringify(values[0]) + "'])").padEnd(73, " ") + ' should return an array of objects', async function () { - const result = sut.getKeyActionOutputArrayFromActionStateOutputArray(read, values[0] as ActionStateOutput[]); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); - }); - }); - - [[[{ "id": "", "state": "1", "output": "ˆ" }], []], - [[{ "id": "", "state": "", "output": "" }], []], - [[{ "id": " ", "state": " ", "output": "" }], []], - - ].forEach(function (values) { - it(("getKeyActionOutputArrayFromActionStateOutputArray(" + JSON.stringify(values[0]) + ")").padEnd(73, " ") + ' should return ' + "'[" + JSON.stringify(values[1]) + "]'", async function () { - const result = sut.getKeyActionOutputArrayFromActionStateOutputArray(read, values[0] as ActionStateOutput[]); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); - }); - }); - - [[, []], - [undefined, []], - [null, []], - ].forEach(function (values) { - it(("getKeyActionOutputArrayFromActionStateOutputArray(" + JSON.stringify(values[0]) + ")").padEnd(73, " ") + ' should return ' + "'[" + JSON.stringify(values[1]) + "]'", async function () { - const result = sut.getKeyActionOutputArrayFromActionStateOutputArray(read, values[0] as ActionStateOutput[]); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); - }); - }); - }); - - describe('createRuleData ', function () { - const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const sutR = new XkbFileReader(compilerTestCallbacks); - [ - [ - ['../data/Test_C0.keylayout'], - [new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_A', new TextEncoder().encode('a')), - new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_A', new TextEncoder().encode('A')), - new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_S', new TextEncoder().encode('s')), - new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_D', new TextEncoder().encode('d'))] - ], - [ - ['../data/Test_C1.keylayout'], - [new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_S', new TextEncoder().encode('s')), - new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_S', new TextEncoder().encode('S'))] - ], - [ - ['../data/Test_C2.keylayout'], - [new Rule("C2", '', '', 0, 0, 'NCAPS', 'K_U', 1, 1, 'CAPS', 'K_A', new TextEncoder().encode('Â'))], - ], - [ - ['../data/Test_C3.keylayout'], - [new Rule("C3", 'NCAPS SHIFT', 'K_D', 2, 1, 'NCAPS', 'K_U', 1, 2, 'CAPS', 'K_A', new TextEncoder().encode('Â'))] - ], - - [ - ['../data/Test_C3_several.keylayout'], - [new Rule("C3", 'NCAPS RALT', 'K_8', 3, 1, 'CAPS', 'K_U', 1, 3, 'NCAPS', 'K_A', new TextEncoder().encode('â')), - new Rule("C3", 'NCAPS RALT', 'K_8', 3, 0, 'CAPS', 'K_U', 1, 0, 'NCAPS RALT', 'K_A', new TextEncoder().encode('â')), - new Rule("C3", 'NCAPS RALT', 'K_8', 3, 0, 'NCAPS RALT', 'K_U', 2, 2, 'NCAPS', 'K_A', new TextEncoder().encode('â')), - new Rule("C3", 'NCAPS RALT', 'K_8', 3, 0, 'NCAPS RALT', 'K_U', 2, 0, 'NCAPS RALT', 'K_A', new TextEncoder().encode('â'))] - ], - [ - ['../data/Test_C0_C1_C2_C3.keylayout'], - [new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_A', new TextEncoder().encode('A')), - new Rule("C2", '', '', 0, 0, 'NCAPS RALT', 'K_EQUAL', 1, 1, 'CAPS', 'K_D', new TextEncoder().encode('Â')), - new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_S', new TextEncoder().encode('S')), - new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'NCAPS RALT', 'K_U', new TextEncoder().encode('S')), - new Rule("C3", 'NCAPS RALT', 'K_8', 6, 1, 'CAPS', 'K_S', 2, 6, 'CAPS', 'K_D', new TextEncoder().encode('Â')), - new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'CAPS', 'K_U', 3, 3, 'CAPS', 'K_D', new TextEncoder().encode('Â')), - new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'NCAPS RALT', 'K_S', 4, 4, 'CAPS', 'K_D', new TextEncoder().encode('Â')), - new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'NCAPS RALT', 'K_U', 5, 5, 'CAPS', 'K_D', new TextEncoder().encode('Â')), - new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_S', new TextEncoder().encode('S')), - new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'NCAPS RALT', 'K_U', new TextEncoder().encode('S')), - new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'CAPS', 'K_S', 2, 0, 'CAPS', 'K_D', new TextEncoder().encode('Â')), - new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'CAPS', 'K_U', 3, 0, 'CAPS', 'K_D', new TextEncoder().encode('Â')), - new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'NCAPS RALT', 'K_S', 4, 0, 'CAPS', 'K_D', new TextEncoder().encode('Â')), - new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'NCAPS RALT', 'K_U', 5, 0, 'CAPS', 'K_D', new TextEncoder().encode('Â')), - new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_U', new TextEncoder().encode('U')),] - ], - ].forEach(function (values: any) { - it('data of \'' + values[0] + "' passed into createRuleData() " + 'should create an array of rules', async function () { - const inputFilename = makePathToFixture(values[0][0]); - const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); - const processedData = sut.convertBound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); - assert.deepEqual(processedData.rules[0], values[1][0]); - }); - }); - }); - -}); From 9a9d33bb50845205e9c0fd30623038a4605f680f Mon Sep 17 00:00:00 2001 From: Sabine Date: Mon, 27 Apr 2026 18:12:34 +0200 Subject: [PATCH 234/251] feat(developer): adapt elements of keylayout-xml boxArray parsing ( tests, validate of and error msg for different amount of keymap<->keymapSelect) first version keylayout.dtd, keylayout.xsd, keylayout.schema.json --- .../src/types/keylayout/keylayout-xml.ts | 57 ++++----- .../src/kmc-convert/src/converter-messages.ts | 6 + .../keylayout-to-kmn/keylayout-file-reader.ts | 108 +++++++++++++++--- .../keylayout-to-kmn-converter.ts | 21 ++-- ...yMapThanKeyMapselectAndJisERROR.keylayout} | 31 +++-- ...moreKeyMapThanKeyMapselectERROR.keylayout} | 6 +- ...moreKeymapSelectThanKeymapERROR.keylayout} | 13 +-- .../test/keylayout-to-kmn-converter.tests.ts | 4 +- .../keylayout/dtd/keylayout.dtd | 79 +++++++++---- .../keylayout/dtd/keylayout.xsd | 2 +- .../keylayout/keylayout.schema.json | 82 ++++++------- 11 files changed, 269 insertions(+), 140 deletions(-) rename developer/src/kmc-convert/test/data/{Test_DifferentAmountMapSelect_KeyMapERROR.keylayout => Test_moreKeyMapThanKeyMapselectAndJisERROR.keylayout} (68%) rename developer/src/kmc-convert/test/data/{Test_DifferentAmountOfMapSelectInKeyMapERROR_1.keylayout => Test_moreKeyMapThanKeyMapselectERROR.keylayout} (97%) rename developer/src/kmc-convert/test/data/{Test_DifferentAmountOfMapSelectInKeyMapERROR.keylayout => Test_moreKeymapSelectThanKeymapERROR.keylayout} (88%) diff --git a/developer/src/common/web/utils/src/types/keylayout/keylayout-xml.ts b/developer/src/common/web/utils/src/types/keylayout/keylayout-xml.ts index a816af701f2..5da06e96baf 100644 --- a/developer/src/common/web/utils/src/types/keylayout/keylayout-xml.ts +++ b/developer/src/common/web/utils/src/types/keylayout/keylayout-xml.ts @@ -26,20 +26,19 @@ export interface KL_Keyboard { /** * attributes of the root element */ - group?: string; - id?: string; - name?: string; - maxoutS?: string; + group: string; + id: string; + name: string; + maxout?: string; /** * , , , , * the 5 main elements. */ - //layoutsMM: KL_Layouts[]; - layouts?: KL_Layouts[]; - modifierMap?: KL_ModifierMap[]; - keyMapSet?: KL_KeyMapSet[]; - actions?: KL_Actions[]; - terminators?: KL_Terminators[]; + layouts: KL_Layouts[]; + modifierMap: KL_ModifierMap[]; + keyMapSet: KL_KeyMapSet[]; + actions?: KL_Actions; + terminators?: KL_Terminators; }; export interface KL_Layouts { @@ -47,7 +46,7 @@ export interface KL_Layouts { * the sub element of , * containing information about the use of (different) mapSet and modifiers */ - layouts?: KL_Layout; + layout: KL_Layout[]; }; export interface KL_Layout { @@ -58,22 +57,22 @@ export interface KL_Layout { * ( ) * referencing */ - first?: string; - last?: string; - mapSet?: string; - modifiers?: string; + first: string; + last: string; + mapSet: string; + modifiers: string; }; export interface KL_ModifierMap { /** * attributes of the element */ - id?: string; - defaultIndex?: string; + id: string; + defaultIndex: string; /** * the sub element of */ - keyMapSelect?: KL_KeyMapSelect[]; + keyMapSelect: KL_KeyMapSelect[]; }; export interface KL_KeyMapSelect { @@ -82,11 +81,11 @@ export interface KL_KeyMapSelect { * containing a set of modifier combinations for a behavior * referencing */ - mapIndex?: string; + mapIndex: string; /** * the sub element of */ - modifier?: KL_Modifier[]; + modifier: KL_Modifier[]; }; export interface KL_Modifier { @@ -94,7 +93,7 @@ export interface KL_Modifier { * attributes of the element * containing one combination of modifier keys */ - keys?: string; + keys: string; }; export interface KL_KeyMapSet { @@ -102,11 +101,11 @@ export interface KL_KeyMapSet { * attributes of the element * referencing */ - id?: string; + id: string; /** * the sub element of */ - keyMap?: KL_KeyMap[]; + keyMap: KL_KeyMap[]; }; export interface KL_KeyMap { @@ -114,11 +113,13 @@ export interface KL_KeyMap { * attributes of the element * referencing */ - index?: string; + index: string; + baseMapSet?: string; + baseIndex?: string; /** * the sub element of */ - key?: KL_Key[]; + key: KL_Key[]; }; export interface KL_Key { @@ -126,8 +127,8 @@ export interface KL_Key { * attributes of the element * containing a keycode and its output or action */ - code?: string; - action?: string; + code: string; + action?: string; //TODO-KMC-CONVERT: Support sub-element 'anonymous actions' output?: string; }; @@ -135,7 +136,7 @@ export interface KL_Actions { /** * the sub element of */ - action?: KL_Action[]; + action: KL_Action[]; }; export interface KL_Action { diff --git a/developer/src/kmc-convert/src/converter-messages.ts b/developer/src/kmc-convert/src/converter-messages.ts index dbb0108db7a..43ad86eeead 100644 --- a/developer/src/kmc-convert/src/converter-messages.ts +++ b/developer/src/kmc-convert/src/converter-messages.ts @@ -53,6 +53,12 @@ export class ConverterMessages { `Input file could not be read.` ); + static ERROR_UnableToParse = SevError | 0x000C; + static Error_UnableToParse = () => m( + this.ERROR_UnableToParse, + `Input data could not be parsed.` + ); + static ERROR_UnsupportedCharactersDetected = SevError | 0x0007; static Error_UnsupportedCharactersDetected = (o: { inputFilename: string, keymapIndex: string, key: string, KeyName: string, output: string; }) => m( this.ERROR_UnsupportedCharactersDetected, diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts index bf07249f019..3d6fb711a9d 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts @@ -16,10 +16,71 @@ export class KeylayoutFileReader { constructor(private callbacks: CompilerCallbacks /*,private options: CompilerOptions*/) { }; + + /** + * @brief helper function to find a specific keyMap index in a keyMapSet + * @param jsonObj the read keylayout data to be checked + * @param keyMapSelect the keyMapSelect element to find in keyMapSet + * @return true if the keyMapSet element is found, false if not + */ + public findMapIndexinKeymap(jsonObj: any, keyMapSelect: any): boolean { + for (const keyMapSet of jsonObj.keyboard.keyMapSet) { + for (const keyMap of keyMapSet.keyMap) { + if (keyMap['index'] === keyMapSelect) { + return true; + } + } + } + return false; + } + + /** + * @brief helper function to find a specific keyMapSelect index in a modifierMap + * @param jsonObj the read keylayout data to be checked + * @param keyMap the keyMap element to find in modifierMap + * @return true if the keyMap element is found, false if not + */ + public findIndexinKeymapSelect(jsonObj: any, keyMap: any): boolean { + for (const modifierMap of jsonObj.keyboard.modifierMap) { + for (const keyMapSelect of modifierMap.keyMapSelect) { + if (keyMapSelect['mapIndex'] === keyMap) { + return true; + } + } + } + return false; + } + + /** + * @brief member function checking if all keyMapSelect elements have a corresponding keyMap + * element in the .keylayout file (if not, the .keylayout file is invalid and will not be converted) + * see TN2056 (https://developer.apple.com/library/archive/technotes/tn2056/_index.html#//apple_ref/doc/uid/DTS10003085-CH1-SUBSECTION7) + * @param jsonObj the read keylayout data to be checked + * @return true if all keyMapSelect elements have a corresponding keyMap element, false if not + */ + public checkForCorrespondingElements(jsonObj: any): boolean { + let available = true; + + // check if all keyMapSelect elements have a corresponding keyMap element in the .keylayout file + for (const modifierMap of jsonObj.keyboard.modifierMap) { + for (const keyMapSelect of modifierMap.keyMapSelect) { + available = available && this.findMapIndexinKeymap(jsonObj, keyMapSelect['mapIndex']); + } + } + // check if all keyMap elements have a corresponding keyMapSelect element in the .keylayout file + for (const keyMapSet of jsonObj.keyboard.keyMapSet) { + for (const keyMap of keyMapSet.keyMap) { + available = available && this.findIndexinKeymapSelect(jsonObj, keyMap['index']); + } + } + return available; + } + + /** * @returns true if valid, false if invalid */ - public validate(source: Keylayout.KeylayoutXMLSourceFile): boolean { + public validate(source: Keylayout.KeylayoutXMLSourceFile, inputFilename: string): boolean { if (!SchemaValidators.default.keylayout(source)) { for (const err of (SchemaValidators.default.keylayout).errors) { this.callbacks.reportMessage(DeveloperUtilsMessages.Error_InvalidXml({ @@ -28,6 +89,12 @@ export class KeylayoutFileReader { } return false; } + + // check if all keyMapSelect elements have a corresponding keyMap element in the .keylayout file + if (!this.checkForCorrespondingElements(source)) { + this.callbacks.reportMessage(ConverterMessages.Error_InvalidFile({ errorText: inputFilename })); + return null; + } return true; } @@ -38,33 +105,39 @@ export class KeylayoutFileReader { */ public boxArray(source: any) { + boxXmlArray(source, 'modifierMap'); boxXmlArray(source, 'keyMapSet'); - boxXmlArray(source.layouts, 'layout'); - boxXmlArray(source?.modifierMap, 'keyMapSelect'); + if (source.layouts) { + boxXmlArray(source.layouts, 'layout'); + } - for (const keyMapSelect of source?.modifierMap?.keyMapSelect) { - boxXmlArray(keyMapSelect, 'modifier'); + if (source.modifierMap) { + for (const modifierMap of source.modifierMap) { + boxXmlArray(modifierMap, 'keyMapSelect'); + if (modifierMap.keyMapSelect) { + for (const keyMapSelect of modifierMap.keyMapSelect) { + boxXmlArray(keyMapSelect, 'modifier'); + } + } + } } - for (const keyMapSet of source?.keyMapSet) { + for (const keyMapSet of source.keyMapSet) { boxXmlArray(keyMapSet, 'keyMap'); for (const keyMap of keyMapSet.keyMap) { boxXmlArray(keyMap, 'key'); } } - boxXmlArray(source?.actions, 'action'); - for (const action of source?.actions?.action) { - boxXmlArray(action, 'when'); - } - - boxXmlArray(source.terminators, 'when'); - for (const action of source?.actions?.action) { - boxXmlArray(action, 'when'); + if (source.actions) { + boxXmlArray(source.actions, 'action'); + for (const action of source.actions.action) { + boxXmlArray(action, 'when'); + } } - return source; + boxXmlArray(source?.terminators, 'when'); } /** @@ -78,6 +151,11 @@ export class KeylayoutFileReader { try { const data = new TextDecoder().decode(source); const jsonObj = new KeymanXMLReader('keylayout').parse(data) as Keylayout.KeylayoutXMLSourceFile; + + if (!jsonObj?.keyboard) { + this.callbacks.reportMessage(ConverterMessages.Error_UnableToParse()); + return null; + } this.boxArray(jsonObj.keyboard); // jsonObj now contains arrays; no single fields return jsonObj; } diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index a09ec52f50f..074c76be370 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -124,7 +124,7 @@ export class KeylayoutToKmnConverter { return null; } try { - if (!KeylayoutReader.validate(jsonO)) { + if (!KeylayoutReader.validate(jsonO,inputFilename)) { return null; } } catch (e) { @@ -169,10 +169,10 @@ export class KeylayoutToKmnConverter { return null; } // create an array of modifier combinations and store in dataObject - for (let j = 0; j < jsonObj.keyboard.modifierMap.keyMapSelect.length; j++) { + for (let j = 0; j < jsonObj.keyboard.modifierMap[0].keyMapSelect.length; j++) { const singleModifierSet: string[] = []; - for (let k = 0; k < jsonObj.keyboard.modifierMap.keyMapSelect[j].modifier.length; k++) { - singleModifierSet.push(jsonObj.keyboard.modifierMap.keyMapSelect[j].modifier[k]['keys']); + for (let k = 0; k < jsonObj.keyboard.modifierMap[0].keyMapSelect[j].modifier.length; k++) { + singleModifierSet.push(jsonObj.keyboard.modifierMap[0].keyMapSelect[j].modifier[k]['keys']); } modifierBehavior.push(singleModifierSet); } @@ -203,16 +203,9 @@ export class KeylayoutToKmnConverter { let dkCounterC2: number = 0; let actionId: string; - // check if we use CAPS in a modifier throughout the .keylayout file. In this case we need to add NCAPS + // check if we use CAPS in a modifier throughout the .keylayout file. In this case we need to add NCAPS at places not specifying CAPS const isCapsused = (this.checkIfCapsIsUsed(dataUkelele.modifiers)); - // if there are different amounts of keyMapSelect vs keyMap - if (jsonObj.keyboard.modifierMap?.keyMapSelect.length !== jsonObj.keyboard.keyMapSet[0].keyMap.length) { - const errorText = dataUkelele.keylayoutFilename; - this.callbacks.reportMessage(ConverterMessages.Error_InvalidFile({ errorText })); - return null; - } - for (let j = 0; j <= KeylayoutToKmnConverter.MAX_KEY_IDENTIFIER; j++) { // loop behaviors (in ukelele it is possible to define multiple modifier combinations that behave in the same way) @@ -928,12 +921,12 @@ export class KeylayoutToKmnConverter { if (!((search === undefined) || (search === null) || (search.length === 0))) { for (let i = 0; i < search.length; i++) { const behaviorIdx: number = Number(search[i].behavior); - for (let j = 0; j < data.keyboard.modifierMap.keyMapSelect[behaviorIdx].modifier.length; j++) { + for (let j = 0; j < data.keyboard.modifierMap[0].keyMapSelect[behaviorIdx].modifier.length; j++) { const singleDataSet = { actionId: search[i].actionId, key: search[i].key, behavior: search[i].behavior, - modifier: this.createKmnModifier(data.keyboard.modifierMap.keyMapSelect[behaviorIdx].modifier[j]['keys'], isCAPSused), + modifier: this.createKmnModifier(data.keyboard.modifierMap[0].keyMapSelect[behaviorIdx].modifier[j]['keys'], isCAPSused), outchar: search[i].outchar, }; keyBehaviorModOutput.push(singleDataSet); diff --git a/developer/src/kmc-convert/test/data/Test_DifferentAmountMapSelect_KeyMapERROR.keylayout b/developer/src/kmc-convert/test/data/Test_moreKeyMapThanKeyMapselectAndJisERROR.keylayout similarity index 68% rename from developer/src/kmc-convert/test/data/Test_DifferentAmountMapSelect_KeyMapERROR.keylayout rename to developer/src/kmc-convert/test/data/Test_moreKeyMapThanKeyMapselectAndJisERROR.keylayout index 15b8a9a72ca..13be153d756 100644 --- a/developer/src/kmc-convert/test/data/Test_DifferentAmountMapSelect_KeyMapERROR.keylayout +++ b/developer/src/kmc-convert/test/data/Test_moreKeyMapThanKeyMapselectAndJisERROR.keylayout @@ -5,10 +5,10 @@ Data generated August 1st 2025 Generated by S. Schmitt - Test_DifferentAmountMapSelect_KeyMapERROR + more keyMapSelect than KeyMap --> - + @@ -21,11 +21,8 @@ - - - - + @@ -34,7 +31,6 @@ - @@ -51,6 +47,27 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/Test_DifferentAmountOfMapSelectInKeyMapERROR_1.keylayout b/developer/src/kmc-convert/test/data/Test_moreKeyMapThanKeyMapselectERROR.keylayout similarity index 97% rename from developer/src/kmc-convert/test/data/Test_DifferentAmountOfMapSelectInKeyMapERROR_1.keylayout rename to developer/src/kmc-convert/test/data/Test_moreKeyMapThanKeyMapselectERROR.keylayout index 38621b27002..3bd9b5ba491 100644 --- a/developer/src/kmc-convert/test/data/Test_DifferentAmountOfMapSelectInKeyMapERROR_1.keylayout +++ b/developer/src/kmc-convert/test/data/Test_moreKeyMapThanKeyMapselectERROR.keylayout @@ -20,8 +20,8 @@ - - + + @@ -67,7 +67,7 @@ - + diff --git a/developer/src/kmc-convert/test/data/Test_DifferentAmountOfMapSelectInKeyMapERROR.keylayout b/developer/src/kmc-convert/test/data/Test_moreKeymapSelectThanKeymapERROR.keylayout similarity index 88% rename from developer/src/kmc-convert/test/data/Test_DifferentAmountOfMapSelectInKeyMapERROR.keylayout rename to developer/src/kmc-convert/test/data/Test_moreKeymapSelectThanKeymapERROR.keylayout index 2fe9c05e76d..25d178237cb 100644 --- a/developer/src/kmc-convert/test/data/Test_DifferentAmountOfMapSelectInKeyMapERROR.keylayout +++ b/developer/src/kmc-convert/test/data/Test_moreKeymapSelectThanKeymapERROR.keylayout @@ -12,7 +12,7 @@ - + @@ -20,13 +20,13 @@ - + - + - - + + @@ -34,7 +34,6 @@ - @@ -55,7 +54,7 @@ - + diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index f99fc03e510..c2f9fa53525 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -57,7 +57,9 @@ describe('KeylayoutToKmnConverter', function () { describe('RunTestFiles resulting in errors ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); [ - [makePathToFixture('../data/Test_DifferentAmountOfMapSelectInKeyMapERROR.keylayout')], + [makePathToFixture('../data/Test_moreKeyMapThanKeyMapselectERROR.keylayout')], + [makePathToFixture('../data/Test_moreKeyMapThanKeyMapselectAndJisERROR.keylayout')], + [makePathToFixture('../data/Test_moreKeyMapThanKeyMapselectERROR.keylayout')], [makePathToFixture('../data/Test_MissingkeyERROR.keylayout')], [makePathToFixture('../data/Test_MissingkeyMapERROR.keylayout')], [makePathToFixture('../data/Test_MissingLayoutsERROR.keylayout')], diff --git a/resources/standards-data/keylayout/dtd/keylayout.dtd b/resources/standards-data/keylayout/dtd/keylayout.dtd index a670078a447..1e7064c6b24 100644 --- a/resources/standards-data/keylayout/dtd/keylayout.dtd +++ b/resources/standards-data/keylayout/dtd/keylayout.dtd @@ -5,28 +5,57 @@ * * This DTD describes a technical preview of Keylayout Data --> - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/standards-data/keylayout/dtd/keylayout.xsd b/resources/standards-data/keylayout/dtd/keylayout.xsd index f9aea8c67d4..48e84f3f156 100644 --- a/resources/standards-data/keylayout/dtd/keylayout.xsd +++ b/resources/standards-data/keylayout/dtd/keylayout.xsd @@ -22,7 +22,7 @@ - + diff --git a/resources/standards-data/keylayout/keylayout.schema.json b/resources/standards-data/keylayout/keylayout.schema.json index 41b9fa6b2ed..e42b23c290f 100644 --- a/resources/standards-data/keylayout/keylayout.schema.json +++ b/resources/standards-data/keylayout/keylayout.schema.json @@ -147,48 +147,52 @@ "type": "string" }, "modifierMap": { - "additionalProperties": false, - "properties": { - "defaultIndex": { - "type": "string" - }, - "id": { - "type": "string" - }, - "keyMapSelect": { - "items": { - "additionalProperties": false, - "properties": { - "mapIndex": { - "type": "string" - }, - "modifier": { - "items": { - "additionalProperties": false, - "properties": { - "keys": { - "type": "string" - } - }, - "type": "object" + "items": { + "additionalProperties": false, + "properties": { + "defaultIndex": { + "type": "string" + }, + "id": { + "type": "string" + }, + "keyMapSelect": { + "items": { + "additionalProperties": false, + "properties": { + "mapIndex": { + "type": "string" }, - "minItems": 1, - "type": "array" - } + "modifier": { + "items": { + "additionalProperties": false, + "properties": { + "keys": { + "type": "string" + } + }, + "type": "object" + }, + "minItems": 1, + "type": "array" + } + }, + "required": [ + "modifier" + ], + "type": "object" }, - "required": [ - "modifier" - ], - "type": "object" - }, - "minItems": 1, - "type": "array" - } + "minItems": 1, + "type": "array" + } + }, + "required": [ + "keyMapSelect" + ], + "type": "object" }, - "required": [ - "keyMapSelect" - ], - "type": "object" + "minItems": 1, + "type": "array" }, "name": { "type": "string" From 461fdd86c4c8f2bedbb2e405dc14f1d83682c835 Mon Sep 17 00:00:00 2001 From: Sabine Date: Tue, 28 Apr 2026 19:27:21 +0200 Subject: [PATCH 235/251] feat(developer): replace all any-datatypes add checkForCorrespondingElements() to validate() min/maxOccurs added in keylayout.xsd edited keylayout.dtd (possible remaining squiggle lines will be addressed in PR#15860 --- .../src/types/keylayout/keylayout-xml.ts | 2 + .../keylayout-to-kmn/keylayout-file-reader.ts | 15 +- .../keylayout-to-kmn-converter.ts | 168 ++++++++++-------- .../src/kmc-convert/test/data/keylayout.dtd | 89 ++++++++-- .../test/keylayout-to-kmn-converter.tests.ts | 21 +-- .../kmc-convert/test/kmn-file-writer.tests.ts | 24 +-- .../keylayout/dtd/keylayout.xsd | 9 +- 7 files changed, 194 insertions(+), 134 deletions(-) diff --git a/developer/src/common/web/utils/src/types/keylayout/keylayout-xml.ts b/developer/src/common/web/utils/src/types/keylayout/keylayout-xml.ts index 5da06e96baf..57760aae633 100644 --- a/developer/src/common/web/utils/src/types/keylayout/keylayout-xml.ts +++ b/developer/src/common/web/utils/src/types/keylayout/keylayout-xml.ts @@ -158,7 +158,9 @@ export interface KL_When { * to define which output or next is followed by a state */ state?: string; + through?: string; output?: string; + multiplier?: string; next?: string; }; diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts index 3d6fb711a9d..26ac23a3a1a 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts @@ -11,6 +11,7 @@ import { CompilerCallbacks, DeveloperUtilsMessages, Keylayout, KeymanXMLReader } import { util, SchemaValidators } from '@keymanapp/common-types'; import { ConverterMessages } from '../converter-messages.js'; import boxXmlArray = util.boxXmlArray; +import { KL_KeyMapSelect,KL_KeyMap } from "../../../common/web/utils/src/types/keylayout/keylayout-xml.js"; export class KeylayoutFileReader { @@ -23,10 +24,10 @@ export class KeylayoutFileReader { * @param keyMapSelect the keyMapSelect element to find in keyMapSet * @return true if the keyMapSet element is found, false if not */ - public findMapIndexinKeymap(jsonObj: any, keyMapSelect: any): boolean { + public findMapIndexinKeymap(jsonObj: Keylayout.KeylayoutXMLSourceFile, keyMapSelect: KL_KeyMapSelect): boolean { for (const keyMapSet of jsonObj.keyboard.keyMapSet) { for (const keyMap of keyMapSet.keyMap) { - if (keyMap['index'] === keyMapSelect) { + if (keyMap['index'] === keyMapSelect.mapIndex) { return true; } } @@ -40,10 +41,10 @@ export class KeylayoutFileReader { * @param keyMap the keyMap element to find in modifierMap * @return true if the keyMap element is found, false if not */ - public findIndexinKeymapSelect(jsonObj: any, keyMap: any): boolean { + public findIndexinKeymapSelect(jsonObj: Keylayout.KeylayoutXMLSourceFile, keyMap: KL_KeyMap): boolean { for (const modifierMap of jsonObj.keyboard.modifierMap) { for (const keyMapSelect of modifierMap.keyMapSelect) { - if (keyMapSelect['mapIndex'] === keyMap) { + if (keyMapSelect['mapIndex'] === keyMap.index) { return true; } } @@ -58,19 +59,19 @@ export class KeylayoutFileReader { * @param jsonObj the read keylayout data to be checked * @return true if all keyMapSelect elements have a corresponding keyMap element, false if not */ - public checkForCorrespondingElements(jsonObj: any): boolean { + public checkForCorrespondingElements(jsonObj: Keylayout.KeylayoutXMLSourceFile): boolean { let available = true; // check if all keyMapSelect elements have a corresponding keyMap element in the .keylayout file for (const modifierMap of jsonObj.keyboard.modifierMap) { for (const keyMapSelect of modifierMap.keyMapSelect) { - available = available && this.findMapIndexinKeymap(jsonObj, keyMapSelect['mapIndex']); + available = available && this.findMapIndexinKeymap(jsonObj, keyMapSelect); } } // check if all keyMap elements have a corresponding keyMapSelect element in the .keylayout file for (const keyMapSet of jsonObj.keyboard.keyMapSet) { for (const keyMap of keyMapSet.keyMap) { - available = available && this.findIndexinKeymapSelect(jsonObj, keyMap['index']); + available = available && this.findIndexinKeymapSelect(jsonObj, keyMap); } } return available; diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 074c76be370..9db2deb84ef 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -48,7 +48,7 @@ export interface KeylayoutFileData { actionId?: string; keyCode?: string; key?: string; - behavior?: string; + behavior: string; modifier?: string; outchar?: string; }; @@ -124,7 +124,7 @@ export class KeylayoutToKmnConverter { return null; } try { - if (!KeylayoutReader.validate(jsonO,inputFilename)) { + if (!KeylayoutReader.validate(jsonO, inputFilename)) { return null; } } catch (e) { @@ -150,7 +150,7 @@ export class KeylayoutToKmnConverter { * @param jsonObj containing filename, behaviorand rules of a json object * @return an ProcessedData containing all data ready to print out */ - private convert(jsonObj: any, inputfilename: string, outputFilename?: string): ProcessedData { + private convert(jsonObj: Keylayout.KeylayoutXMLSourceFile, inputfilename: string, outputFilename?: string): ProcessedData { // modifiers for each behavior const modifierBehavior: string[][] = []; @@ -196,7 +196,7 @@ export class KeylayoutToKmnConverter { * @param jsonObj: json Object containing all data read from a keylayout file * @return an object containing the name of the input file, an array of behaviors and a populated array of Rules[] */ - public createRuleData(dataUkelele: ProcessedData, jsonObj: any): ProcessedData { + public createRuleData(dataUkelele: ProcessedData, jsonObj: Keylayout.KeylayoutXMLSourceFile): ProcessedData { const rules: Rule[] = []; let dkCounterC3: number = 0; @@ -260,7 +260,7 @@ export class KeylayoutToKmnConverter { } else if (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['action'] !== undefined) { - actionId = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['action']; + actionId = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['action'] ?? ""; // ............................................................................................................................... // case C1: action + state none + output ......................................................................................... // C1 see: https://docs.google.com/document/d/12J3NGO6RxIthCpZDTR8FYSRjiMgXJDLwPY2z9xqKzJ0/edit?tab=t.0#heading=h.g7jwx3lx0ydd ... @@ -317,7 +317,7 @@ export class KeylayoutToKmnConverter { this.callbacks.reportMessage(ConverterMessages.Error_UndefinedActionDetected({ inputFilename: jsonObj.keyboard['name'] + ".keylayout", action: actionId, - KeyName: this.mapUkeleleKeycodeToVK(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['code']), + KeyName: this.mapUkeleleKeycodeToVK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['code'])), keymapIndex: jsonObj.keyboard.keyMapSet[0].keyMap[i]['index'] })); return null; @@ -325,13 +325,14 @@ export class KeylayoutToKmnConverter { // with actionId from above loop all 'action' and search for a state(none)-next-pair ............................................................................................................ // e.g. in Block 5: find for action id a18 ...................................................................................................................... - for (let l = 0; l < jsonObj.keyboard.actions.action[b1ActionIndex].when.length; l++) { - if ((jsonObj.keyboard.actions.action[b1ActionIndex].when[l]['state'] === "none") // find "none" - && (jsonObj.keyboard.actions.action[b1ActionIndex].when[l]['next'] !== undefined)) { // find "next" + if (jsonObj.keyboard.actions?.action?.[b1ActionIndex]?.when) { + for (const when of jsonObj.keyboard.actions.action[b1ActionIndex].when) { + if ((when['state'] === "none") // find "none" + && (when['next'] !== undefined)) { // find "next" // Data of Block Nr 5 ..................................................................................................................................................................... // of this state(none)-next-pair get value of next (next="1") ............................................................................................................................. - /* eg: 1 */ const b5ValueNext: string = jsonObj.keyboard.actions.action[b1ActionIndex].when[l]['next']; + /* eg: 1 */ const b5ValueNext: string = when['next']; // ........................................................................................................................................................................................ @@ -339,7 +340,7 @@ export class KeylayoutToKmnConverter { // with present actionId (a18) find all keycode-behavior-pairs that use this action (a18) => (keymapIndex 0/keycode 24 and keymapIndex 3/keycode 24) .................................... // from these create an array of modifier combinations e.g. [['','caps?'], ['Caps']] ..................................................................................................... /* eg: [['24', 0], ['24', 3]] */ const b4DeadkeyObj: KeylayoutFileData[] = this.getKeyModifierArrayFromActionID(jsonObj, actionId); - /* e.g. [['','caps?'], ['Caps']]*/ const b4DeadkeyModifierObj: string[] = this.getModifierArrayFromKeyModifierArray(dataUkelele.modifiers, b4DeadkeyObj); + /* e.g. [['','caps?'], ['Caps']]*/ const b4DeadkeyModifierObj: string[][] = this.getModifierArrayFromKeyModifierArray(dataUkelele.modifiers, b4DeadkeyObj); // ........................................................................................................................................................................................ @@ -353,14 +354,14 @@ export class KeylayoutToKmnConverter { // create array[Keycode,Keyname,action id,actionIndex,output] and array[Keyname,action id,behavior,modifier,output] ...................................................................... /* eg: ['0','K_A','a9','0','â'] */ const b1KeycodeObj: KeylayoutFileData[] = this.getKeyActionOutputArrayFromActionStateOutputArray(jsonObj, b6ActionIdObj); /* eg: ['K_A','a9','0','NCAPS','â']*/ const b1ModifierKeyObj: KeylayoutFileData[] = this.getKeyBehaviorModOutputArrayFromKeyActionBehaviorOutputArray(jsonObj, b1KeycodeObj, isCapsused); - // ....................................................................................................................................................................................... + // ....................................................................................................................................................................................... - for (let n1 = 0; n1 < b4DeadkeyModifierObj.length; n1++) { - for (let n2 = 0; n2 < b4DeadkeyModifierObj[n1].length; n2++) { - for (let n3 = 0; n3 < b4DeadkeyObj.length; n3++) { - for (let n4 = 0; n4 < b1ModifierKeyObj.length; n4++) { + for (let n1 = 0; n1 < b4DeadkeyModifierObj.length; n1++) { + for (let n2 = 0; n2 < b4DeadkeyModifierObj[n1].length; n2++) { + for (let n3 = 0; n3 < b4DeadkeyObj.length; n3++) { + for (let n4 = 0; n4 < b1ModifierKeyObj.length; n4++) { - ruleObj = new Rule( + ruleObj = new Rule( /* ruleType */ "C2", /* modifierPrevDeadkey*/ "", @@ -376,11 +377,12 @@ export class KeylayoutToKmnConverter { /* modifierKey*/ b1ModifierKeyObj[n4].modifier, /* key */ b1ModifierKeyObj[n4].key, /* output */ new TextEncoder().encode(b1ModifierKeyObj[n4].outchar), - ); - if ((b1ModifierKeyObj[n4].outchar !== undefined) - && (b1ModifierKeyObj[n4].outchar !== "undefined") - && (b1ModifierKeyObj[n4].outchar !== "")) { - rules.push(ruleObj); + ); + if ((b1ModifierKeyObj[n4].outchar !== undefined) + && (b1ModifierKeyObj[n4].outchar !== "undefined") + && (b1ModifierKeyObj[n4].outchar !== "")) { + rules.push(ruleObj); + } } } } @@ -416,7 +418,7 @@ export class KeylayoutToKmnConverter { // with present actionId (a16) find all keycode-behavior-pairs that use this action (a16) => (keymapIndex 3/keycode 32) .................................................................... // from these create an array of modifier combinations e.g. [ [ 'anyOption', 'Caps' ] ] ..................................................................................................... /* e.g. [['32', 3]] */ const b4DeadkeyObj: KeylayoutFileData[] = this.getKeyModifierArrayFromActionID(jsonObj, actionId); - /* e.g. [ [ 'anyOption', 'Caps' ] ]*/ const b4DeadkeyModifierObj: string[] = this.getModifierArrayFromKeyModifierArray(dataUkelele.modifiers, b4DeadkeyObj); + /* e.g. [ [ 'anyOption', 'Caps' ] ]*/ const b4DeadkeyModifierObj: string[][] = this.getModifierArrayFromKeyModifierArray(dataUkelele.modifiers, b4DeadkeyObj); // ........................................................................................................................................................................................... // Data of Block Nr 3 ........................................................................................................................................................................ @@ -428,7 +430,7 @@ export class KeylayoutToKmnConverter { // with present actionId (a17) find all key names and behaviors that use this action (a17) => (keymapIndex 3/keycode 28) .................................................................... // from these create an array of modifier combinations e.g. [ [ 'anyOption', 'Caps' ] ] ..................................................................................................... /* eg: index=3 */ const b2PrevDeadkeyObj: KeylayoutFileData[] = this.getKeyModifierArrayFromActionID(jsonObj, b3ActionId); - /* e.g. [ [ 'anyOption', 'Caps' ] ] */ const b2PrevDeadkeyModifierObj: string[] = this.getModifierArrayFromKeyModifierArray(dataUkelele.modifiers, b2PrevDeadkeyObj); + /* e.g. [ [ 'anyOption', 'Caps' ] ] */ const b2PrevDeadkeyModifierObj: string[][] = this.getModifierArrayFromKeyModifierArray(dataUkelele.modifiers, b2PrevDeadkeyObj); // ........................................................................................................................................................................................... // Data of Block Nr 6 ........................................................................................................................................................................ // create an array[action id,state,output] from all state-output-pairs that use state = b5ValueNext (e.g. use 1 in ) ......................................... @@ -486,7 +488,7 @@ export class KeylayoutToKmnConverter { keymapIndex: jsonObj.keyboard.keyMapSet[0].keyMap[i]['index'], output: jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['output'], key: jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['code'], - KeyName: this.mapUkeleleKeycodeToVK(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['code']) + KeyName: this.mapUkeleleKeycodeToVK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['code'])) })); return null; } @@ -773,7 +775,7 @@ export class KeylayoutToKmnConverter { ]; if (!(pos >= 0 && pos <= 0x31) || (pos === null) || (pos === undefined)) { - return ""; + return "" as string; } else { return vk[pos]; } @@ -781,11 +783,14 @@ export class KeylayoutToKmnConverter { /** * @brief member function to return an index for a given actionID - * @param data :any - an object containing all data read from a .keylayout file + * @param data an object containing all data read from a .keylayout file * @param search :string - value 'id' to be found * @return a number specifying the index of an actionId */ - public getActionIndexFromActionId(data: any, search: string): number { + public getActionIndexFromActionId(data: Keylayout.KeylayoutXMLSourceFile, search: string): number { + if (!data.keyboard?.actions?.action) { + return -1; + } for (let i = 0; i < data.keyboard.actions.action.length; i++) { if (data.keyboard.actions.action[i]['id'] === search) { return i; @@ -796,53 +801,60 @@ export class KeylayoutToKmnConverter { /** * @brief member function to find the actionID of a certain state-next pair - * @param data :any an object containing all data read from a .keylayout file + * @param data an object containing all data read from a .keylayout file * @param search :string value 'next' to be found * @return a string containing the actionId of a certain state(none)-next pair */ - public getActionIdFromActionNext(data: any, search: string): string { - if (search !== "none") { - for (let i = 0; i < data.keyboard.actions.action.length; i++) { - for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { - if (data.keyboard.actions.action[i].when[j]['next'] === search) { - return data.keyboard.actions.action[i]['id']; + public getActionIdFromActionNext(data: Keylayout.KeylayoutXMLSourceFile, search: string): string { + if (search !== "none" && data.keyboard?.actions?.action) { + for (const action of data.keyboard.actions.action) { + if (action.when) { + for (const when of action.when) { + if (when['next'] === search) { + return action['id'] as string; + } } } } } - return ""; + return "" as string; } /** * @brief member function to create an array of (modifier) behaviors for a given keycode in [{keycode,modifier}] - * @param data : any - an object containing all data read from a .keylayout file + * @param data an object containing all data read from a .keylayout file * @param search : KeylayoutFileData[] - an array[{keycode,modifier}] to be found * @return a string[] containing modifiers */ - public getModifierArrayFromKeyModifierArray(data: any, search: KeylayoutFileData[]): string[] { - const returnString1D: string[] = []; + public getModifierArrayFromKeyModifierArray(data: ProcessedData["modifiers"], search: KeylayoutFileData[]): string[][] | [null] { + const returnString1D: string[][] = []; for (let i = 0; i < search.length; i++) { - returnString1D.push(data[search[i].behavior]); + if (search[i].behavior === undefined || search[i].behavior === null) { + return [null]; + } + returnString1D.push(data[Number(search[i].behavior)]); } return returnString1D; } - /** * @brief member function to find the output for a certain actionID for state 'none' - * @param data :any an object containing all data read from a .keylayout file + * @param data an object containing all data read from a .keylayout file * @param search :string an actionId to be found * @return a string containing the output character */ - public getOutputFromActionIdNone(data: any, search: string): string { + public getOutputFromActionIdNone(data: Keylayout.KeylayoutXMLSourceFile, search: string): string { let OutputValue: string = ""; - for (let i = 0; i < data.keyboard.actions.action.length; i++) { - if (data.keyboard.actions.action[i]['id'] === search) { - for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { - if (data.keyboard.actions.action[i].when[j]['state'] === "none") { - if (data.keyboard.actions.action[i].when[j]['output'] !== undefined) { - OutputValue = data.keyboard.actions.action[i].when[j]['output']; - } + + if (!data.keyboard?.actions?.action) { + return OutputValue; + } + + for (const action of data.keyboard.actions.action as Keylayout.KL_Action[]) { + if (action['id'] === search) { + for (const when of action.when as Keylayout.KL_When[]) { + if ((when['state'] === "none") && (when['output'] !== undefined)) { + OutputValue = when['output']; } } } @@ -852,11 +864,11 @@ export class KeylayoutToKmnConverter { /** * @brief member function to return array of [Keycode,Keyname,actionId,actionIDIndex, output] for a given actionID in of [ actionID,state,output] - * @param data :any - an object containing all data read from a .keylayout file + * @param data an object containing all data read from a .keylayout file * @param search :idStateOutputObject[] - array of [{ actionID,state,output }] * @return a KeylayoutFileData[] containing [{Keycode,Keyname,actionId,actionID, output}] */ - public getKeyActionOutputArrayFromActionStateOutputArray(data: any, search: ActionStateOutput[]): KeylayoutFileData[] { + public getKeyActionOutputArrayFromActionStateOutputArray(data: Keylayout.KeylayoutXMLSourceFile, search: ActionStateOutput[]): KeylayoutFileData[] { if ((search === undefined) || (search === null)) return []; @@ -867,7 +879,7 @@ export class KeylayoutToKmnConverter { for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['action'] === search[k].id && - data.keyboard.keyMapSet[0].keyMap[i].key[j]['code'] <= KeylayoutToKmnConverter.MAX_KEY_IDENTIFIER) { + Number(data.keyboard.keyMapSet[0].keyMap[i].key[j]['code']) <= KeylayoutToKmnConverter.MAX_KEY_IDENTIFIER) { const singleDataSet = { keyCode: data.keyboard.keyMapSet[0].keyMap[i].key[j]['code'], key: this.mapUkeleleKeycodeToVK(Number(data.keyboard.keyMapSet[0].keyMap[i].key[j]['code'])), @@ -885,24 +897,26 @@ export class KeylayoutToKmnConverter { /** * @brief member function to get an array of all actionId-output pairs for a certain state - * @param data : any an object containing all data read from a .keylayout file + * @param data an object containing all data read from a .keylayout file * @param search : string a 'state' to be found * @return an array: idStateOutputObject[] containing all [{actionId, state, output}] for a certain state */ - public getActionStateOutputArrayFromActionState(data: any, search: string): ActionStateOutput[] { + public getActionStateOutputArrayFromActionState(data: Keylayout.KeylayoutXMLSourceFile, search: string): ActionStateOutput[] { const actionStateOutput: ActionStateOutput[] = []; - - for (let i = 0; i < data.keyboard.actions.action.length; i++) { - for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { - if (data.keyboard.actions.action[i].when[j]['state'] === search) { - if (data.keyboard.actions.action[i].when[j]['output'] !== undefined) { - const singleDataSet = { - id: data.keyboard.actions.action[i]['id'], - state: data.keyboard.actions.action[i].when[j]['state'], - output: data.keyboard.actions.action[i].when[j]['output'] - }; - actionStateOutput.push(singleDataSet); + if (search !== "none" && data.keyboard?.actions?.action) { + for (const action of data.keyboard.actions.action) { + if (action.when) { + for (const when of action.when) { + if ((when['state'] === search) && (when['output'] !== undefined)) { + const singleDataSet = { + id: action['id'], + state: when['state'], + output: when['output'] + }; + actionStateOutput.push(singleDataSet as ActionStateOutput); + } } + } } } @@ -911,12 +925,12 @@ export class KeylayoutToKmnConverter { /** * @brief member function to create an 2D array of [KeyName,actionId,behavior,modifier,output] - * @param data : any an object containing all data read from a .keylayout file + * @param data an object containing all data read from a .keylayout file * @param search : array of [{keycode,keyname,actionId,behavior,output}] to be found * @param isCAPSused : boolean flag to indicate if CAPS is used in a keylayout file or not * @return an array: KeylayoutFileData[] containing [{KeyName,actionId,behavior,modifier,output}] */ - public getKeyBehaviorModOutputArrayFromKeyActionBehaviorOutputArray(data: any, search: KeylayoutFileData[], isCAPSused: boolean): KeylayoutFileData[] { + public getKeyBehaviorModOutputArrayFromKeyActionBehaviorOutputArray(data: Keylayout.KeylayoutXMLSourceFile, search: KeylayoutFileData[], isCAPSused: boolean): KeylayoutFileData[] { const keyBehaviorModOutput = []; if (!((search === undefined) || (search === null) || (search.length === 0))) { for (let i = 0; i < search.length; i++) { @@ -945,20 +959,20 @@ export class KeylayoutToKmnConverter { unique.push(o); } return unique; - }, []); + }, [] as KeylayoutFileData[]); return uniquekeyBehaviorModOutput; } /** * @brief member function to create an array of [actionID, output, behavior,keyname,modifier] for a given actionId - * @param data : any - an object containing all data read from a .keylayout file - * @param modi : any - an array of modifiers + * @param data an object containing all data read from a .keylayout file + * @param modi an array of modifiers * @param search : string - an actionId to be found * @param outchar : string - the output character * @param isCAPSused : boolean - flag to indicate if CAPS is used in a keylayout file or not * @return an array: KeylayoutFileData[] containing [{actionID,output, behavior,keyname,modifier}] */ - public getActionOutputBehaviorKeyModiFromActionIDStateOutput(data: any, modi: string[][], search: string, outchar: string, isCapsused: boolean): KeylayoutFileData[] { + public getActionOutputBehaviorKeyModiFromActionIDStateOutput(data: Keylayout.KeylayoutXMLSourceFile, modi: string[][], search: string, outchar: string, isCapsused: boolean): KeylayoutFileData[] { const actionOutputBehaviorKeyModi = []; if ((!modi) || (search === "") || (search === undefined)) { return []; @@ -967,8 +981,8 @@ export class KeylayoutToKmnConverter { for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['action'] === search) { - for (let k = 0; k < modi[data.keyboard.keyMapSet[0].keyMap[i]['index']].length; k++) { - const behaviorIdx: number = data.keyboard.keyMapSet[0].keyMap[i]['index']; + for (let k = 0; k < modi[Number(data.keyboard.keyMapSet[0].keyMap[i]['index'])].length; k++) { + const behaviorIdx: number = Number(data.keyboard.keyMapSet[0].keyMap[i]['index']); const singleDataSet = { outchar: outchar, actionId: data.keyboard.keyMapSet[0].keyMap[i].key[j]['action'], @@ -996,18 +1010,18 @@ export class KeylayoutToKmnConverter { unique.push(o); } return unique; - }, []); + }, [] as KeylayoutFileData[]); return uniqueactionOutputBehaviorKey; } /** * @brief member function to create an array of [{keycode,behavior}] for a given actionId - * @param data : any - an object containing all data read from a .keylayout file + * @param data an object containing all data read from a .keylayout file * @param search : string - an actionId to be found * @return an array: KeylayoutFileData[] containing [{keycode,behavior}] */ - public getKeyModifierArrayFromActionID(data: any, search: string): KeylayoutFileData[] { + public getKeyModifierArrayFromActionID(data: Keylayout.KeylayoutXMLSourceFile, search: string): KeylayoutFileData[] { const mapIndexObject1D: KeylayoutFileData[] = []; for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { diff --git a/developer/src/kmc-convert/test/data/keylayout.dtd b/developer/src/kmc-convert/test/data/keylayout.dtd index e60fa8c51c5..9a734b11b86 100644 --- a/developer/src/kmc-convert/test/data/keylayout.dtd +++ b/developer/src/kmc-convert/test/data/keylayout.dtd @@ -4,29 +4,86 @@ * Created by S. Schmitt on 2025-07-14 * * This DTD describes a technical preview of Keylayout Data - --> + * + * Unless otherwise specified we used TN 2056: + * https://developer.apple.com/library/archive/technotes/tn2056/_index.html#//apple_ref/doc/uid/DTS10003085-CH1-SUBSECTION7 + * + * kmc-convert does not need and therefore does not process the following attributes: + * group, id, maxout, + * first, last, mapSet, modifiers, + * defaultIndex, + * baseMapSet, baseIndex, + * through, multiplier + * kmc-convert does not need and therefore does not process the following elements: + * terminators + * kmc-convert does not need and therefore does not process 'anonymous actions' + * --> + + + + + + + + + - - - + + + + - - + + + + + + + - - + + + + - - + + - + + - - + + + - - + + + + - + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index c2f9fa53525..a7010ef1e7d 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -186,24 +186,6 @@ describe('KeylayoutToKmnConverter', function () { assert.isNull(convertedEmpty); }); - it('should return empty on only modifiers as input', async function () { - const convertedMod = sut.convertBound.convert({ - keylayoutFilename: '', - modifiers: [['caps'], ['Shift'], ['command']], - rules: [] - }, ''); - assert.isNull(convertedMod); - }); - - it('should return empty on only rules as input', async function () { - const convertedRule = sut.convertBound.convert({ - keylayoutFilename: '', - modifiers: [], - rules: [['C0', '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_A', 'A']] - }, ''); - assert.isNull(convertedRule); - }); - it('should return empty array of rules on null input', async function () { const convertedRule = sut.convertBound.convert(null, 'ABC.kmn'); assert.isNull(convertedRule); @@ -350,13 +332,14 @@ describe('KeylayoutToKmnConverter', function () { [[{ key: '999', behavior: null }], [null]], [[{ key: '0', behavior: -999 }], [null]], [[{ key: '0', behavior: null }], [null]], + [[{ key: '0', behavior: undefined }], [null]], [[], []], ].forEach(function (values) { it((values[1] !== null) ? ("getModifierArrayFromKeyModifierArray('" + JSON.stringify(values[0]) + "')").padEnd(68, " ") + " should return '" + JSON.stringify(values[1]) + "'" : ("getModifierArrayFromKeyModifierArray('" + JSON.stringify(values[0]) + "')").padEnd(68, " ") + " should return '" + "null" + "'", async function () { - const result = sut.getModifierArrayFromKeyModifierArray(converted.modifiers, values[0] as KeylayoutFileData[]); + const result = sut.getModifierArrayFromKeyModifierArray(converted.modifiers, values[0] as unknown as KeylayoutFileData[]); assert.deepStrictEqual(JSON.stringify(result), JSON.stringify(values[1])); }); }); diff --git a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts index 0eb23c88b46..ede21c9b9a4 100644 --- a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts +++ b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts @@ -74,7 +74,7 @@ describe('KmnFileWriter', function () { ["ሴ", 'ሴ'], ["😎", '😎'], ["", '\u0002'], - ["�",undefined ], + ["�", undefined], ["a", 'a'], ["ሴ", 'ሴ'], ["😆", '😆'], @@ -148,9 +148,9 @@ describe('KmnFileWriter', function () { ['c WARNING: unavailable modifier : here: '], ['c WARNING: unavailable superior rule ( [Y K_Y] > dk(B0) ) : here: ']], - ].forEach(function (values: any, index: number) { - it(('rule " ' + values[0][0].ruleType + ' "') + 'should create "' + values[1] + ' | ' + values[2] + ' | ' + values[3] + '"', async function () { - const result: string[] = sutW.reviewRules(values[0], 0); + ].forEach(function (values: (string[] | Rule[])[], index: number) { + it(('rule " ' + (values[0][0] as Rule).ruleType as string + ' "') + 'should create "' + values[1] + ' | ' + values[2] + ' | ' + values[3] + '"', async function () { + const result: string[] = sutW.reviewRules(values[0] as Rule[], 0); assert.equal(result[0], values[1][0]); assert.equal(result[1], values[2][0]); assert.equal(result[2], values[3][0]); @@ -313,9 +313,9 @@ describe('KmnFileWriter', function () { [''], ["c WARNING: duplicate rule: earlier: [CAPS K_C] > 'X' here: "]], - ].forEach(function (values: any, index: number) { - it('rule ' + values[0][0].ruleType + ' should create " ' + ' "' + values[1] + ' | ' + values[2] + ' | ' + values[3] + '"', async function () { - const result: string[] = sutW.reviewRules(values[0], 1); + ].forEach(function (values: (string[] | Rule[])[], index: number) { + it('rule ' + (values[0][0] as Rule).ruleType as string + ' should create " ' + ' "' + values[1] + ' | ' + values[2] + ' | ' + values[3] + '"', async function () { + const result: string[] = sutW.reviewRules(values[0] as Rule[], 1); assert.equal(result[0], values[1][0]); assert.equal(result[1], values[2][0]); assert.equal(result[2], values[3][0]); @@ -333,9 +333,9 @@ describe('KmnFileWriter', function () { [''], [''], ["c WARNING: ambiguous rule: later: [RALT K_B] > dk(A0) ambiguous rule: earlier: [RALT K_B] > 'X' here: PLEASE CHECK THE FOLLOWING RULE AS IT WILL NOT BE WRITTEN ! "]], - ].forEach(function (values: any, index: number) { - it(('rule ' + values[0][0].ruleType + ' should create " ' + ' "') + values[1] + ' | ' + values[2] + ' | ' + values[3] + '"', async function () { - const result: string[] = sutW.reviewRules(values[0], 2); + ].forEach(function (values: (string[] | Rule[])[], index: number) { + it(('rule ' + (values[0][0]as Rule).ruleType as string + ' should create " ' + ' "') + values[1] + ' | ' + values[2] + ' | ' + values[3] + '"', async function () { + const result: string[] = sutW.reviewRules(values[0]as Rule[], 2); assert.equal(result[0], values[1][0]); assert.equal(result[1], values[2][0]); assert.equal(result[2], values[3][0]); @@ -432,13 +432,13 @@ describe('KmnFileWriter', function () { "dk(B2) + [NCAPS RALT K_A] > 'â'\n\n" ] ], - ].forEach(function (values: any) { + ].forEach(function (values: (string[] | Rule[])[], index: number) { it(('an array of Rules should create a set of kmn rules '), async function () { const data: ProcessedData = { keylayoutFilename: "", kmnFilename: "", modifiers: [[]], - rules: values[0] + rules: values[0] as Rule[] }; const result1 = sutW.writeDataRules(data); assert.isTrue(result1 === values[1][0]); diff --git a/resources/standards-data/keylayout/dtd/keylayout.xsd b/resources/standards-data/keylayout/dtd/keylayout.xsd index 48e84f3f156..554d5bbd273 100644 --- a/resources/standards-data/keylayout/dtd/keylayout.xsd +++ b/resources/standards-data/keylayout/dtd/keylayout.xsd @@ -8,7 +8,10 @@ - + + @@ -63,7 +66,7 @@ - + @@ -83,7 +86,7 @@ - + From 620851ac6f43cd03d5845493c4b411dd393ed07e Mon Sep 17 00:00:00 2001 From: Sabine Date: Tue, 28 Apr 2026 21:58:22 +0200 Subject: [PATCH 236/251] feat(developer): edit comments --- .../src/types/keylayout/keylayout-xml.ts | 76 +++++++++---------- .../keylayout-to-kmn/keylayout-file-reader.ts | 3 +- .../keylayout-to-kmn-converter.ts | 32 ++++---- .../src/keylayout-to-kmn/kmn-file-writer.ts | 6 +- .../src/kmc-convert/test/data/keylayout.dtd | 2 +- 5 files changed, 59 insertions(+), 60 deletions(-) diff --git a/developer/src/common/web/utils/src/types/keylayout/keylayout-xml.ts b/developer/src/common/web/utils/src/types/keylayout/keylayout-xml.ts index 57760aae633..12f64e2a6cc 100644 --- a/developer/src/common/web/utils/src/types/keylayout/keylayout-xml.ts +++ b/developer/src/common/web/utils/src/types/keylayout/keylayout-xml.ts @@ -16,23 +16,30 @@ */ export interface KeylayoutXMLSourceFile { - /** + /* * -- the root element */ keyboard: KL_Keyboard; }; export interface KL_Keyboard { - /** - * attributes of the root element - */ + /* + attributes of the main element + even if they are not optional kmc-convert might not use some attributes(group, id, maxout) + */ group: string; id: string; name: string; maxout?: string; - /** + /* * , , , , * the 5 main elements. + * + * The keyboard element must contain exactly one element, + * one or more elements, + * one or more elements, + * an optional element, + * and an optional element. (Source: TN2056) */ layouts: KL_Layouts[]; modifierMap: KL_ModifierMap[]; @@ -42,20 +49,18 @@ export interface KL_Keyboard { }; export interface KL_Layouts { - /** - * the sub element of , - * containing information about the use of (different) mapSet and modifiers - */ + // the sub element of , contains one or more elements layout: KL_Layout[]; }; export interface KL_Layout { - /** + /* * attributes of the sub element * containing information about the use of mapSet and modifiers for certain keys * e.g. key 4 - key 5 use mapSet 2a4 and modifiers 19c * ( ) * referencing + * even if they are not optional kmc-convert might not use some attributes(first, last, mapSet, modifiers) */ first: string; last: string; @@ -64,98 +69,94 @@ export interface KL_Layout { }; export interface KL_ModifierMap { - /** + /* * attributes of the element + * even if they are not optional kmc-convert might not use some attributes(defaultIndex) */ id: string; defaultIndex: string; - /** + /* * the sub element of + * The element contains one or more elements, each of which correspond to one table */ keyMapSelect: KL_KeyMapSelect[]; }; export interface KL_KeyMapSelect { - /** + /* * attributes of the element * containing a set of modifier combinations for a behavior * referencing */ mapIndex: string; - /** - * the sub element of - */ + // the sub element of modifier: KL_Modifier[]; }; export interface KL_Modifier { - /** + /* * attributes of the element - * containing one combination of modifier keys + * each containing one combination of modifier keys */ keys: string; }; export interface KL_KeyMapSet { - /** + /* * attributes of the element * referencing */ id: string; - /** - * the sub element of + /* the sub element of + * The contains one or more elements, each of which correspond to one table */ keyMap: KL_KeyMap[]; }; export interface KL_KeyMap { - /** + /* * attributes of the element * referencing + * even if they are not optional kmc-convert might not use some attributes(baseMapSet, baseIndex) */ index: string; baseMapSet?: string; baseIndex?: string; - /** - * the sub element of - */ + // the sub element of key: KL_Key[]; }; export interface KL_Key { - /** + /* * attributes of the element * containing a keycode and its output or action */ code: string; - action?: string; //TODO-KMC-CONVERT: Support sub-element 'anonymous actions' + action?: string; //TODO-KMC-CONVERT: Support sub-element 'anonymous actions' in the future output?: string; }; export interface KL_Actions { - /** - * the sub element of - */ + // the sub element of action: KL_Action[]; }; export interface KL_Action { - /** + /* * attributes of the element * defining an action id */ id?: string; - /** - * a sub element of - */ + // a sub element of when?: KL_When[]; }; export interface KL_When { - /** + /* * attributes of the element * contain either a state-output pair or a state-next pair * to define which output or next is followed by a state + * even if they are not optional kmc-convert might not use some attributes(through, multiplier) */ state?: string; through?: string; @@ -163,10 +164,7 @@ export interface KL_When { multiplier?: string; next?: string; }; - export interface KL_Terminators { - /** - * a sub element of - */ + // a sub element of when?: KL_When[]; }; diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts index 26ac23a3a1a..e8d09eb121b 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts @@ -107,9 +107,10 @@ export class KeylayoutFileReader { public boxArray(source: any) { boxXmlArray(source, 'modifierMap'); + boxXmlArray(source, 'keyMapSet'); - if (source.layouts) { + if(source.layouts) { boxXmlArray(source.layouts, 'layout'); } diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 9db2deb84ef..1a02662c4be 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -7,6 +7,7 @@ * */ +// ToDo-kmc-convert all warnings/squiggely lines will be adressed in PR #15860 import { CompilerCallbacks, CompilerOptions, KeymanCompilerResult, Keylayout } from "@keymanapp/developer-utils"; import { KmnFileWriter } from './kmn-file-writer.js'; import { KeylayoutFileReader } from './keylayout-file-reader.js'; @@ -14,7 +15,7 @@ import { ConverterMessages } from '../converter-messages.js'; import { ConverterArtifacts, ConverterToKmnArtifacts } from "../converter-artifacts.js"; export interface ConverterResult extends KeymanCompilerResult { - /** + /* * Internal in-memory build artifacts from a successful compilation. Caller * can write these to disk with {@link Converter.write} */ @@ -22,29 +23,29 @@ export interface ConverterResult extends KeymanCompilerResult { }; export interface ConverterToKmnResult extends ConverterResult { - /** + /* * Internal in-memory build artifacts from a successful compilation. Caller * can write these to disk with {@link Converter.write} */ artifacts: ConverterToKmnArtifacts; }; -export interface ProcessedData { - /** + /** * Interface for all data read from a .keylayout file. Also contains all rules processed from input data. * Data will be used for writing to a .kmn file (e.g. filename, modifier combinations, rules) */ +export interface ProcessedData { + keylayoutFilename: string; kmnFilename: string; modifiers: string[][]; rules: Rule[]; }; - +/** + * Interface for storing data read from a .keylayout file and used for processing rules. + * These are used for obtaining one entity form the other (e.g. from action id to output, from keycode to modifier, etc.) + */ export interface KeylayoutFileData { - /** - * Interface for storing data read from a .keylayout file and used for processing rules. - * These are used for obtaining one entity form the other (e.g. from action id to output, from keycode to modifier, etc.) - */ actionId?: string; keyCode?: string; key?: string; @@ -53,12 +54,12 @@ export interface KeylayoutFileData { outchar?: string; }; +/** + * Interface for storing data read from a .keylayout file and used for processing rules. + * These are used for obtaining the triplet [action id, state, output] + * e.g. ['a9','1','â'] from for action id a9 + */ export interface ActionStateOutput { - /** - * Interface for storing data read from a .keylayout file and used for processing rules. - * These are used for obtaining the triplet [action id, state, output] - * e.g. ['a9','1','â'] from for action id a9 - */ id: string; state: string; output: string; @@ -255,7 +256,6 @@ export class KeylayoutToKmnConverter { rules.push(ruleObj); } } - // } } else if (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['action'] !== undefined) { @@ -441,7 +441,7 @@ export class KeylayoutToKmnConverter { // create array[Keycode,Keyname,action id,actionIndex,output] and array[Keyname,action id,behavior,modifier,output] ......................................................................... /* eg: ['49','K_SPACE','a0','0','Â'] */ const b1KeycodeObj: KeylayoutFileData[] = this.getKeyActionOutputArrayFromActionStateOutputArray(jsonObj, b6ActionIdObj); /* eg: ['K_SPACE','a0','0','NCAPS','Â'] */ const b1ModifierKeyObj: KeylayoutFileData[] = this.getKeyBehaviorModOutputArrayFromKeyActionBehaviorOutputArray(jsonObj, b1KeycodeObj, isCapsused); - // ........................................................................................................................................................................................... + // ........................................................................................................................................................................................... for (let n1 = 0; n1 < b2PrevDeadkeyModifierObj.length; n1++) { for (let n2 = 0; n2 < b2PrevDeadkeyModifierObj[n1].length; n2++) { diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts index b2181eeb1c5..4471b546fbd 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts @@ -145,7 +145,7 @@ export class KmnFileWriter { const warnText = this.reviewRules(uniqueDataRules, k); const outputCharacter = new TextDecoder().decode(uniqueDataRules[k].output); - // TODO-kmc-convert: after merge of PR 14564 use functions from util instead of the ones in this class + // TODO-kmc-convert: after merge of PR 14569 use functions from util instead of the ones in this class // const outputUnicodeCharacter = util.convertToUnicodeCharacter(outputCharacter); // const outputUnicodeCodePoint = util.convertToUnicodeCodePoint(outputCharacter); @@ -198,7 +198,7 @@ export class KmnFileWriter { const warnText = this.reviewRules(uniqueDataRules, k); const outputCharacter = new TextDecoder().decode(uniqueDataRules[k].output); - // TODO-kmc-convert: after merge of PR 14564 use functions from util instead of the ones in this class + // TODO-kmc-convert: after merge of PR 14569 use functions from util instead of the ones in this class // const outputUnicodeCharacter = util.convertToUnicodeCharacter(outputCharacter); // const outputUnicodeCodePoint = util.convertToUnicodeCodePoint(outputCharacter); @@ -274,7 +274,7 @@ export class KmnFileWriter { const warnText = this.reviewRules(uniqueDataRules, k); const outputCharacter = new TextDecoder().decode(uniqueDataRules[k].output); - // TODO-kmc-convert: after merge of PR 14564 use functions from util instead of the ones in this class + // TODO-kmc-convert: after merge of PR 14569 use functions from util instead of the ones in this class if ((outputCharacter !== undefined) || (outputCharacter !== "")) { const characterMessage = this.writeCharacterOrUnicode(outputCharacter, warnText[2]); diff --git a/developer/src/kmc-convert/test/data/keylayout.dtd b/developer/src/kmc-convert/test/data/keylayout.dtd index 9a734b11b86..a5c75267811 100644 --- a/developer/src/kmc-convert/test/data/keylayout.dtd +++ b/developer/src/kmc-convert/test/data/keylayout.dtd @@ -23,7 +23,7 @@ + kmc-convert uses instead: --> From 1c3524ef31a07a1040ef0246af562889aaae1a4a Mon Sep 17 00:00:00 2001 From: Sabine Date: Tue, 28 Apr 2026 22:54:19 +0200 Subject: [PATCH 237/251] feat(developer): typos, tidy up --- developer/src/kmc-convert/src/converter-messages.ts | 12 +++--------- developer/src/kmc-convert/src/converter.ts | 2 +- .../src/keylayout-to-kmn/keylayout-file-reader.ts | 6 +++--- .../keylayout-to-kmn/keylayout-to-kmn-converter.ts | 12 ++++++------ 4 files changed, 13 insertions(+), 19 deletions(-) diff --git a/developer/src/kmc-convert/src/converter-messages.ts b/developer/src/kmc-convert/src/converter-messages.ts index 43ad86eeead..40816d23155 100644 --- a/developer/src/kmc-convert/src/converter-messages.ts +++ b/developer/src/kmc-convert/src/converter-messages.ts @@ -17,15 +17,9 @@ const SevError = CompilerErrorSeverity.Error | Namespace; */ export class ConverterMessages { - static ERROR_OutputFilenameIsRequired = SevError | 0x0001; - static Error_OutputFilenameIsRequired = () => m( - this.ERROR_OutputFilenameIsRequired, - `An output filename is required for keyboard conversion.` - ); - - static ERROR_IntputFilenameIsRequired = SevError | 0x0002; - static Error_IntputFilenameIsRequired = () => m( - this.ERROR_IntputFilenameIsRequired, + static ERROR_InputFilenameIsRequired = SevError | 0x0002; + static Error_InputFilenameIsRequired = () => m( + this.ERROR_InputFilenameIsRequired, `An input filename is required for keyboard conversion.` ); diff --git a/developer/src/kmc-convert/src/converter.ts b/developer/src/kmc-convert/src/converter.ts index 6c32603fac9..63da75dd81e 100644 --- a/developer/src/kmc-convert/src/converter.ts +++ b/developer/src/kmc-convert/src/converter.ts @@ -64,7 +64,7 @@ export class Converter implements KeymanCompiler { }; if (!inputFilename) { - this.callbacks.reportMessage(ConverterMessages.Error_IntputFilenameIsRequired()); + this.callbacks.reportMessage(ConverterMessages.Error_InputFilenameIsRequired()); return null; } diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts index e8d09eb121b..46b4e055b31 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts @@ -11,7 +11,7 @@ import { CompilerCallbacks, DeveloperUtilsMessages, Keylayout, KeymanXMLReader } import { util, SchemaValidators } from '@keymanapp/common-types'; import { ConverterMessages } from '../converter-messages.js'; import boxXmlArray = util.boxXmlArray; -import { KL_KeyMapSelect,KL_KeyMap } from "../../../common/web/utils/src/types/keylayout/keylayout-xml.js"; +import { KL_KeyMapSelect, KL_KeyMap } from "../../../common/web/utils/src/types/keylayout/keylayout-xml.js"; export class KeylayoutFileReader { @@ -94,7 +94,7 @@ export class KeylayoutFileReader { // check if all keyMapSelect elements have a corresponding keyMap element in the .keylayout file if (!this.checkForCorrespondingElements(source)) { this.callbacks.reportMessage(ConverterMessages.Error_InvalidFile({ errorText: inputFilename })); - return null; + return false; } return true; } @@ -110,7 +110,7 @@ export class KeylayoutFileReader { boxXmlArray(source, 'keyMapSet'); - if(source.layouts) { + if (source.layouts) { boxXmlArray(source.layouts, 'layout'); } diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 1a02662c4be..66c6507fb85 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -30,10 +30,10 @@ export interface ConverterToKmnResult extends ConverterResult { artifacts: ConverterToKmnArtifacts; }; - /** - * Interface for all data read from a .keylayout file. Also contains all rules processed from input data. - * Data will be used for writing to a .kmn file (e.g. filename, modifier combinations, rules) - */ +/** + * Interface for all data read from a .keylayout file. Also contains all rules processed from input data. + * Data will be used for writing to a .kmn file (e.g. filename, modifier combinations, rules) + */ export interface ProcessedData { keylayoutFilename: string; @@ -166,7 +166,7 @@ export class KeylayoutToKmnConverter { rules: [] }; - if ((jsonObj === null) || (!jsonObj.hasOwnProperty("keyboard"))) { + if ((jsonObj === null)) { return null; } // create an array of modifier combinations and store in dataObject @@ -441,7 +441,7 @@ export class KeylayoutToKmnConverter { // create array[Keycode,Keyname,action id,actionIndex,output] and array[Keyname,action id,behavior,modifier,output] ......................................................................... /* eg: ['49','K_SPACE','a0','0','Â'] */ const b1KeycodeObj: KeylayoutFileData[] = this.getKeyActionOutputArrayFromActionStateOutputArray(jsonObj, b6ActionIdObj); /* eg: ['K_SPACE','a0','0','NCAPS','Â'] */ const b1ModifierKeyObj: KeylayoutFileData[] = this.getKeyBehaviorModOutputArrayFromKeyActionBehaviorOutputArray(jsonObj, b1KeycodeObj, isCapsused); - // ........................................................................................................................................................................................... + // ........................................................................................................................................................................................... for (let n1 = 0; n1 < b2PrevDeadkeyModifierObj.length; n1++) { for (let n2 = 0; n2 < b2PrevDeadkeyModifierObj[n1].length; n2++) { From 79feb58f6004da314477d8ddf3a99f5d316afb8b Mon Sep 17 00:00:00 2001 From: Sabine Date: Thu, 7 May 2026 08:07:38 +0200 Subject: [PATCH 238/251] feat(developer): add (reader/converter/writer tests for xkb --- .../test/kmnXKB-file-writer.tests.ts | 524 +++++++++++ .../kmc-convert/test/xkb-file-reader.tests.ts | 52 ++ .../test/xkb-to-kmn-converter.tests.ts | 824 ++++++++++++++++++ 3 files changed, 1400 insertions(+) create mode 100644 developer/src/kmc-convert/test/kmnXKB-file-writer.tests.ts create mode 100644 developer/src/kmc-convert/test/xkb-file-reader.tests.ts create mode 100644 developer/src/kmc-convert/test/xkb-to-kmn-converter.tests.ts diff --git a/developer/src/kmc-convert/test/kmnXKB-file-writer.tests.ts b/developer/src/kmc-convert/test/kmnXKB-file-writer.tests.ts new file mode 100644 index 00000000000..8db24fc66e2 --- /dev/null +++ b/developer/src/kmc-convert/test/kmnXKB-file-writer.tests.ts @@ -0,0 +1,524 @@ +/* + * Keyman is copyright (C) SIL Global. MIT License. + * + * Created by S. Schmitt on 2025-05-12 + * + * Tests for XkbToKmnConverter, XkbFileReader, KmnXKBFileWriter + * + */ + +import 'mocha'; +import { assert } from 'chai'; +import KEYMAN_VERSION from "@keymanapp/keyman-version"; +import { compilerTestCallbacks, compilerTestOptions, makePathToFixture } from './helpers/index.js'; +import { XkbToKmnConverter, ProcessedData, Rule } from '../src/xkb-to-kmn/xkb-to-kmn-converter.js'; +import { KmnXKBFileWriter } from '../src/xkb-to-kmn/kmnXKB-file-writer.js'; +import { XkbFileReader } from '../src/xkb-to-kmn/xkb-file-reader.js'; + +describe('KmnXKBFileWriter', function () { + + before(function () { + compilerTestCallbacks.clear(); + }); + + describe("Xkb-kmn: writeDataRules() ", function () { + const inputFilename = makePathToFixture('../data/Test.xkb'); + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sutR = new XkbFileReader(compilerTestCallbacks); + const sutW = new KmnXKBFileWriter(compilerTestCallbacks, compilerTestOptions); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + const converted = sut.convertBound.convert(read, inputFilename.replace(/\.xkb$/, '.kmn')); + + it('writeDataRules() should return true (no error) if written', async function () { + const result = sutW.writeDataRules(converted); + assert.isTrue(result.length > 0); + }); + + }); + + describe("Xkb-kmn: writeKmnFileHeader() ", function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sutR = new XkbFileReader(compilerTestCallbacks); + const sutW = new KmnXKBFileWriter(compilerTestCallbacks, compilerTestOptions); + const inputFilename = makePathToFixture('../data/Test.xkb'); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + const converted = sut.convertBound.convert(read, inputFilename.replace(/\.xkb$/, '.kmn')); + + const outExpectedFirst: string = + "c ..................................................................................................................\n" + + "c ..................................................................................................................\n" + + "c Keyman keyboard generated by kmn-convert version: " + KEYMAN_VERSION.VERSION + "\n" + + "c from Ukelele file: "; + + const outExpectedLast: string = + "\n" + + "c ..................................................................................................................\n" + + "c ..................................................................................................................\n" + + "\n" + + "store(&TARGETS) 'desktop'\n" + + "\n" + + "begin Unicode > use(main)\n\n" + + "group(main) using keys\n\n" + + "\n"; + + it(('writeKmnFileHeader should return store text with filename ').padEnd(62, " ") + 'on correct input', async function () { + const writtenCorrectName = sutW.writeKmnFileHeader(converted); + assert.equal(writtenCorrectName, (outExpectedFirst + converted.keylayoutFilename + outExpectedLast)); + }); + }); + + describe('Xkb-kmn: convertToUnicodeCharacter ', function () { + const sutW = new KmnXKBFileWriter(compilerTestCallbacks, compilerTestOptions); + [ + + ["<", '<'], + ["a", 'a'], + ["ሴ", 'ሴ'], + ["W̊", "W̊"], + ['😎', '😎'], + ["ab", 'ab'], + ["ሴЖ", 'ሴЖ'], + ["ẘẈ", "ẘẈ"], + ["😎😆", '😎😆'], + ["aሴ😆", 'aሴ😆'], + /* + ["U+0061", 'a'], + ["U+1234", 'ሴ'], + ["U+1E9A", "ẚ"], + ["U+1F60A", '😊'], + ["U+0001", '\u0001'], + ["U+1000000;", undefined], + */ + ["a", 'a'], + ["ሴ", 'ሴ'], + ["ẘ", "ẘ"], + ["😏", '😏'], + ["", '\u0002'], + ["�", undefined], + ["a", 'a'], + ["ሴ", 'ሴ'], + ["ẛ", "ẛ"], + ["😆", '😆'], + ["", '\u0003'], + ["󴉀", '󴉀'], + ["@", undefined], + [">", '>'], + ["<", '<'], + [""", '"'], + ["'", "'"], + [">", undefined], + ["␤", '␤'], + ["␕", '␕'], + ["", ''], + ["", ''], + [undefined, undefined], + [null, undefined], + /* + ["U+", undefined], + ['U+', undefined], + ['U+U+', undefined], + ['U+D799', '힙'], + ['U+D800', undefined], + ['U+D83D', undefined], + ['U+DFFF', undefined], + ['U+10FFFF', '􏿿'], + ['U+E000', ''], + ['U+1000000', undefined], + */ + ['&', '&'], + ['&;', '&;'], + ['&&', '&&'], + ['&&;', '&&;'], + ["&#&#", undefined], + ["&#x&#x", undefined], + ["&#", undefined], + ["&#;", undefined], + ["&#x", undefined], + ["&#x;", undefined], + ['&##', undefined], + ['&##;', undefined], + ["􏿿", "􏿿"], + ["􏿿", "􏿿"], + ["�", undefined], + ["�", undefined], + ['Ӓ56', undefined], + +//.................................................................. + + ["a", 'a'], + ["ሴ", 'ሴ'], + ["😎", '😎'], + ["", '\u0002'], + ["�", undefined], + ["a", 'a'], + ["ሴ", 'ሴ'], + ["😆", '😆'], + ["", '\u0003'], + ["󴉀", '󴉀'], + /*["U+0061", 'a'], + ["U+1234", 'ሴ'], + ["U+1F60E", '😎'], + ["U+0001", '\u0001'], + ["U+1000000;", undefined],*/ + ["@", undefined], + ["a", 'a'], + ["ሴ", 'ሴ'], + ['😎', '😎'], + ["W̊", "W̊"], + ["ab", 'ab'], + ["", ''], + ["␤", '␤'], + ["␕", '␕'], + ["", ''], + [undefined, undefined], + [null, undefined] + ].forEach(function (values) { + it(('should convert "' + values[0] + '"').padEnd(25, " ") + 'to "' + values[1] + '"', async function () { + const result = sutW.convertToUnicodeCharacter(values[0] as string); + assert.equal(result, values[1]); + }); + }); + }); + + describe('Xkb-kmn: reviewRules messages', function () { + const sutW = new KmnXKBFileWriter(compilerTestCallbacks, compilerTestOptions); + [ + [[new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'UNAVAILABLE', 'K_A', new TextEncoder().encode('A'))], + [''], + [''], + ['c WARNING: unavailable modifier : here: ']], + + [[new Rule("C1", '', '', 0, 0, 'CAPS', 'K_EQUAL', 0, 0, 'UNAVAILABLE', 'K_B', new TextEncoder().encode('B'))], + [''], + [''], + ['c WARNING: unavailable modifier : here: ']], + + [[new Rule("C2", '', '', 0, 0, 'CAPS', 'K_EQUAL', 0, 0, 'UNAVAILABLE', 'K_C', new TextEncoder().encode('C'),)], + [''], + [''], + ['c WARNING: unavailable modifier : here: ']], + + [[new Rule("C2", '', '', 0, 0, 'UNAVAILABLE_dk', 'K_EQUAL', 0, 0, 'UNAVAILABLE', 'K_C', new TextEncoder().encode('C'),)], + [''], + ['c WARNING: unavailable modifier : here: '], + ['c WARNING: unavailable modifier : here: ']], + + [[new Rule("C3", 'UNAVAILABLE_prev_dk', 'K_D', 0, 0, 'UNAVAILABLE_dk', 'K_EQUAL', 0, 0, 'SHIFT', 'K_C', new TextEncoder().encode('D'),)], + ['c WARNING: unavailable modifier : here: '], + ['c WARNING: unavailable modifier : here: '], + ['c WARNING: unavailable superior rule ( [UNAVAILABLE_dk K_EQUAL] > dk(B0) ) : here: ']], + + [[new Rule("C3", 'UNAVAILABLE_prev_dk', 'K_D', 0, 0, 'UNAVAILABLE_dk', 'K_EQUAL', 0, 0, 'UNAVAIL', 'K_C', new TextEncoder().encode('D'),)], + ['c WARNING: unavailable modifier : here: '], + ['c WARNING: unavailable modifier : here: '], + ['c WARNING: unavailable modifier : here: ']], + + [[new Rule("C3", 'CAPS', 'K_D', 0, 0, 'RALT', 'K_EQUAL', 0, 0, 'SHIFT', 'K_C', new TextEncoder().encode('D'),)], + [''], + [''], + ['']], + + [[new Rule("C3", 'X', 'K_X', 0, 0, 'Y', 'K_Y', 0, 0, 'SHIFT', 'K_Z', new TextEncoder().encode('D'),)], + ['c WARNING: unavailable modifier : here: '], + ['c WARNING: unavailable modifier : here: '], + ['c WARNING: unavailable superior rule ( [Y K_Y] > dk(B0) ) : here: ']], + + ].forEach(function (values: any, index: number) { + it(('rule " ' + values[0][0].ruleType + ' "') + 'should create "' + values[1] + ' | ' + values[2] + ' | ' + values[3] + '"', async function () { + const result: string[] = sutW.reviewRules(values[0], 0); + assert.equal(result[0], values[1][0]); + assert.equal(result[1], values[2][0]); + assert.equal(result[2], values[3][0]); + }); + }); + }); + + describe('Xkb-kmn: reviewRules messages duplicate and ambiguous', function () { + const sutW = new KmnXKBFileWriter(compilerTestCallbacks, compilerTestOptions); + [ + //all + [[ + new Rule("C3", 'LALT', 'K_A', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), + new Rule("C3", 'LALT', 'K_A', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')),], + ['c WARNING: duplicate rule: earlier: [LALT K_A] > dk(C0) here: '], + ["c WARNING: duplicate rule: earlier: dk(B0) + [SHIFT K_B] > dk(B0) here: "], + ["c WARNING: duplicate rule: earlier: dk(B0) + [CAPS K_C] > 'X' here: "]], + + //6-6 dup + [[ + new Rule("C3", 'LALT', 'K_A', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), + new Rule("C3", 'CTRL', 'K_D', 0, 0, 'NCAPS', 'K_E', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')),], + [''], + [""], + ["c WARNING: duplicate rule: earlier: dk(B0) + [CAPS K_C] > 'X' here: "]], + + //6-6 amb + [[ + new Rule("C3", 'LALT', 'K_A', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), + new Rule("C3", 'CTRL', 'K_D', 0, 0, 'NCAPS', 'K_E', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('Y')),], + [''], + [""], + ["c WARNING: ambiguous rule: earlier: dk(B0) + [CAPS K_C] > 'X' here: "]], + + // 5-5 amb + [[ + new Rule("C3", 'LALT', 'K_A', 0, 0, 'NCAPS', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), + new Rule("C3", 'LALT', 'K_A', 0, 0, 'NCAPS', 'K_B', 0, 1, 'RALT', 'K_F', new TextEncoder().encode('X')),], + ['c WARNING: duplicate rule: earlier: [LALT K_A] > dk(C0) here: '], + ["c WARNING: ambiguous rule: earlier: dk(B0) + [NCAPS K_B] > dk(B0) here: "], [''], + ], + + // 5-5 dup + [[ + new Rule("C3", 'LALT', 'K_A', 0, 0, 'NCAPS', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), + new Rule("C3", 'LALT', 'K_A', 0, 0, 'NCAPS', 'K_B', 0, 0, 'RALT', 'K_F', new TextEncoder().encode('X')),], + ['c WARNING: duplicate rule: earlier: [LALT K_A] > dk(C0) here: '], + ["c WARNING: duplicate rule: earlier: dk(B0) + [NCAPS K_B] > dk(B0) here: "], + ['']], + + // 4-2 amb + [[ + new Rule("C3", 'LALT', 'K_A', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), + new Rule("C2", '', '', 0, 0, 'LALT', 'K_A', 0, 0, 'RALT', 'K_F', new TextEncoder().encode('X')),], + ['c WARNING: ambiguous rule: later: [LALT K_A] > dk(C0) here: '], + [''], + ['']], + + // 4-4 amb + [[ + new Rule("C3", 'LALT', 'K_A', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), + new Rule("C3", 'LALT', 'K_A', 1, 1, 'NCAPS', 'K_E', 0, 0, 'RALT', 'K_F', new TextEncoder().encode('Y')),], + ['c WARNING: ambiguous rule: earlier: [LALT K_A] > dk(C0) here: '], + [""], + [''],], + + // 4-4 dup + [[ + new Rule("C3", 'LALT', 'K_A', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), + new Rule("C3", 'LALT', 'K_A', 0, 0, 'NCAPS', 'K_E', 0, 0, 'RALT', 'K_F', new TextEncoder().encode('X')),], + ['c WARNING: duplicate rule: earlier: [LALT K_A] > dk(C0) here: '], + [''], + ['']], + + // 4-2 amb + [[ + new Rule("C3", 'LALT', 'K_A', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), + new Rule("C2", '', '', 0, 0, 'LALT', 'K_A', 0, 0, 'RALT', 'K_F', new TextEncoder().encode('Y')),], + ['c WARNING: ambiguous rule: later: [LALT K_A] > dk(C0) here: '], + [''], + ['']], + + // 6-3 dup + [[ + new Rule("C2", '', '', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), + new Rule("C3", 'CTRL', 'K_D', 0, 0, 'NCAPS', 'K_E', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')),], + [''], + ["c WARNING: duplicate rule: earlier: dk(C0) + [CAPS K_C] > 'X' here: "], + [''],], + + // 6-3 amb + [[ + new Rule("C2", '', '', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), + new Rule("C3", 'CTRL', 'K_D', 0, 0, 'NCAPS', 'K_E', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('Y')),], + [''], + ["c WARNING: ambiguous rule: earlier: dk(C0) + [CAPS K_C] > 'X' here: "], + [''],], + + // 2-4 amb + [[ + new Rule("C2", '', '', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), + new Rule("C3", 'SHIFT', 'K_B', 0, 0, 'NCAPS', 'K_E', 0, 0, 'RALT', 'K_F', new TextEncoder().encode('Y')),], + ['c WARNING: ambiguous rule: earlier: [SHIFT K_B] > dk(A0) here: '], + [''], + ['']], + + //2-2 amb + [[ + new Rule("C2", '', '', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), + new Rule("C2", '', '', 0, 0, 'SHIFT', 'K_B', 1, 1, 'RALT', 'K_F', new TextEncoder().encode('Y')),], + [''], + ['c WARNING: ambiguous rule: earlier: [SHIFT K_B] > dk(C0) here: '], + ['']], + + // 2-2 dup + [[ + new Rule("C2", '', '', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), + new Rule("C2", '', '', 0, 0, 'SHIFT', 'K_B', 0, 0, 'RALT', 'K_F', new TextEncoder().encode('Y')),], + [''], + ['c WARNING: duplicate rule: earlier: [SHIFT K_B] > dk(C0) here: '], + ['']], + + // 3-3 dup + [[ + new Rule("C2", '', '', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), + new Rule("C2", '', '', 0, 0, 'NCAPS', 'K_E', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')),], + [''], + [''], + ["c WARNING: duplicate rule: earlier: dk(A0) + [CAPS K_C] > 'X' here: "]], + + // 3-3 amb + [[ + new Rule("C2", '', '', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), + new Rule("C2", '', '', 0, 0, 'NCAPS', 'K_E', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('Y')),], + [''], + [''], + ["c WARNING: ambiguous rule: earlier: dk(A0) + [CAPS K_C] > 'X' here: "]], + + // 2-1 amb + [[ + new Rule("C2", '', '', 0, 0, 'RALT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), + new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'RALT', 'K_B', new TextEncoder().encode('Y'))], + [''], + [''], + ['c WARNING: ambiguous rule: later: [RALT K_B] > dk(A0) here: ']], + + // 1-1 amb + [[ + new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), + new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('Y'))], + [''], + [''], + ["c WARNING: ambiguous rule: earlier: [CAPS K_C] > 'X' here: "]], + + // 1-1 amb + [[ + new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), + new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X'))], + [''], + [''], + ["c WARNING: duplicate rule: earlier: [CAPS K_C] > 'X' here: "]], + + ].forEach(function (values: any, index: number) { + it('rule ' + values[0][0].ruleType + ' should create " ' + ' "' + values[1] + ' | ' + values[2] + ' | ' + values[3] + '"', async function () { + const result: string[] = sutW.reviewRules(values[0], 1); + assert.equal(result[0], values[1][0]); + assert.equal(result[1], values[2][0]); + assert.equal(result[2], values[3][0]); + }); + }); + }); + + describe('Xkb-kmn: reviewRules messages duplicate and ambiguous with Extra warning', function () { + const sutW = new KmnXKBFileWriter(compilerTestCallbacks, compilerTestOptions); + [[[ + new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'RALT', 'K_B', new TextEncoder().encode('X')), + new Rule("C2", '', '', 0, 0, 'RALT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('Y')), + new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'RALT', 'K_B', new TextEncoder().encode('Z')) + ], + [''], + [''], + ["c WARNING: ambiguous rule: later: [RALT K_B] > dk(A0) ambiguous rule: earlier: [RALT K_B] > 'X' here: PLEASE CHECK THE FOLLOWING RULE AS IT WILL NOT BE WRITTEN ! "]], + ].forEach(function (values: any, index: number) { + it(('rule ' + values[0][0].ruleType + ' should create " ' + ' "') + values[1] + ' | ' + values[2] + ' | ' + values[3] + '"', async function () { + const result: string[] = sutW.reviewRules(values[0], 2); + assert.equal(result[0], values[1][0]); + assert.equal(result[1], values[2][0]); + assert.equal(result[2], values[3][0]); + }); + }); + }); + + describe('Xkb-kmn: write from intermediate data array', function () { + const sutW = new KmnXKBFileWriter(compilerTestCallbacks, compilerTestOptions); + [ + [ + [ /* see ../data/Test_C0.xkb */ + new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_A', new TextEncoder().encode('a')), + new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_A', new TextEncoder().encode('A')), + new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_S', new TextEncoder().encode('s')), + new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_D', new TextEncoder().encode('d')) + ], + ["+ [NCAPS K_A] > 'a'\n" + + "+ [CAPS K_A] > 'A'\n\n" + + "+ [NCAPS K_S] > 's'\n\n" + + "+ [NCAPS K_D] > 'd'\n"] + ], + [ + [ /* see ../data/Test_C1.xkb */ + new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_S', new TextEncoder().encode('s')), + new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_S', new TextEncoder().encode('S')) + ], + ["+ [NCAPS K_S] > 's'\n" + + "+ [CAPS K_S] > 'S'\n"] + ], + [ + [ /* see ../data/Test_C2.xkb */ + new Rule("C2", '', '', 0, 0, 'NCAPS', 'K_U', 1, 1, 'CAPS', 'K_A', new TextEncoder().encode('Â')) + ], + ["+ [NCAPS K_U] > dk(A1)\n" + + "dk(A1) + [CAPS K_A] > 'Â'\n\n"] + ], + [ + [ /* see ../data/Test_C3.xkb */ + new Rule("C3", 'NCAPS SHIFT', 'K_D', 2, 1, 'NCAPS', 'K_U', 1, 2, 'CAPS', 'K_A', new TextEncoder().encode('Â')) + ], + ["+ [NCAPS SHIFT K_D] > dk(A2)\n" + + "dk(A2) + [NCAPS K_U] > dk(B1)\n" + + "dk(B1) + [CAPS K_A] > 'Â'\n\n" + ] + ], + [ + [ /* see ../data/Test_C0_C1_C2_C3.xkb */ + new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_A', new TextEncoder().encode('A')), + new Rule("C2", '', '', 0, 0, 'NCAPS RALT', 'K_EQUAL', 1, 1, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_S', new TextEncoder().encode('S')), + new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'NCAPS RALT', 'K_U', new TextEncoder().encode('S')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 1, 'CAPS', 'K_S', 2, 6, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'CAPS', 'K_U', 3, 3, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'NCAPS RALT', 'K_S', 4, 4, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'NCAPS RALT', 'K_U', 5, 5, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_S', new TextEncoder().encode('S')), + new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'NCAPS RALT', 'K_U', new TextEncoder().encode('S')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'CAPS', 'K_S', 2, 0, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'CAPS', 'K_U', 3, 0, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'NCAPS RALT', 'K_S', 4, 0, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'NCAPS RALT', 'K_U', 5, 0, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_U', new TextEncoder().encode('U')), + ], + ["+ [CAPS K_A] > 'A'\n" + + "+ [CAPS K_S] > 'S'\n\n" + + "+ [NCAPS RALT K_U] > 'S'\n" + + "+ [CAPS K_U] > 'U'\n" + + "+ [NCAPS RALT K_EQUAL] > dk(A1)\n" + + "dk(A1) + [CAPS K_D] > 'Â'\n\n" + + "+ [NCAPS RALT K_8] > dk(A6)\n" + + "dk(A6) + [CAPS K_S] > dk(B2)\n" + + "dk(B2) + [CAPS K_D] > 'Â'\n\n" + + "dk(A6) + [CAPS K_U] > dk(B3)\n" + + "dk(B3) + [CAPS K_D] > 'Â'\n\n" + + "dk(A6) + [NCAPS RALT K_S] > dk(B4)\n" + + "dk(B4) + [CAPS K_D] > 'Â'\n\n" + + "dk(A6) + [NCAPS RALT K_U] > dk(B5)\n" + + "dk(B5) + [CAPS K_D] > 'Â'\n\n"] + ], + [ + [ /* see ../data/Test_C3_several.xkb */ + new Rule("C3", 'NCAPS RALT', 'K_8', 3, 1, 'CAPS', 'K_U', 1, 3, 'NCAPS', 'K_A', new TextEncoder().encode('â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 3, 0, 'CAPS', 'K_U', 1, 0, 'NCAPS RALT', 'K_A', new TextEncoder().encode('â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 3, 0, 'NCAPS RALT', 'K_U', 2, 2, 'NCAPS', 'K_A', new TextEncoder().encode('â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 3, 0, 'NCAPS RALT', 'K_U', 2, 0, 'NCAPS RALT', 'K_A', new TextEncoder().encode('â')) + ], + ["+ [NCAPS RALT K_8] > dk(A3)\n" + + "dk(A3) + [CAPS K_U] > dk(B1)\n" + + "dk(B1) + [NCAPS K_A] > 'â'\n\n" + + "dk(B1) + [NCAPS RALT K_A] > 'â'\n\n" + + "dk(A3) + [NCAPS RALT K_U] > dk(B2)\n" + + "dk(B2) + [NCAPS K_A] > 'â'\n\n" + + "dk(B2) + [NCAPS RALT K_A] > 'â'\n\n" + ] + ], + ].forEach(function (values: any) { + it(('an array of Rules should create a set of kmn rules '), async function () { + const data: ProcessedData = { + keylayoutFilename: "", + kmnFilename: "", + modifiers: [[]], + rules: values[0] + }; + const result1 = sutW.writeDataRules(data); + assert.isTrue(result1 === values[1][0]); + }); + }); + }); + +}); diff --git a/developer/src/kmc-convert/test/xkb-file-reader.tests.ts b/developer/src/kmc-convert/test/xkb-file-reader.tests.ts new file mode 100644 index 00000000000..0df6b4f2273 --- /dev/null +++ b/developer/src/kmc-convert/test/xkb-file-reader.tests.ts @@ -0,0 +1,52 @@ +/* + * Keyman is copyright (C) SIL Global. MIT License. + * + * Created by S. Schmitt on 2025-05-12 + * + * Tests for KeylayoutToKmnConverter, XkbFileReader, KmnFileWriter + * + */ + +import 'mocha'; +import { assert } from 'chai'; +import { compilerTestCallbacks, makePathToFixture } from './helpers/index.js'; +import { XkbFileReader } from '../src/xkb-to-kmn/xkb-file-reader.js'; + +describe('XkbFileReader', function () { + + before(function () { + compilerTestCallbacks.clear(); + }); + + describe("Xkb-kmn:: read() ", function () { + const sutR = new XkbFileReader(compilerTestCallbacks); + + it('read() should return filled array on correct input', async function () { + const inputFilename = makePathToFixture('../data/Test.xkb'); + const result = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + assert.isNotEmpty(result); + }); + + it('read() should return empty array on empty input', async function () { + const result = sutR.read(compilerTestCallbacks.loadFile("")); + assert.isNull(result); + }); + + it('read() should return empty array on space as input', async function () { + const result = sutR.read(compilerTestCallbacks.loadFile(" ")); + assert.isNull(result); + }); + + it('read() should return empty array on unavailable file name', async function () { + const inputFilenameUnavailable = makePathToFixture('../data/X.xkb'); + const result = sutR.read(compilerTestCallbacks.loadFile(inputFilenameUnavailable)); + assert.isNull(result); + }); + + it('read() should return empty array on typo in path', async function () { + const result = sutR.read(compilerTestCallbacks.loadFile(makePathToFixture('../data|Test.xkb'))); + assert.isNull(result); + }); + }); + +}); diff --git a/developer/src/kmc-convert/test/xkb-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/xkb-to-kmn-converter.tests.ts new file mode 100644 index 00000000000..c6c9c522aa1 --- /dev/null +++ b/developer/src/kmc-convert/test/xkb-to-kmn-converter.tests.ts @@ -0,0 +1,824 @@ +/* + * Keyman is copyright (C) SIL Global. MIT License. + * + * Created by S. Schmitt on 2025-05-12 + * + * Tests for XkbToKmnConverter, XkbFileReader, KmnFileWriter + * + */ +import 'mocha'; +import { assert } from 'chai'; +import * as NodeAssert from 'node:assert'; +import { compilerTestCallbacks, compilerTestOptions, makePathToFixture } from './helpers/index.js'; +import { ActionStateOutput, KeylayoutFileData, XkbToKmnConverter, Rule } from '../src/xkb-to-kmn/xkb-to-kmn-converter.js'; +import { XkbFileReader } from '../src/xkb-to-kmn/xkb-file-reader.js'; +import { ConverterMessages } from '../src/converter-messages.js'; + +describe('XkbToKmnConverter', function () { + + before(function () { + compilerTestCallbacks.clear(); + }); + + describe('Xkb-kmn: RunSpecialTestFiles', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + [ + [makePathToFixture('../data/Test_C0.keylayout')], + [makePathToFixture('../data/Test_C1.keylayout')], + [makePathToFixture('../data/Test_C2.keylayout')], + [makePathToFixture('../data/Test_C2_several.keylayout')], + [makePathToFixture('../data/Test_C3.keylayout')], + [makePathToFixture('../data/Test_C3_several.keylayout')], + [makePathToFixture('../data/Test_C0_C1_C2_C3.keylayout')], + [makePathToFixture('../data/Test_maxKeyCode.keylayout')], + [makePathToFixture('../data/Test_messages.keylayout')], + [makePathToFixture('../data/Test_messages_controlCharacter.keylayout')], + [makePathToFixture('../data/Test_messages_superior_C2.keylayout')], + [makePathToFixture('../data/Test_messages_superior_C3.keylayout')], + [makePathToFixture('../data/Test_duplicate_missing_keycode.keylayout')], + [makePathToFixture('../data/Test_modifier.keylayout')], + [makePathToFixture('../data/Test_modifierNoCaps.keylayout')], + [makePathToFixture('../data/Test_differentAmountOfKeysInBehaviours.keylayout')], + [makePathToFixture('../data/Test_duplicate_missing_keys.keylayout')], + [makePathToFixture('../data/Test_duplicate_keys.keylayout')], + [makePathToFixture('../data/Test_ambiguous_keys.keylayout')], + [makePathToFixture('../data/Test_nr_elements.keylayout')], + [makePathToFixture('../data/Test.keylayout')], + [makePathToFixture('../data/Test_differentEncodings.keylayout')], + [makePathToFixture('../data/Test_ExtraWarning.keylayout')], + ].forEach(function (files) { + it(files + " should give no errors ", async function () { + sut.run(files[0]); + assert.isTrue(compilerTestCallbacks.messages.length === 0); + }); + }); + }); + + describe('Xkb-kmn: RunTestFiles resulting in errors ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + [ + [makePathToFixture('../data/Test_DifferentAmountOfMapSelectInKeyMapERROR.keylayout')], + [makePathToFixture('../data/Test_MissingkeyERROR.keylayout')], + [makePathToFixture('../data/Test_MissingkeyMapERROR.keylayout')], + [makePathToFixture('../data/Test_MissingLayoutsERROR.keylayout')], + [makePathToFixture('../data/Test_MissingmodifierMapERROR.keylayout')], + [makePathToFixture('../data/Test_MissingkeyMapSetERROR.keylayout')], + [makePathToFixture('../data/Test_MissingActionsERROR.keylayout')], + [makePathToFixture('../data/Test_MissingTerminatorsERROR.keylayout')], + [makePathToFixture('../data/Test_MissingAllERROR.keylayout')], + ].forEach(function (files) { + it(files + " should give an error ", async function () { + sut.run(files[0]); + assert.isTrue(compilerTestCallbacks.messages.length > 0); + }); + }); + }); + + describe('Xkb-kmn: RunSpecialTestFiles - create Error: unsupported characters', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + [ + [makePathToFixture('../data/Test_characters.keylayout')], + ].forEach(function (files) { + it(files + " should give Error: unsupported characters ", async function () { + sut.run(files[0]); + assert.isTrue(compilerTestCallbacks.messages.length === 1); + }); + }); + }); + + describe('Xkb-kmn: RunSpecialTestFiles - create Error: undefined action', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + [ + [makePathToFixture('../data/Test_undefinedAction.keylayout')], + ].forEach(function (files) { + it(files + " should give Error: undefined action detected", async function () { + sut.run(files[0]); + assert.isTrue(compilerTestCallbacks.messages.length === 1); + assert.equal(compilerTestCallbacks.messages[0].code, 5292040); + }); + }); + }); + + describe('Xkb-kmn: run() ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + + it('run() should throw on null input file name and null output file name', async function () { + // note, could use 'chai as promised' library to make this more fluent: + const result = sut.run(null, null); + assert.isNotNull(result); + assert.equal(compilerTestCallbacks.messages.length, 1); + assert.deepEqual(compilerTestCallbacks.messages[0], ConverterMessages.Error_FileNotFound({ inputFilename: null })); + }); + + it('run() should throw on null input file name and empty output file name', async function () { + const result = sut.run(null, ''); + assert.isNotNull(result); + assert.equal(compilerTestCallbacks.messages.length, 1); + assert.deepEqual(compilerTestCallbacks.messages[0], ConverterMessages.Error_FileNotFound({ inputFilename: null })); + }); + + it('run() should throw on null input file name and unknown output file name', async function () { + const result = sut.run(null, 'X'); + assert.isNotNull(result); + assert.equal(compilerTestCallbacks.messages.length, 1); + assert.deepEqual(compilerTestCallbacks.messages[0], ConverterMessages.Error_FileNotFound({ inputFilename: null })); + }); + + it('run() should throw on unavailable input file name and null output file name', async function () { + const inputFilename = makePathToFixture('../data/Unavailable.keylayout'); + const result = sut.run(inputFilename, null); + assert.isNotNull(result); + assert.equal(compilerTestCallbacks.messages.length, 2); + assert.deepEqual(compilerTestCallbacks.messages[0], ConverterMessages.Error_UnableToRead()); + assert.equal(compilerTestCallbacks.messages[1].code, 5292037); + }); + }); + + describe('Xkb-kmn: Run kmc-convert with or without outputfile name', async function () { + this.timeout(5000); // allow longer time for this test + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const infile = '../data/Test.keylayout'; + [ + [makePathToFixture('../data/Test.kmn')], + [makePathToFixture('')], + [], + [null], + [makePathToFixture('../data/test_OtherOutputName.kmn')], + [makePathToFixture('../data/OutputXName.bb')], + ].forEach(function (files) { + it(infile + " should run ", async function () { + await NodeAssert.doesNotReject(async () => sut.run(makePathToFixture(infile), files[0])); + assert.equal(compilerTestCallbacks.messages.length, 0); + }); + }); + }); + + describe('Xkb-kmn: convert() ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sutR = new XkbFileReader(compilerTestCallbacks); + + // ProcessedData from usable file + const inputFilename = makePathToFixture('../data/Test.keylayout'); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + const converted = sut.convertBound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); + + // ProcessedData from unavailable file + const inputFilenameUnavailable = makePathToFixture('../data/X.keylayout'); + const readUnavailable = sutR.read(compilerTestCallbacks.loadFile(inputFilenameUnavailable)); + const convertedUnavailable = sut.convertBound.convert(readUnavailable, inputFilenameUnavailable.replace(/\.keylayout$/, '.kmn')); + + // ProcessedData from empty file + const inputFilenameEmpty = makePathToFixture(''); + const readEmpty = sutR.read(compilerTestCallbacks.loadFile(inputFilenameEmpty)); + const convertedEmpty = sut.convertBound.convert(readEmpty, inputFilenameEmpty); + + it('should return converted array on correct input', async function () { + assert.isTrue(converted.rules.length !== 0); + }); + + it('should return empty on empty name as input', async function () { + assert.isNull(convertedUnavailable); + }); + + it('should return empty on empty input', async function () { + assert.isNull(convertedEmpty); + }); + + it('should return empty on only modifiers as input', async function () { + const convertedMod = sut.convertBound.convert({ + keylayoutFilename: '', + modifiers: [['caps'], ['Shift'], ['command']], + rules: [] + }, ''); + assert.isNull(convertedMod); + }); + + it('should return empty on only rules as input', async function () { + const convertedRule = sut.convertBound.convert({ + keylayoutFilename: '', + modifiers: [], + rules: [['C0', '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_A', 'A']] + }, ''); + assert.isNull(convertedRule); + }); + + it('should return empty array of rules on null input', async function () { + const convertedRule = sut.convertBound.convert(null, 'ABC.kmn'); + assert.isNull(convertedRule); + }); + }); + + describe('Xkb-kmn: createKmnModifier ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + [ + [' ', true, 'NCAPS'], + [' ', false, ''], + + ['NCAPS', true, 'NCAPS'], + ['NCAPS', false, ''], + ['caps', true, 'CAPS'], + ['CAPS', true, 'CAPS'], + ['CAPS?', true, 'NCAPS'], + ['CAPS', false, 'CAPS'], + ['CAPS?', false, ''], + ['CAPS? NCAPS', true, 'NCAPS'], + ['CAPS NCAPS', true, 'CAPS NCAPS'], + ['caps ncaps', true, 'CAPS NCAPS'], + ['NCAPS shift', true, 'NCAPS SHIFT'], + ['shift', true, 'NCAPS SHIFT'], + ['leftshift', true, 'NCAPS SHIFT'], + ['rightShift', true, 'NCAPS SHIFT'], + ['shift', false, 'SHIFT'], + ['leftshift', false, 'SHIFT'], + ['rightShift', false, 'SHIFT'], + ['shift rightShift?', true, 'NCAPS SHIFT'], + ['rightShift?', true, 'NCAPS'], + ['shift Shift?', true, 'NCAPS SHIFT'], + ['shift rightShift? caps? rightOption? rightControl', true, 'NCAPS SHIFT RCTRL'], + ['leftshift rightShift? caps? rightOption? rightControl', true, 'NCAPS SHIFT RCTRL'], + ['anycontrol', true, 'NCAPS CTRL'], + ['shift?', true, 'NCAPS'], + ['?', true, 'NCAPS'], + ['?', false, ''], + ['', true, 'NCAPS'], + [' ', false, ''], + ['wrongModifierName', false, 'wrongModifierName'], + ['shift', false, 'SHIFT'], + ['shift command', true, 'NCAPS SHIFT command'], + ['rshift', true, 'NCAPS SHIFT'], + ['rshift', false, 'SHIFT'], + ['rightshift', true, 'NCAPS SHIFT'], + ['riGhtsHift', true, 'NCAPS SHIFT'], + ['LEFTCONTROL', true, 'NCAPS LCTRL'], + ['RCONTROL', true, 'NCAPS RCTRL'], + ['leftoption', true, 'NCAPS LALT'], + ['loption', true, 'NCAPS LALT'], + ['rightoption', true, 'NCAPS RALT'], + ['roption', true, 'NCAPS RALT'], + ].forEach(function (values) { + it(('should convert "' + values[0] + '"').padEnd(36, " ") + 'to "' + values[2] + '"', async function () { + const result = sut.createKmnModifier(values[0] as string, values[1] as boolean); + assert.equal(result, values[2]); + }); + }); + }); + + describe('Xkb-kmn: isAcceptableKeymanModifier ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + [ + ['NCAPS', true], + ['NxCAPS', false], + ['SHIFT', true], + ['ALT', true], + ['RALT', true], + ['LALT', true], + ['CTRL', true], + ['LCTRL', true], + ['RCTRL', true], + ['LCTRL CAPS', true], + ['LCTRL X', false], + ['', true], + [null, false], + ].forEach(function (values) { + it(("isAcceptableKeymanModifier(" + values[0] + ")").padEnd(38, " ") + ' should return ' + values[1], async function () { + const result = sut.isAcceptableKeymanModifier(values[0] as string); + assert.equal(result, values[1]); + }); + }); + }); + + describe('Xkb-kmn: mapUkeleleKeycodeToVK ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + [ + [0x00, 'K_A'], + [0x31, 'K_SPACE'], + [0x18, 'K_EQUAL'], + [0x10, 'K_Y'], + [0x18, 'K_EQUAL'], + [0x21, 'K_LBRKT'], + [0x999, ''], + [-1, ''], + [null, ''], + [undefined, ''], + [, ''], + ].forEach(function (values) { + it(("mapUkeleleKeycodeToVK(" + values[0] + ")").padEnd(26, " ") + "should return " + "'" + values[1] + "'", async function () { + const result = sut.mapUkeleleKeycodeToVK(values[0] as number); + assert.equal(result, values[1]); + }); + }); + }); + + describe('Xkb-kmn: checkIfCapsIsUsed ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + [ + [[['caps', 'xxx'], ['yyy']], true], + [[['Caps', 'xxx'], ['yyy']], true], + [[['CaPs', 'xxx'], ['yyy']], true], + [[['Caps?', 'xxx'], ['yyy']], false], + [[['zzz', 'xxx'], ['Caps?']], false], + [[['caps?', 'xxx'], ['yyy']], false], + [[['zzz', 'xxx'], ['yyy']], false], + [[['shift', 'xxx'], ['caps']], true], + [[['shift', 'caps'], ['yyy']], true], + [[['caps', 'xxx'], ['caps']], true], + [[['', 'someWordWithCaps'], ['']], false], + [null, false], + [[], false], + [[['', ''], ['']], false], + [[[' ', ' '], [' ']], false], + ].forEach(function (values) { + it(("checkIfCapsIsUsed(" + values[0] + ")").padEnd(40, " ") + "should return " + "'" + values[1] + "'", async function () { + const result = sut.checkIfCapsIsUsed(values[0] as string[][]); + assert.isTrue(result === values[1]); + }); + }); + }); + + describe('Xkb-kmn: getModifierArrayFromKeyModifierArray ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sutR = new XkbFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/Test.keylayout'); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + const converted = sut.convertBound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); + [ + [[{ key: '0', behavior: 0 }], [['', 'shift? caps? ']]], + [[{ key: '0', behavior: 2 }], [['shift? leftShift caps? ', 'anyShift caps?', 'shift leftShift caps ', 'shift? rightShift caps? ']]], + [[{ key: '0', behavior: 999 }], [null]], + [[{ key: '999', behavior: null }], [null]], + [[{ key: '0', behavior: -999 }], [null]], + [[{ key: '0', behavior: null }], [null]], + [[], []], + + ].forEach(function (values) { + it((values[1] !== null) ? + ("getModifierArrayFromKeyModifierArray('" + JSON.stringify(values[0]) + "')").padEnd(68, " ") + " should return '" + JSON.stringify(values[1]) + "'" : + ("getModifierArrayFromKeyModifierArray('" + JSON.stringify(values[0]) + "')").padEnd(68, " ") + " should return '" + "null" + "'", async function () { + const result = sut.getModifierArrayFromKeyModifierArray(converted.modifiers, values[0] as KeylayoutFileData[]); + assert.deepStrictEqual(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); + }); + + describe('Xkb-kmn: getKeyModifierArrayFromActionID ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sutR = new XkbFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/Test.keylayout'); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + [ + ['A_16', [{ "key": "32", "behavior": "5" }]], + ['A_19', [{ "key": "45", "behavior": "5" }]], + ['A_18', [{ "key": "24", "behavior": "0" }, { "key": "24", "behavior": "5" }]], + ['unknown', []], + [undefined, []], + [null, []], + [' ', []], + ['', []], + ].forEach(function (values) { + let outstring = '[ '; + for (let i = 0; i < values[1].length; i++) { + outstring = outstring + "[ " + JSON.stringify(values[1][i]) + "], "; + } + it(("getKeyModifierArrayFromActionID('" + values[0] + "')").padEnd(57, " ") + ' should return ' + outstring.substring(0, outstring.lastIndexOf(']') + 2) + " ]", async function () { + const result = sut.getKeyModifierArrayFromActionID(read, String(values[0])); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); + }); + + describe('Xkb-kmn: getActionIdFromActionNext ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sutR = new XkbFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/Test.keylayout'); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + [ + ['none', ''], + ['0', ''], + ['A_18', ''], + ['1', 'A_16'], + ['2', 'A_8'], + ['3', 'A_17'], + ['', ''], + [' ', ''], + ['99', ''], + [null, ''], + [undefined, ''], + ['unknown', ''], + ].forEach(function (values) { + it(("getActionIdFromActionNext('" + values[0] + "')").padEnd(49, " ") + ' should return ' + "'" + values[1] + "'", async function () { + const result = sut.getActionIdFromActionNext(read, String(values[0])); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); + }); + + describe('Xkb-kmn: getActionIndexFromActionId ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sutR = new XkbFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/Test.keylayout'); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + [ + ['none', -1], + ['A_16', 8], + ['A_18', 10], + ['A_19', 11], + ['0', -1], + ['', -1], + [' ', -1], + [null, -1], + [undefined, -1], + ['unknown', -1], + ].forEach(function (values) { + it(("getActionIndexFromActionId('" + values[0] + "')").padEnd(50, " ") + ' should return ' + values[1], async function () { + const result = sut.getActionIndexFromActionId(read, String(values[0])); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); + }); + + describe('Xkb-kmn: getOutputFromActionIdNone ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sutR = new XkbFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/Test.keylayout'); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + [ + ['A_14', 'u'], + ['', ''], + [' ', ''], + ['A_18', ''], + ['unknown', ''], + ].forEach(function (values) { + it( + ("getOutputFromActionIdNone('" + values[0] + "')").padEnd(56, " ") + ' should return ' + "'" + values[1] + "'", async function () { + const result = sut.getOutputFromActionIdNone(read, String(values[0])); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); + + [[null, ''], + [undefined, ''], + [99, ''], + ].forEach(function (values) { + it(("getOutputFromActionIdNone('" + values[0] + "')").padEnd(56, " ") + ' should return ' + values[1], async function () { + const result = sut.getOutputFromActionIdNone(read, String(values[0])); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); + }); + + describe('Xkb-kmn: getKeybehaviorModOutputArrayFromKeyActionbehaviorOutputArray ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sutR = new XkbFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/Test.keylayout'); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + + const b1KeycodeArr: KeylayoutFileData[] = [ + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '0', outchar: 'ˆ' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '1', outchar: 'ˆ' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '2', outchar: 'ˆ' }, + { keyCode: '6', key: 'K_Z', actionId: 'A_0', behavior: '4', outchar: 'ˆ' }, + { keyCode: '25', key: 'K_9', actionId: 'A_0', behavior: '4', outchar: 'ˆ' }, + { keyCode: '43', key: 'K_COMMA', actionId: 'A_0', behavior: '4', outchar: 'ˆ' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '3', outchar: 'ˆ' }, + { keyCode: '0', key: 'K_A', actionId: 'A_1', behavior: '2', outchar: 'Â' }, + { keyCode: '0', key: 'K_A', actionId: 'A_1', behavior: '1', outchar: 'Â' }, + { keyCode: '14', key: 'K_E', actionId: 'A_10', behavior: '0', outchar: 'ê' }, + { keyCode: '34', key: 'K_I', actionId: 'A_11', behavior: '0', outchar: 'î' }, + { keyCode: '31', key: 'K_O', actionId: 'A_13', behavior: '0', outchar: 'ô' }, + { keyCode: '32', key: 'K_U', actionId: 'A_14', behavior: '0', outchar: 'û' }, + { keyCode: '14', key: 'K_E', actionId: 'A_2', behavior: '2', outchar: 'Ê' }, + { keyCode: '14', key: 'K_E', actionId: 'A_2', behavior: '1', outchar: 'Ê' }, + { keyCode: '34', key: 'K_I', actionId: 'A_3', behavior: '2', outchar: 'Î' }, + { keyCode: '34', key: 'K_I', actionId: 'A_3', behavior: '1', outchar: 'Î' }, + { keyCode: '31', key: 'K_O', actionId: 'A_5', behavior: '2', outchar: 'Ô' }, + { keyCode: '31', key: 'K_O', actionId: 'A_5', behavior: '1', outchar: 'Ô' }, + { keyCode: '32', key: 'K_U', actionId: 'A_6', behavior: '2', outchar: 'Û' }, + { keyCode: '32', key: 'K_U', actionId: 'A_6', behavior: '1', outchar: 'Û' }, + { keyCode: '0', key: 'K_A', actionId: 'A_9', behavior: '0', outchar: 'â' } + + ]; + const b1ModifierKeyArr: KeylayoutFileData[] = [ + { actionId: 'A_0', key: 'K_SPACE', behavior: '0', modifier: 'NCAPS', outchar: 'ˆ' }, + { actionId: 'A_0', key: 'K_SPACE', behavior: '1', modifier: 'CAPS', outchar: 'ˆ' }, + { actionId: 'A_0', key: 'K_SPACE', behavior: '2', modifier: 'NCAPS SHIFT', outchar: 'ˆ' }, + { actionId: 'A_0', key: 'K_SPACE', behavior: '2', modifier: 'SHIFT CAPS', outchar: 'ˆ' }, + { actionId: 'A_0', key: 'K_Z', behavior: '4', modifier: 'NCAPS SHIFT RALT', outchar: 'ˆ' }, + { actionId: 'A_0', key: 'K_9', behavior: '4', modifier: 'NCAPS SHIFT RALT', outchar: 'ˆ' }, + { actionId: 'A_0', key: 'K_COMMA', behavior: '4', modifier: 'NCAPS SHIFT RALT', outchar: 'ˆ' }, + { actionId: 'A_0', key: 'K_SPACE', behavior: '3', modifier: 'NCAPS RALT CTRL', outchar: 'ˆ' }, + { actionId: 'A_0', key: 'K_SPACE', behavior: '3', modifier: 'NCAPS CTRL', outchar: 'ˆ' }, + { actionId: 'A_1', key: 'K_A', behavior: '2', modifier: 'NCAPS SHIFT', outchar: 'Â' }, + { actionId: 'A_1', key: 'K_A', behavior: '2', modifier: 'SHIFT CAPS', outchar: 'Â' }, + { actionId: 'A_1', key: 'K_A', behavior: '1', modifier: 'CAPS', outchar: 'Â' }, + { actionId: 'A_10', key: 'K_E', behavior: '0', modifier: 'NCAPS', outchar: 'ê' }, + { actionId: 'A_11', key: 'K_I', behavior: '0', modifier: 'NCAPS', outchar: 'î' }, + { actionId: 'A_13', key: 'K_O', behavior: '0', modifier: 'NCAPS', outchar: 'ô' }, + { actionId: 'A_14', key: 'K_U', behavior: '0', modifier: 'NCAPS', outchar: 'û' }, + { actionId: 'A_2', key: 'K_E', behavior: '2', modifier: 'NCAPS SHIFT', outchar: 'Ê' }, + { actionId: 'A_2', key: 'K_E', behavior: '2', modifier: 'SHIFT CAPS', outchar: 'Ê' }, + { actionId: 'A_2', key: 'K_E', behavior: '1', modifier: 'CAPS', outchar: 'Ê' }, + { actionId: 'A_3', key: 'K_I', behavior: '2', modifier: 'NCAPS SHIFT', outchar: 'Î' }, + { actionId: 'A_3', key: 'K_I', behavior: '2', modifier: 'SHIFT CAPS', outchar: 'Î' }, + { actionId: 'A_3', key: 'K_I', behavior: '1', modifier: 'CAPS', outchar: 'Î' }, + { actionId: 'A_5', key: 'K_O', behavior: '2', modifier: 'NCAPS SHIFT', outchar: 'Ô' }, + { actionId: 'A_5', key: 'K_O', behavior: '2', modifier: 'SHIFT CAPS', outchar: 'Ô' }, + { actionId: 'A_5', key: 'K_O', behavior: '1', modifier: 'CAPS', outchar: 'Ô' }, + { actionId: 'A_6', key: 'K_U', behavior: '2', modifier: 'NCAPS SHIFT', outchar: 'Û' }, + { actionId: 'A_6', key: 'K_U', behavior: '2', modifier: 'SHIFT CAPS', outchar: 'Û' }, + { actionId: 'A_6', key: 'K_U', behavior: '1', modifier: 'CAPS', outchar: 'Û' }, + { actionId: 'A_9', key: 'K_A', behavior: '0', modifier: 'NCAPS', outchar: 'â' } + ]; + + [[b1KeycodeArr, b1ModifierKeyArr], + [[{ keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '0', modifier: '0', outchar: 'ˆ' }], [{ actionId: 'A_0', key: 'K_SPACE', behavior: '0', modifier: 'NCAPS', outchar: 'ˆ' }]], + [[{ keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '0', modifier: '', outchar: 'ˆ' }], [{ actionId: 'A_0', key: 'K_SPACE', behavior: '0', modifier: 'NCAPS', outchar: 'ˆ' }]], + [[{ keyCode: '49', key: 'K_SPACE', actionId: '', behavior: '0', modifier: '0', outchar: 'ˆ' }], [{ actionId: '', key: 'K_SPACE', behavior: '0', modifier: 'NCAPS', outchar: 'ˆ' }]], + [[{ keyCode: '49', key: '', actionId: 'A_0', behavior: '0', modifier: '0', outchar: 'ˆ' }], [{ actionId: 'A_0', key: '', behavior: '0', modifier: 'NCAPS', outchar: 'ˆ' }]], + [[{ keyCode: '', key: 'K_SPACE', actionId: 'A_0', behavior: '0', modifier: '0', outchar: 'ˆ' }], [{ actionId: 'A_0', key: 'K_SPACE', behavior: '0', modifier: 'NCAPS', outchar: 'ˆ' }]], + [[{ keyCode: '', key: '', actionId: '', behavior: '0', modifier: '', outchar: '' }], [{ actionId: '', key: '', behavior: '0', modifier: 'NCAPS', outchar: '' }]], + ].forEach(function (values) { + const isCapsUsed = true; + const stringIn = "getKeybehaviorModOutputArrayFromKeyActionbehaviorOutputArray(['" + "', '" + "', '" + values[0][0].keyCode + "', '" + values[0][0].key + "', '" + values[0][0].actionId + "', '" + values[0][0].modifier + "', '" + values[0][0].outchar + "'])"; + const stringOut = "['" + "', '" + "', '" + values[1][0].key + "', '" + values[1][0].actionId + "', '" + "', '" + values[1][0].modifier + "', '" + values[1][0].outchar + "']"; + + it((JSON.stringify(values[1]).length > 60) ? 'an array of objects should return an array of objects' : + stringIn.padEnd(74, " ") + ' should return ' + stringOut, async function () { + const result = sut.getKeyBehaviorModOutputArrayFromKeyActionBehaviorOutputArray(read, values[0], isCapsUsed); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); + + [[{ keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '0', modifier: '0', outchar: 'ˆ' }, { actionId: 'A_0', key: 'K_SPACE', behavior: '0', modifier: '', outchar: 'ˆ' }], + [{ keyCode: '', key: 'K_SPACE', actionId: 'A_0', behavior: '0', modifier: '0', outchar: 'ˆ' }, { actionId: 'A_0', key: 'K_SPACE', behavior: '0', modifier: '', outchar: 'ˆ' }], + [{ keyCode: '', key: '', actionId: '', behavior: '0', modifier: '', outchar: '' }, { actionId: '', key: '', behavior: '0', modifier: '', outchar: '' }], + ].forEach(function (values) { + const isCapsUsed = false; + const stringIn = "getKeybehaviorModOutputArrayFromKeyActionbehaviorOutputArray([ '" + values[0].keyCode + "', '" + values[0].key + "', '" + values[0].actionId + "', '" + values[0].modifier + "', '" + values[0].outchar + "'])"; + const stringOut = "['" + values[1].actionId + "', '" + "', '" + values[1].modifier + "', '" + values[1].key + "', '" + values[1].outchar + "']"; + + it(stringIn.padEnd(74, " ") + ' should return ' + stringOut, async function () { + const result = sut.getKeyBehaviorModOutputArrayFromKeyActionBehaviorOutputArray(read, [values[0]], isCapsUsed); + assert.equal(JSON.stringify(result), JSON.stringify([values[1]])); + }); + }); + + [[[], []], + [undefined, []], + [null, []], + ].forEach(function (values) { + const isCaps = true; + it(("getKeybehaviorModOutputArrayFromKeyActionbehaviorOutputArray([" + values[0] + "])").padEnd(74, " ") + ' should return ' + "[" + values[1] + "]", async function () { + const result = sut.getKeyBehaviorModOutputArrayFromKeyActionBehaviorOutputArray(read, values[0], isCaps); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); + }); + + describe('Xkb-kmn: getActionStateOutputArrayFromActionState ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sutR = new XkbFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/Test.keylayout'); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + [['1', [ + { "id": "A_0", "state": "1", "output": "ˆ" }, + { "id": "A_1", "state": "1", "output": "Â" }, + { "id": "A_10", "state": "1", "output": "ê" }, + { "id": "A_11", "state": "1", "output": "î" }, + { "id": "A_13", "state": "1", "output": "ô" }, + { "id": "A_14", "state": "1", "output": "û" }, + { "id": "A_2", "state": "1", "output": "Ê" }, + { "id": "A_3", "state": "1", "output": "Î" }, + { "id": "A_5", "state": "1", "output": "Ô" }, + { "id": "A_6", "state": "1", "output": "Û" }, + { "id": "A_9", "state": "1", "output": "â" } + ],], + ['2', [ + { "id": "A_0", "state": "2", "output": "`" }, + { "id": "A_1", "state": "2", "output": "À" }, + { "id": "A_10", "state": "2", "output": "è" }, + { "id": "A_11", "state": "2", "output": "ì" }, + { "id": "A_13", "state": "2", "output": "ò" }, + { "id": "A_14", "state": "2", "output": "ù" }, + { "id": "A_2", "state": "2", "output": "È" }, + { "id": "A_3", "state": "2", "output": "Ì" }, + { "id": "A_5", "state": "2", "output": "Ò" }, + { "id": "A_6", "state": "2", "output": "Ù" }, + { "id": "A_9", "state": "2", "output": "à" } + ],], + ['789', [],], + ['', [],], + [' ', [],], + [123, [],], + [null, [],], + [undefined, [],], + ].forEach(function (values) { + it((JSON.stringify(values[1]).length > 30) ? + ("getActionStateOutputArrayFromActionState('" + values[0] + "')").padEnd(60, " ") + ' should return an array of objects' : + ("getActionStateOutputArrayFromActionState('" + values[0] + "')").padEnd(60, " ") + ' should return ' + "'" + JSON.stringify(values[1]) + "'", async function () { + const result = sut.getActionStateOutputArrayFromActionState(read, String(values[0])); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); + }); + + describe('Xkb-kmn: getActionOutputbehaviorKeyModiFromActionIDStateOutput ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sutR = new XkbFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/Test.keylayout'); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + const converted = sut.convertBound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); + [ + ['A_1', 'A', true, + [{ "outchar": "A", "actionId": "A_1", "behavior": "1", "key": "K_A", "modifier": "CAPS" }, + { "outchar": "A", "actionId": "A_1", "behavior": "2", "key": "K_A", "modifier": "NCAPS SHIFT" }, + { "outchar": "A", "actionId": "A_1", "behavior": "2", "key": "K_A", "modifier": "SHIFT CAPS" }] + ], + ['A_1', 'A', false, + [{ "outchar": "A", "actionId": "A_1", "behavior": "1", "key": "K_A", "modifier": "CAPS" }, + { "outchar": "A", "actionId": "A_1", "behavior": "2", "key": "K_A", "modifier": "SHIFT" }, + { "outchar": "A", "actionId": "A_1", "behavior": "2", "key": "K_A", "modifier": "SHIFT CAPS" }] + ], + ['A_9', 'a', true, [{ "outchar": "a", "actionId": "A_9", "behavior": "0", "key": "K_A", "modifier": "NCAPS" }]], + ['A_9', 'a', false, [{ "outchar": "a", "actionId": "A_9", "behavior": "0", "key": "K_A", "modifier": "" }]], + ['A_9', 'a', , [{ "outchar": "a", "actionId": "A_9", "behavior": "0", "key": "K_A", "modifier": "" }]], + ['A_9', '', true, [{ "outchar": "", "actionId": "A_9", "behavior": "0", "key": "K_A", "modifier": "NCAPS" }]], + ['A_9', '', false, [{ "outchar": "", "actionId": "A_9", "behavior": "0", "key": "K_A", "modifier": "" }]], + ['', 'a', true, []], + ['', 'a', false, []], + ['', '', , []], + ].forEach(function (values) { + it((JSON.stringify(values[3]).length > 35) ? + ("getActionOutputbehaviorKeyModiFromActionIDStateOutput('" + values[0] + "', '" + values[1] + "', " + values[2] + ")").padEnd(67, " ") + ' should return an array of objects' : + ("getActionOutputbehaviorKeyModiFromActionIDStateOutput('" + values[0] + "', '" + values[1] + "', " + values[2] + ")").padEnd(67, " ") + ' should return ' + "'" + JSON.stringify(values[3]) + "'", async function () { + const result = sut.getActionOutputBehaviorKeyModiFromActionIDStateOutput(read, converted.modifiers, String(values[0]), String(values[1]), Boolean(values[2])); + assert.equal(JSON.stringify(result), JSON.stringify(values[3])); + }); + }); + }); + + describe('Xkb-kmn: getKeyActionOutputArrayFromActionStateOutputArray ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sutR = new XkbFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/Test.keylayout'); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + + const b6ActionIdArr: ActionStateOutput[] = [ + { "id": "A_0", "state": "1", "output": "ˆ" }, + { "id": "A_1", "state": "1", "output": "Â" }, + { "id": "A_10", "state": "1", "output": "ê" }, + { "id": "A_11", "state": "1", "output": "î" }, + { "id": "A_13", "state": "1", "output": "ô" }, + { "id": "A_14", "state": "1", "output": "û" }, + { "id": "A_2", "state": "1", "output": "Ê" }, + { "id": "A_3", "state": "1", "output": "Î" }, + { "id": "A_5", "state": "1", "output": "Ô" }, + { "id": "A_6", "state": "1", "output": "Û" }, + { "id": "A_9", "state": "1", "output": "â" } + ]; + + const b1KeycodeArr: KeylayoutFileData[] = [ + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '0', outchar: 'ˆ' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '1', outchar: 'ˆ' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '2', outchar: 'ˆ' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '3', outchar: 'ˆ' }, + { keyCode: '6', key: 'K_Z', actionId: 'A_0', behavior: '4', outchar: 'ˆ' }, + { keyCode: '25', key: 'K_9', actionId: 'A_0', behavior: '4', outchar: 'ˆ' }, + { keyCode: '43', key: 'K_COMMA', actionId: 'A_0', behavior: '4', outchar: 'ˆ' }, + { keyCode: '0', key: 'K_A', actionId: 'A_1', behavior: '1', outchar: 'Â' }, + { keyCode: '0', key: 'K_A', actionId: 'A_1', behavior: '2', outchar: 'Â' }, + { keyCode: '14', key: 'K_E', actionId: 'A_10', behavior: '0', outchar: 'ê' }, + { keyCode: '34', key: 'K_I', actionId: 'A_11', behavior: '0', outchar: 'î' }, + { keyCode: '31', key: 'K_O', actionId: 'A_13', behavior: '0', outchar: 'ô' }, + { keyCode: '32', key: 'K_U', actionId: 'A_14', behavior: '0', outchar: 'û' }, + { keyCode: '14', key: 'K_E', actionId: 'A_2', behavior: '1', outchar: 'Ê' }, + { keyCode: '14', key: 'K_E', actionId: 'A_2', behavior: '2', outchar: 'Ê' }, + { keyCode: '34', key: 'K_I', actionId: 'A_3', behavior: '1', outchar: 'Î' }, + { keyCode: '34', key: 'K_I', actionId: 'A_3', behavior: '2', outchar: 'Î' }, + { keyCode: '31', key: 'K_O', actionId: 'A_5', behavior: '1', outchar: 'Ô' }, + { keyCode: '31', key: 'K_O', actionId: 'A_5', behavior: '2', outchar: 'Ô' }, + { keyCode: '32', key: 'K_U', actionId: 'A_6', behavior: '1', outchar: 'Û' }, + { keyCode: '32', key: 'K_U', actionId: 'A_6', behavior: '2', outchar: 'Û' }, + { keyCode: '0', key: 'K_A', actionId: 'A_9', behavior: '0', outchar: 'â' } + ]; + + [[b6ActionIdArr, b1KeycodeArr], + ].forEach(function (values) { + it(("getKeyActionOutputArrayFromActionStateOutputArray([['" + JSON.stringify(values[0]) + "'],..])").padEnd(73, " ") + '1 should return an array of objects', async function () { + const result = sut.getKeyActionOutputArrayFromActionStateOutputArray(read, values[0] as ActionStateOutput[]); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); + + const oneEntryResult = [ + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '0', outchar: 'ˆ' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '1', outchar: 'ˆ' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '2', outchar: 'ˆ' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '3', outchar: 'ˆ' }, + { keyCode: '6', key: 'K_Z', actionId: 'A_0', behavior: '4', outchar: 'ˆ' }, + { keyCode: '25', key: 'K_9', actionId: 'A_0', behavior: '4', outchar: 'ˆ' }, + { keyCode: '43', key: 'K_COMMA', actionId: 'A_0', behavior: '4', outchar: 'ˆ' } + ]; + + const oneEntryResultNoOutput = [ + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '0', outchar: '' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '1', outchar: '' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '2', outchar: '' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '3', outchar: '' }, + { keyCode: '6', key: 'K_Z', actionId: 'A_0', behavior: '4', outchar: '' }, + { keyCode: '25', key: 'K_9', actionId: 'A_0', behavior: '4', outchar: '' }, + { keyCode: '43', key: 'K_COMMA', actionId: 'A_0', behavior: '4', outchar: '' }, + ]; + + [[[{ "id": "A_0", "state": "1", "output": "ˆ" }], oneEntryResult], + [[{ "id": "A_0", "state": "1", "output": "" }], oneEntryResultNoOutput], + [[{ "id": "A_0", "state": "", "output": "ˆ" }], oneEntryResult], + ].forEach(function (values) { + it(("getKeyActionOutputArrayFromActionStateOutputArray(['" + JSON.stringify(values[0]) + "'])").padEnd(73, " ") + ' should return an array of objects', async function () { + const result = sut.getKeyActionOutputArrayFromActionStateOutputArray(read, values[0] as ActionStateOutput[]); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); + + [[[{ "id": "", "state": "1", "output": "ˆ" }], []], + [[{ "id": "", "state": "", "output": "" }], []], + [[{ "id": " ", "state": " ", "output": "" }], []], + + ].forEach(function (values) { + it(("getKeyActionOutputArrayFromActionStateOutputArray(" + JSON.stringify(values[0]) + ")").padEnd(73, " ") + ' should return ' + "'[" + JSON.stringify(values[1]) + "]'", async function () { + const result = sut.getKeyActionOutputArrayFromActionStateOutputArray(read, values[0] as ActionStateOutput[]); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); + + [[, []], + [undefined, []], + [null, []], + ].forEach(function (values) { + it(("getKeyActionOutputArrayFromActionStateOutputArray(" + JSON.stringify(values[0]) + ")").padEnd(73, " ") + ' should return ' + "'[" + JSON.stringify(values[1]) + "]'", async function () { + const result = sut.getKeyActionOutputArrayFromActionStateOutputArray(read, values[0] as ActionStateOutput[]); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); + }); + + describe('Xkb-kmn: createRuleData ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sutR = new XkbFileReader(compilerTestCallbacks); + [ + [ + ['../data/Test_C0.keylayout'], + [new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_A', new TextEncoder().encode('a')), + new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_A', new TextEncoder().encode('A')), + new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_S', new TextEncoder().encode('s')), + new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_D', new TextEncoder().encode('d'))] + ], + [ + ['../data/Test_C1.keylayout'], + [new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_S', new TextEncoder().encode('s')), + new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_S', new TextEncoder().encode('S'))] + ], + [ + ['../data/Test_C2.keylayout'], + [new Rule("C2", '', '', 0, 0, 'NCAPS', 'K_U', 1, 1, 'CAPS', 'K_A', new TextEncoder().encode('Â'))], + ], + [ + ['../data/Test_C3.keylayout'], + [new Rule("C3", 'NCAPS SHIFT', 'K_D', 2, 1, 'NCAPS', 'K_U', 1, 2, 'CAPS', 'K_A', new TextEncoder().encode('Â'))] + ], + + [ + ['../data/Test_C3_several.keylayout'], + [new Rule("C3", 'NCAPS RALT', 'K_8', 3, 1, 'CAPS', 'K_U', 1, 3, 'NCAPS', 'K_A', new TextEncoder().encode('â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 3, 0, 'CAPS', 'K_U', 1, 0, 'NCAPS RALT', 'K_A', new TextEncoder().encode('â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 3, 0, 'NCAPS RALT', 'K_U', 2, 2, 'NCAPS', 'K_A', new TextEncoder().encode('â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 3, 0, 'NCAPS RALT', 'K_U', 2, 0, 'NCAPS RALT', 'K_A', new TextEncoder().encode('â'))] + ], + [ + ['../data/Test_C0_C1_C2_C3.keylayout'], + [new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_A', new TextEncoder().encode('A')), + new Rule("C2", '', '', 0, 0, 'NCAPS RALT', 'K_EQUAL', 1, 1, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_S', new TextEncoder().encode('S')), + new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'NCAPS RALT', 'K_U', new TextEncoder().encode('S')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 1, 'CAPS', 'K_S', 2, 6, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'CAPS', 'K_U', 3, 3, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'NCAPS RALT', 'K_S', 4, 4, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'NCAPS RALT', 'K_U', 5, 5, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_S', new TextEncoder().encode('S')), + new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'NCAPS RALT', 'K_U', new TextEncoder().encode('S')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'CAPS', 'K_S', 2, 0, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'CAPS', 'K_U', 3, 0, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'NCAPS RALT', 'K_S', 4, 0, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'NCAPS RALT', 'K_U', 5, 0, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_U', new TextEncoder().encode('U')),] + ], + ].forEach(function (values: any) { + it('data of \'' + values[0] + "' passed into createRuleData() " + 'should create an array of rules', async function () { + const inputFilename = makePathToFixture(values[0][0]); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + const processedData = sut.convertBound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); + assert.deepEqual(processedData.rules[0], values[1][0]); + }); + }); + }); + +}); From a1ceb539c2dff74d98c1c9cb460008290fd0f351 Mon Sep 17 00:00:00 2001 From: Sabine Date: Thu, 7 May 2026 08:43:43 +0200 Subject: [PATCH 239/251] feat(developer): add changes from merge into xkb-kmn modules --- .../keylayout-to-kmn-converter.ts | 4 +- .../src/xkb-to-kmn/kmnXKB-file-writer.ts | 8 +- .../src/xkb-to-kmn/xkb-file-reader.ts | 111 ++++++++-- .../src/xkb-to-kmn/xkb-to-kmn-converter.ts | 191 +++++++++--------- .../test/xkb-to-kmn-converter.tests.ts | 20 +- 5 files changed, 200 insertions(+), 134 deletions(-) diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 1760859aa8c..fec3a1f19d5 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -110,8 +110,6 @@ export class KeylayoutToKmnConverter { */ async run(inputFilename: string, outputFilename?: string): Promise { - console.log("°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°\n running KeylayoutToKmnConverter with input file " - + inputFilename + " and output file " + outputFilename); if (!inputFilename) { this.callbacks.reportMessage(ConverterMessages.Error_FileNotFound({ inputFilename })); @@ -169,7 +167,7 @@ export class KeylayoutToKmnConverter { rules: [] }; - if ((jsonObj === null)) { + if (jsonObj === null) { return null; } // create an array of modifier combinations and store in dataObject diff --git a/developer/src/kmc-convert/src/xkb-to-kmn/kmnXKB-file-writer.ts b/developer/src/kmc-convert/src/xkb-to-kmn/kmnXKB-file-writer.ts index d4c9a97a0ba..a35202b7de1 100644 --- a/developer/src/kmc-convert/src/xkb-to-kmn/kmnXKB-file-writer.ts +++ b/developer/src/kmc-convert/src/xkb-to-kmn/kmnXKB-file-writer.ts @@ -152,7 +152,7 @@ export class KmnXKBFileWriter { if ((outputCharacter !== undefined) || (outputCharacter !== "")) { const characterMessage = this.writeCharacterOrUnicode(outputCharacter, warnText[2]); versionOutputCharacter = characterMessage.character; - warnText[2] = characterMessage.message; + warnText[2] = characterMessage.message; } // add a warning in front of rules in case unavailable modifiers or ambiguous rules are used @@ -205,7 +205,7 @@ export class KmnXKBFileWriter { if ((outputCharacter !== undefined) || (outputCharacter !== "")) { const characterMessage = this.writeCharacterOrUnicode(outputCharacter, warnText[2]); versionOutputCharacter = characterMessage.character; - warnText[2] = characterMessage.message; + warnText[2] = characterMessage.message; } // add a warning in front of rules in case unavailable modifiers or ambiguous rules are used @@ -279,7 +279,7 @@ export class KmnXKBFileWriter { if ((outputCharacter !== undefined) || (outputCharacter !== "")) { const characterMessage = this.writeCharacterOrUnicode(outputCharacter, warnText[2]); versionOutputCharacter = characterMessage.character; - warnText[2] = characterMessage.message; + warnText[2] = characterMessage.message; } // add a warning in front of rules in case unavailable modifiers or ambiguous rules are used @@ -1030,7 +1030,7 @@ export class KmnXKBFileWriter { const m_chr_inv = /^((&;?)+|(&#;?)+|(&#x;?)+;?)$|^$/i.exec(inputString); // valid '&#x...' - if (m_hex) { + if (m_hex) { const codePoint_h = parseInt(m_hex[1], 16); // Reject surrogates and invalid codepoints if ((codePoint_h >= 0xD800 && codePoint_h <= 0xDFFF) || codePoint_h > 0x10FFFF) { diff --git a/developer/src/kmc-convert/src/xkb-to-kmn/xkb-file-reader.ts b/developer/src/kmc-convert/src/xkb-to-kmn/xkb-file-reader.ts index f737a56780d..cc55e9d6ca9 100644 --- a/developer/src/kmc-convert/src/xkb-to-kmn/xkb-file-reader.ts +++ b/developer/src/kmc-convert/src/xkb-to-kmn/xkb-file-reader.ts @@ -11,15 +11,78 @@ import { CompilerCallbacks, DeveloperUtilsMessages, Keylayout, KeymanXMLReader } import { util, SchemaValidators } from '@keymanapp/common-types'; import { ConverterMessages } from '../converter-messages.js'; import boxXmlArray = util.boxXmlArray; +import { KL_KeyMapSelect, KL_KeyMap } from "../../../common/web/utils/src/types/keylayout/keylayout-xml.js"; + export class XkbFileReader { constructor(private callbacks: CompilerCallbacks /*,private options: CompilerOptions*/) { }; + + /** + * @brief helper function to find a specific keyMap index in a keyMapSet + * @param jsonObj the read keylayout data to be checked + * @param keyMapSelect the keyMapSelect element to find in keyMapSet + * @return true if the keyMapSet element is found, false if not + */ + public findMapIndexinKeymap(jsonObj: Keylayout.KeylayoutXMLSourceFile, keyMapSelect: KL_KeyMapSelect): boolean { + for (const keyMapSet of jsonObj.keyboard.keyMapSet) { + for (const keyMap of keyMapSet.keyMap) { + if (keyMap['index'] === keyMapSelect.mapIndex) { + return true; + } + } + } + return false; + } + + /** + * @brief helper function to find a specific keyMapSelect index in a modifierMap + * @param jsonObj the read keylayout data to be checked + * @param keyMap the keyMap element to find in modifierMap + * @return true if the keyMap element is found, false if not + */ + public findIndexinKeymapSelect(jsonObj: Keylayout.KeylayoutXMLSourceFile, keyMap: KL_KeyMap): boolean { + for (const modifierMap of jsonObj.keyboard.modifierMap) { + for (const keyMapSelect of modifierMap.keyMapSelect) { + if (keyMapSelect['mapIndex'] === keyMap.index) { + return true; + } + } + } + return false; + } + + /** + * @brief member function checking if all keyMapSelect elements have a corresponding keyMap + * element in the .keylayout file (if not, the .keylayout file is invalid and will not be converted) + * see TN2056 (https://developer.apple.com/library/archive/technotes/tn2056/_index.html#//apple_ref/doc/uid/DTS10003085-CH1-SUBSECTION7) + * @param jsonObj the read keylayout data to be checked + * @return true if all keyMapSelect elements have a corresponding keyMap element, false if not + */ + public checkForCorrespondingElements(jsonObj: Keylayout.KeylayoutXMLSourceFile): boolean { + let available = true; + + // check if all keyMapSelect elements have a corresponding keyMap element in the .keylayout file + for (const modifierMap of jsonObj.keyboard.modifierMap) { + for (const keyMapSelect of modifierMap.keyMapSelect) { + available = available && this.findMapIndexinKeymap(jsonObj, keyMapSelect); + } + } + // check if all keyMap elements have a corresponding keyMapSelect element in the .keylayout file + for (const keyMapSet of jsonObj.keyboard.keyMapSet) { + for (const keyMap of keyMapSet.keyMap) { + available = available && this.findIndexinKeymapSelect(jsonObj, keyMap); + } + } + return available; + } + + /** * @returns true if valid, false if invalid */ - public validate(source: Keylayout.KeylayoutXMLSourceFile): boolean { + public validate(source: Keylayout.KeylayoutXMLSourceFile, inputFilename: string): boolean { if (!SchemaValidators.default.keylayout(source)) { for (const err of (SchemaValidators.default.keylayout).errors) { this.callbacks.reportMessage(DeveloperUtilsMessages.Error_InvalidXml({ @@ -28,6 +91,12 @@ export class XkbFileReader { } return false; } + + // check if all keyMapSelect elements have a corresponding keyMap element in the .keylayout file + if (!this.checkForCorrespondingElements(source)) { + this.callbacks.reportMessage(ConverterMessages.Error_InvalidFile({ errorText: inputFilename })); + return false; + } return true; } @@ -38,33 +107,40 @@ export class XkbFileReader { */ public boxArray(source: any) { + boxXmlArray(source, 'modifierMap'); + boxXmlArray(source, 'keyMapSet'); - boxXmlArray(source.layouts, 'layout'); - boxXmlArray(source?.modifierMap, 'keyMapSelect'); + if (source.layouts) { + boxXmlArray(source.layouts, 'layout'); + } - for (const keyMapSelect of source?.modifierMap?.keyMapSelect) { - boxXmlArray(keyMapSelect, 'modifier'); + if (source.modifierMap) { + for (const modifierMap of source.modifierMap) { + boxXmlArray(modifierMap, 'keyMapSelect'); + if (modifierMap.keyMapSelect) { + for (const keyMapSelect of modifierMap.keyMapSelect) { + boxXmlArray(keyMapSelect, 'modifier'); + } + } + } } - for (const keyMapSet of source?.keyMapSet) { + for (const keyMapSet of source.keyMapSet) { boxXmlArray(keyMapSet, 'keyMap'); for (const keyMap of keyMapSet.keyMap) { boxXmlArray(keyMap, 'key'); } } - boxXmlArray(source?.actions, 'action'); - for (const action of source?.actions?.action) { - boxXmlArray(action, 'when'); - } - - boxXmlArray(source.terminators, 'when'); - for (const action of source?.actions?.action) { - boxXmlArray(action, 'when'); + if (source.actions) { + boxXmlArray(source.actions, 'action'); + for (const action of source.actions.action) { + boxXmlArray(action, 'when'); + } } - return source; + boxXmlArray(source?.terminators, 'when'); } /** @@ -78,6 +154,11 @@ export class XkbFileReader { try { const data = new TextDecoder().decode(source); const jsonObj = new KeymanXMLReader('keylayout').parse(data) as Keylayout.KeylayoutXMLSourceFile; + + if (!jsonObj?.keyboard) { + this.callbacks.reportMessage(ConverterMessages.Error_UnableToParse()); + return null; + } this.boxArray(jsonObj.keyboard); // jsonObj now contains arrays; no single fields return jsonObj; } diff --git a/developer/src/kmc-convert/src/xkb-to-kmn/xkb-to-kmn-converter.ts b/developer/src/kmc-convert/src/xkb-to-kmn/xkb-to-kmn-converter.ts index 0722b5cf1d6..416bb884a92 100644 --- a/developer/src/kmc-convert/src/xkb-to-kmn/xkb-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/xkb-to-kmn/xkb-to-kmn-converter.ts @@ -48,7 +48,7 @@ export interface KeylayoutFileData { actionId?: string; keyCode?: string; key?: string; - behavior?: string; + behavior: string; modifier?: string; outchar?: string; }; @@ -108,8 +108,7 @@ export class XkbToKmnConverter { * @return null on success */ async run(inputFilename: string, outputFilename?: string): Promise { - console.log("##############################################################\n running XkbToKmnConverter with input file " - + inputFilename + " and output file " + outputFilename); + if (!inputFilename) { this.callbacks.reportMessage(ConverterMessages.Error_FileNotFound({ inputFilename })); @@ -126,7 +125,7 @@ export class XkbToKmnConverter { return null; } try { - if (!KeylayoutReader.validate(jsonO)) { + if (!KeylayoutReader.validate(jsonO, inputFilename)) { return null; } } catch (e) { @@ -152,7 +151,7 @@ export class XkbToKmnConverter { * @param jsonObj containing filename, behaviorand rules of a json object * @return an ProcessedData containing all data ready to print out */ - private convert(jsonObj: any, inputfilename: string, outputFilename?: string): ProcessedData { + private convert(jsonObj: Keylayout.KeylayoutXMLSourceFile, inputfilename: string, outputFilename?: string): ProcessedData { // modifiers for each behavior const modifierBehavior: string[][] = []; @@ -167,14 +166,14 @@ export class XkbToKmnConverter { rules: [] }; - if ((jsonObj === null) || (!jsonObj.hasOwnProperty("keyboard"))) { + if (jsonObj === null) { return null; } // create an array of modifier combinations and store in dataObject - for (let j = 0; j < jsonObj.keyboard.modifierMap.keyMapSelect.length; j++) { + for (let j = 0; j < jsonObj.keyboard.modifierMap[0].keyMapSelect.length; j++) { const singleModifierSet: string[] = []; - for (let k = 0; k < jsonObj.keyboard.modifierMap.keyMapSelect[j].modifier.length; k++) { - singleModifierSet.push(jsonObj.keyboard.modifierMap.keyMapSelect[j].modifier[k]['keys']); + for (let k = 0; k < jsonObj.keyboard.modifierMap[0].keyMapSelect[j].modifier.length; k++) { + singleModifierSet.push(jsonObj.keyboard.modifierMap[0].keyMapSelect[j].modifier[k]['keys']); } modifierBehavior.push(singleModifierSet); } @@ -198,7 +197,7 @@ export class XkbToKmnConverter { * @param jsonObj: json Object containing all data read from a keylayout file * @return an object containing the name of the input file, an array of behaviors and a populated array of Rules[] */ - public createRuleData(dataUkelele: ProcessedData, jsonObj: any): ProcessedData { + public createRuleData(dataUkelele: ProcessedData, jsonObj: Keylayout.KeylayoutXMLSourceFile): ProcessedData { const rules: Rule[] = []; let dkCounterC3: number = 0; @@ -208,13 +207,6 @@ export class XkbToKmnConverter { // check if we use CAPS in a modifier throughout the .keylayout file. In this case we need to add NCAPS const isCapsused = (this.checkIfCapsIsUsed(dataUkelele.modifiers)); - // if there are different amounts of keyMapSelect vs keyMap - if (jsonObj.keyboard.modifierMap?.keyMapSelect.length !== jsonObj.keyboard.keyMapSet[0].keyMap.length) { - const errorText = dataUkelele.keylayoutFilename; - this.callbacks.reportMessage(ConverterMessages.Error_InvalidFile({ errorText })); - return null; - } - for (let j = 0; j <= XkbToKmnConverter.MAX_KEY_IDENTIFIER; j++) { // loop behaviors (in ukelele it is possible to define multiple modifier combinations that behave in the same way) @@ -264,12 +256,11 @@ export class XkbToKmnConverter { rules.push(ruleObj); } } - // } } else if (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['action'] !== undefined) { - actionId = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['action']; + actionId = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['action'] ?? ""; // ............................................................................................................................... // case C1: action + state none + output ......................................................................................... // C1 see: https://docs.google.com/document/d/12J3NGO6RxIthCpZDTR8FYSRjiMgXJDLwPY2z9xqKzJ0/edit?tab=t.0#heading=h.g7jwx3lx0ydd ... @@ -326,7 +317,7 @@ export class XkbToKmnConverter { this.callbacks.reportMessage(ConverterMessages.Error_UndefinedActionDetected({ inputFilename: jsonObj.keyboard['name'] + ".keylayout", action: actionId, - KeyName: this.mapUkeleleKeycodeToVK(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['code']), + KeyName: this.mapUkeleleKeycodeToVK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['code'])), keymapIndex: jsonObj.keyboard.keyMapSet[0].keyMap[i]['index'] })); return null; @@ -334,13 +325,14 @@ export class XkbToKmnConverter { // with actionId from above loop all 'action' and search for a state(none)-next-pair ............................................................................................................ // e.g. in Block 5: find for action id a18 ...................................................................................................................... - for (let l = 0; l < jsonObj.keyboard.actions.action[b1ActionIndex].when.length; l++) { - if ((jsonObj.keyboard.actions.action[b1ActionIndex].when[l]['state'] === "none") // find "none" - && (jsonObj.keyboard.actions.action[b1ActionIndex].when[l]['next'] !== undefined)) { // find "next" + if (jsonObj.keyboard.actions?.action?.[b1ActionIndex]?.when) { + for (const when of jsonObj.keyboard.actions.action[b1ActionIndex].when) { + if ((when['state'] === "none") // find "none" + && (when['next'] !== undefined)) { // find "next" // Data of Block Nr 5 ..................................................................................................................................................................... // of this state(none)-next-pair get value of next (next="1") ............................................................................................................................. - /* eg: 1 */ const b5ValueNext: string = jsonObj.keyboard.actions.action[b1ActionIndex].when[l]['next']; + /* eg: 1 */ const b5ValueNext: string = when['next']; // ........................................................................................................................................................................................ @@ -348,7 +340,7 @@ export class XkbToKmnConverter { // with present actionId (a18) find all keycode-behavior-pairs that use this action (a18) => (keymapIndex 0/keycode 24 and keymapIndex 3/keycode 24) .................................... // from these create an array of modifier combinations e.g. [['','caps?'], ['Caps']] ..................................................................................................... /* eg: [['24', 0], ['24', 3]] */ const b4DeadkeyObj: KeylayoutFileData[] = this.getKeyModifierArrayFromActionID(jsonObj, actionId); - /* e.g. [['','caps?'], ['Caps']]*/ const b4DeadkeyModifierObj: string[] = this.getModifierArrayFromKeyModifierArray(dataUkelele.modifiers, b4DeadkeyObj); + /* e.g. [['','caps?'], ['Caps']]*/ const b4DeadkeyModifierObj: string[][] = this.getModifierArrayFromKeyModifierArray(dataUkelele.modifiers, b4DeadkeyObj); // ........................................................................................................................................................................................ @@ -362,14 +354,14 @@ export class XkbToKmnConverter { // create array[Keycode,Keyname,action id,actionIndex,output] and array[Keyname,action id,behavior,modifier,output] ...................................................................... /* eg: ['0','K_A','a9','0','â'] */ const b1KeycodeObj: KeylayoutFileData[] = this.getKeyActionOutputArrayFromActionStateOutputArray(jsonObj, b6ActionIdObj); /* eg: ['K_A','a9','0','NCAPS','â']*/ const b1ModifierKeyObj: KeylayoutFileData[] = this.getKeyBehaviorModOutputArrayFromKeyActionBehaviorOutputArray(jsonObj, b1KeycodeObj, isCapsused); - // ....................................................................................................................................................................................... + // ....................................................................................................................................................................................... - for (let n1 = 0; n1 < b4DeadkeyModifierObj.length; n1++) { - for (let n2 = 0; n2 < b4DeadkeyModifierObj[n1].length; n2++) { - for (let n3 = 0; n3 < b4DeadkeyObj.length; n3++) { - for (let n4 = 0; n4 < b1ModifierKeyObj.length; n4++) { + for (let n1 = 0; n1 < b4DeadkeyModifierObj.length; n1++) { + for (let n2 = 0; n2 < b4DeadkeyModifierObj[n1].length; n2++) { + for (let n3 = 0; n3 < b4DeadkeyObj.length; n3++) { + for (let n4 = 0; n4 < b1ModifierKeyObj.length; n4++) { - ruleObj = new Rule( + ruleObj = new Rule( /* ruleType */ "C2", /* modifierPrevDeadkey*/ "", @@ -385,11 +377,12 @@ export class XkbToKmnConverter { /* modifierKey*/ b1ModifierKeyObj[n4].modifier, /* key */ b1ModifierKeyObj[n4].key, /* output */ new TextEncoder().encode(b1ModifierKeyObj[n4].outchar), - ); - if ((b1ModifierKeyObj[n4].outchar !== undefined) - && (b1ModifierKeyObj[n4].outchar !== "undefined") - && (b1ModifierKeyObj[n4].outchar !== "")) { - rules.push(ruleObj); + ); + if ((b1ModifierKeyObj[n4].outchar !== undefined) + && (b1ModifierKeyObj[n4].outchar !== "undefined") + && (b1ModifierKeyObj[n4].outchar !== "")) { + rules.push(ruleObj); + } } } } @@ -425,7 +418,7 @@ export class XkbToKmnConverter { // with present actionId (a16) find all keycode-behavior-pairs that use this action (a16) => (keymapIndex 3/keycode 32) .................................................................... // from these create an array of modifier combinations e.g. [ [ 'anyOption', 'Caps' ] ] ..................................................................................................... /* e.g. [['32', 3]] */ const b4DeadkeyObj: KeylayoutFileData[] = this.getKeyModifierArrayFromActionID(jsonObj, actionId); - /* e.g. [ [ 'anyOption', 'Caps' ] ]*/ const b4DeadkeyModifierObj: string[] = this.getModifierArrayFromKeyModifierArray(dataUkelele.modifiers, b4DeadkeyObj); + /* e.g. [ [ 'anyOption', 'Caps' ] ]*/ const b4DeadkeyModifierObj: string[][] = this.getModifierArrayFromKeyModifierArray(dataUkelele.modifiers, b4DeadkeyObj); // ........................................................................................................................................................................................... // Data of Block Nr 3 ........................................................................................................................................................................ @@ -437,7 +430,7 @@ export class XkbToKmnConverter { // with present actionId (a17) find all key names and behaviors that use this action (a17) => (keymapIndex 3/keycode 28) .................................................................... // from these create an array of modifier combinations e.g. [ [ 'anyOption', 'Caps' ] ] ..................................................................................................... /* eg: index=3 */ const b2PrevDeadkeyObj: KeylayoutFileData[] = this.getKeyModifierArrayFromActionID(jsonObj, b3ActionId); - /* e.g. [ [ 'anyOption', 'Caps' ] ] */ const b2PrevDeadkeyModifierObj: string[] = this.getModifierArrayFromKeyModifierArray(dataUkelele.modifiers, b2PrevDeadkeyObj); + /* e.g. [ [ 'anyOption', 'Caps' ] ] */ const b2PrevDeadkeyModifierObj: string[][] = this.getModifierArrayFromKeyModifierArray(dataUkelele.modifiers, b2PrevDeadkeyObj); // ........................................................................................................................................................................................... // Data of Block Nr 6 ........................................................................................................................................................................ // create an array[action id,state,output] from all state-output-pairs that use state = b5ValueNext (e.g. use 1 in ) ......................................... @@ -495,7 +488,7 @@ export class XkbToKmnConverter { keymapIndex: jsonObj.keyboard.keyMapSet[0].keyMap[i]['index'], output: jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['output'], key: jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['code'], - KeyName: this.mapUkeleleKeycodeToVK(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['code']) + KeyName: this.mapUkeleleKeycodeToVK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['code'])) })); return null; } @@ -782,7 +775,7 @@ export class XkbToKmnConverter { ]; if (!(pos >= 0 && pos <= 0x31) || (pos === null) || (pos === undefined)) { - return ""; + return "" as string; } else { return vk[pos]; } @@ -790,11 +783,14 @@ export class XkbToKmnConverter { /** * @brief member function to return an index for a given actionID - * @param data :any - an object containing all data read from a .keylayout file + * @param data an object containing all data read from a .keylayout file * @param search :string - value 'id' to be found * @return a number specifying the index of an actionId */ - public getActionIndexFromActionId(data: any, search: string): number { + public getActionIndexFromActionId(data: Keylayout.KeylayoutXMLSourceFile, search: string): number { + if (!data.keyboard?.actions?.action) { + return -1; + } for (let i = 0; i < data.keyboard.actions.action.length; i++) { if (data.keyboard.actions.action[i]['id'] === search) { return i; @@ -805,53 +801,60 @@ export class XkbToKmnConverter { /** * @brief member function to find the actionID of a certain state-next pair - * @param data :any an object containing all data read from a .keylayout file + * @param data an object containing all data read from a .keylayout file * @param search :string value 'next' to be found * @return a string containing the actionId of a certain state(none)-next pair */ - public getActionIdFromActionNext(data: any, search: string): string { - if (search !== "none") { - for (let i = 0; i < data.keyboard.actions.action.length; i++) { - for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { - if (data.keyboard.actions.action[i].when[j]['next'] === search) { - return data.keyboard.actions.action[i]['id']; + public getActionIdFromActionNext(data: Keylayout.KeylayoutXMLSourceFile, search: string): string { + if (search !== "none" && data.keyboard?.actions?.action) { + for (const action of data.keyboard.actions.action) { + if (action.when) { + for (const when of action.when) { + if (when['next'] === search) { + return action['id'] as string; + } } } } } - return ""; + return "" as string; } /** * @brief member function to create an array of (modifier) behaviors for a given keycode in [{keycode,modifier}] - * @param data : any - an object containing all data read from a .keylayout file + * @param data an object containing all data read from a .keylayout file * @param search : KeylayoutFileData[] - an array[{keycode,modifier}] to be found * @return a string[] containing modifiers */ - public getModifierArrayFromKeyModifierArray(data: any, search: KeylayoutFileData[]): string[] { - const returnString1D: string[] = []; + public getModifierArrayFromKeyModifierArray(data: ProcessedData["modifiers"], search: KeylayoutFileData[]): string[][] | [null] { + const returnString1D: string[][] = []; for (let i = 0; i < search.length; i++) { - returnString1D.push(data[search[i].behavior]); + if (search[i].behavior === undefined || search[i].behavior === null) { + return [null]; + } + returnString1D.push(data[Number(search[i].behavior)]); } return returnString1D; } - /** * @brief member function to find the output for a certain actionID for state 'none' - * @param data :any an object containing all data read from a .keylayout file + * @param data an object containing all data read from a .keylayout file * @param search :string an actionId to be found * @return a string containing the output character */ - public getOutputFromActionIdNone(data: any, search: string): string { + public getOutputFromActionIdNone(data: Keylayout.KeylayoutXMLSourceFile, search: string): string { let OutputValue: string = ""; - for (let i = 0; i < data.keyboard.actions.action.length; i++) { - if (data.keyboard.actions.action[i]['id'] === search) { - for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { - if (data.keyboard.actions.action[i].when[j]['state'] === "none") { - if (data.keyboard.actions.action[i].when[j]['output'] !== undefined) { - OutputValue = data.keyboard.actions.action[i].when[j]['output']; - } + + if (!data.keyboard?.actions?.action) { + return OutputValue; + } + + for (const action of data.keyboard.actions.action as Keylayout.KL_Action[]) { + if (action['id'] === search) { + for (const when of action.when as Keylayout.KL_When[]) { + if ((when['state'] === "none") && (when['output'] !== undefined)) { + OutputValue = when['output']; } } } @@ -861,11 +864,11 @@ export class XkbToKmnConverter { /** * @brief member function to return array of [Keycode,Keyname,actionId,actionIDIndex, output] for a given actionID in of [ actionID,state,output] - * @param data :any - an object containing all data read from a .keylayout file + * @param data an object containing all data read from a .keylayout file * @param search :idStateOutputObject[] - array of [{ actionID,state,output }] * @return a KeylayoutFileData[] containing [{Keycode,Keyname,actionId,actionID, output}] */ - public getKeyActionOutputArrayFromActionStateOutputArray(data: any, search: ActionStateOutput[]): KeylayoutFileData[] { + public getKeyActionOutputArrayFromActionStateOutputArray(data: Keylayout.KeylayoutXMLSourceFile, search: ActionStateOutput[]): KeylayoutFileData[] { if ((search === undefined) || (search === null)) return []; @@ -876,7 +879,7 @@ export class XkbToKmnConverter { for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['action'] === search[k].id && - data.keyboard.keyMapSet[0].keyMap[i].key[j]['code'] <= XkbToKmnConverter.MAX_KEY_IDENTIFIER) { + Number(data.keyboard.keyMapSet[0].keyMap[i].key[j]['code']) <= XkbToKmnConverter.MAX_KEY_IDENTIFIER) { const singleDataSet = { keyCode: data.keyboard.keyMapSet[0].keyMap[i].key[j]['code'], key: this.mapUkeleleKeycodeToVK(Number(data.keyboard.keyMapSet[0].keyMap[i].key[j]['code'])), @@ -894,24 +897,26 @@ export class XkbToKmnConverter { /** * @brief member function to get an array of all actionId-output pairs for a certain state - * @param data : any an object containing all data read from a .keylayout file + * @param data an object containing all data read from a .keylayout file * @param search : string a 'state' to be found * @return an array: idStateOutputObject[] containing all [{actionId, state, output}] for a certain state */ - public getActionStateOutputArrayFromActionState(data: any, search: string): ActionStateOutput[] { + public getActionStateOutputArrayFromActionState(data: Keylayout.KeylayoutXMLSourceFile, search: string): ActionStateOutput[] { const actionStateOutput: ActionStateOutput[] = []; - - for (let i = 0; i < data.keyboard.actions.action.length; i++) { - for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) { - if (data.keyboard.actions.action[i].when[j]['state'] === search) { - if (data.keyboard.actions.action[i].when[j]['output'] !== undefined) { - const singleDataSet = { - id: data.keyboard.actions.action[i]['id'], - state: data.keyboard.actions.action[i].when[j]['state'], - output: data.keyboard.actions.action[i].when[j]['output'] - }; - actionStateOutput.push(singleDataSet); + if (search !== "none" && data.keyboard?.actions?.action) { + for (const action of data.keyboard.actions.action) { + if (action.when) { + for (const when of action.when) { + if ((when['state'] === search) && (when['output'] !== undefined)) { + const singleDataSet = { + id: action['id'], + state: when['state'], + output: when['output'] + }; + actionStateOutput.push(singleDataSet as ActionStateOutput); + } } + } } } @@ -920,22 +925,22 @@ export class XkbToKmnConverter { /** * @brief member function to create an 2D array of [KeyName,actionId,behavior,modifier,output] - * @param data : any an object containing all data read from a .keylayout file + * @param data an object containing all data read from a .keylayout file * @param search : array of [{keycode,keyname,actionId,behavior,output}] to be found * @param isCAPSused : boolean flag to indicate if CAPS is used in a keylayout file or not * @return an array: KeylayoutFileData[] containing [{KeyName,actionId,behavior,modifier,output}] */ - public getKeyBehaviorModOutputArrayFromKeyActionBehaviorOutputArray(data: any, search: KeylayoutFileData[], isCAPSused: boolean): KeylayoutFileData[] { + public getKeyBehaviorModOutputArrayFromKeyActionBehaviorOutputArray(data: Keylayout.KeylayoutXMLSourceFile, search: KeylayoutFileData[], isCAPSused: boolean): KeylayoutFileData[] { const keyBehaviorModOutput = []; if (!((search === undefined) || (search === null) || (search.length === 0))) { for (let i = 0; i < search.length; i++) { const behaviorIdx: number = Number(search[i].behavior); - for (let j = 0; j < data.keyboard.modifierMap.keyMapSelect[behaviorIdx].modifier.length; j++) { + for (let j = 0; j < data.keyboard.modifierMap[0].keyMapSelect[behaviorIdx].modifier.length; j++) { const singleDataSet = { actionId: search[i].actionId, key: search[i].key, behavior: search[i].behavior, - modifier: this.createKmnModifier(data.keyboard.modifierMap.keyMapSelect[behaviorIdx].modifier[j]['keys'], isCAPSused), + modifier: this.createKmnModifier(data.keyboard.modifierMap[0].keyMapSelect[behaviorIdx].modifier[j]['keys'], isCAPSused), outchar: search[i].outchar, }; keyBehaviorModOutput.push(singleDataSet); @@ -954,20 +959,20 @@ export class XkbToKmnConverter { unique.push(o); } return unique; - }, []); + }, [] as KeylayoutFileData[]); return uniquekeyBehaviorModOutput; } /** * @brief member function to create an array of [actionID, output, behavior,keyname,modifier] for a given actionId - * @param data : any - an object containing all data read from a .keylayout file - * @param modi : any - an array of modifiers + * @param data an object containing all data read from a .keylayout file + * @param modi an array of modifiers * @param search : string - an actionId to be found * @param outchar : string - the output character * @param isCAPSused : boolean - flag to indicate if CAPS is used in a keylayout file or not * @return an array: KeylayoutFileData[] containing [{actionID,output, behavior,keyname,modifier}] */ - public getActionOutputBehaviorKeyModiFromActionIDStateOutput(data: any, modi: string[][], search: string, outchar: string, isCapsused: boolean): KeylayoutFileData[] { + public getActionOutputBehaviorKeyModiFromActionIDStateOutput(data: Keylayout.KeylayoutXMLSourceFile, modi: string[][], search: string, outchar: string, isCapsused: boolean): KeylayoutFileData[] { const actionOutputBehaviorKeyModi = []; if ((!modi) || (search === "") || (search === undefined)) { return []; @@ -976,8 +981,8 @@ export class XkbToKmnConverter { for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['action'] === search) { - for (let k = 0; k < modi[data.keyboard.keyMapSet[0].keyMap[i]['index']].length; k++) { - const behaviorIdx: number = data.keyboard.keyMapSet[0].keyMap[i]['index']; + for (let k = 0; k < modi[Number(data.keyboard.keyMapSet[0].keyMap[i]['index'])].length; k++) { + const behaviorIdx: number = Number(data.keyboard.keyMapSet[0].keyMap[i]['index']); const singleDataSet = { outchar: outchar, actionId: data.keyboard.keyMapSet[0].keyMap[i].key[j]['action'], @@ -1005,18 +1010,18 @@ export class XkbToKmnConverter { unique.push(o); } return unique; - }, []); + }, [] as KeylayoutFileData[]); return uniqueactionOutputBehaviorKey; } /** * @brief member function to create an array of [{keycode,behavior}] for a given actionId - * @param data : any - an object containing all data read from a .keylayout file + * @param data an object containing all data read from a .keylayout file * @param search : string - an actionId to be found * @return an array: KeylayoutFileData[] containing [{keycode,behavior}] */ - public getKeyModifierArrayFromActionID(data: any, search: string): KeylayoutFileData[] { + public getKeyModifierArrayFromActionID(data: Keylayout.KeylayoutXMLSourceFile, search: string): KeylayoutFileData[] { const mapIndexObject1D: KeylayoutFileData[] = []; for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { diff --git a/developer/src/kmc-convert/test/xkb-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/xkb-to-kmn-converter.tests.ts index c6c9c522aa1..91a2dd1025c 100644 --- a/developer/src/kmc-convert/test/xkb-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/xkb-to-kmn-converter.tests.ts @@ -184,24 +184,6 @@ describe('XkbToKmnConverter', function () { assert.isNull(convertedEmpty); }); - it('should return empty on only modifiers as input', async function () { - const convertedMod = sut.convertBound.convert({ - keylayoutFilename: '', - modifiers: [['caps'], ['Shift'], ['command']], - rules: [] - }, ''); - assert.isNull(convertedMod); - }); - - it('should return empty on only rules as input', async function () { - const convertedRule = sut.convertBound.convert({ - keylayoutFilename: '', - modifiers: [], - rules: [['C0', '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_A', 'A']] - }, ''); - assert.isNull(convertedRule); - }); - it('should return empty array of rules on null input', async function () { const convertedRule = sut.convertBound.convert(null, 'ABC.kmn'); assert.isNull(convertedRule); @@ -354,7 +336,7 @@ describe('XkbToKmnConverter', function () { it((values[1] !== null) ? ("getModifierArrayFromKeyModifierArray('" + JSON.stringify(values[0]) + "')").padEnd(68, " ") + " should return '" + JSON.stringify(values[1]) + "'" : ("getModifierArrayFromKeyModifierArray('" + JSON.stringify(values[0]) + "')").padEnd(68, " ") + " should return '" + "null" + "'", async function () { - const result = sut.getModifierArrayFromKeyModifierArray(converted.modifiers, values[0] as KeylayoutFileData[]); + const result = sut.getModifierArrayFromKeyModifierArray(converted.modifiers, values[0] as unknown as KeylayoutFileData[]); assert.deepStrictEqual(JSON.stringify(result), JSON.stringify(values[1])); }); }); From cbf3dee04f42de1cb79d640296e0732bfaa63a3a Mon Sep 17 00:00:00 2001 From: Sabine Date: Thu, 7 May 2026 09:21:30 +0200 Subject: [PATCH 240/251] feat(developer): move testfiles to seperate folders for each conversion --- .../Test copy.keylayout} | 0 .../Test.keylayout} | 0 .../test/data/tests-keylayout-kmn/Test.xkb | 596 ++++++++++++++++++ .../Test_C0.keylayout | 0 .../Test_C0_C1_C2_C3.keylayout | 0 .../Test_C1.keylayout | 0 .../Test_C2.keylayout | 0 .../Test_C2_several.keylayout | 0 .../Test_C3.keylayout | 0 .../Test_C3_several.keylayout | 0 .../Test_ExtraWarning.keylayout | 0 .../Test_ambiguous_keys.keylayout | 0 .../Test_characters.keylayout | 0 ...ifferentAmountOfKeysInBehaviours.keylayout | 0 .../Test_differentEncodings.keylayout | 0 .../Test_duplicate_keys.keylayout | 0 .../Test_duplicate_missing_keycode.keylayout | 0 .../Test_duplicate_missing_keys.keylayout | 0 .../Test_maxKeyCode.keylayout | 0 .../Test_messages.keylayout | 0 .../Test_messages_controlCharacter.keylayout | 0 .../Test_messages_superior_C2.keylayout | 0 .../Test_messages_superior_C3.keylayout | 0 .../Test_modifier.keylayout | 0 .../Test_modifierNoCaps.keylayout | 0 ...eyMapThanKeyMapselectAndJisERROR.keylayout | 0 ..._moreKeyMapThanKeyMapselectERROR.keylayout | 0 ..._moreKeymapSelectThanKeymapERROR.keylayout | 0 .../Test_nr_elements.keylayout | 0 .../Test_onlyOneKeymap.keylayout | 0 .../Test_undefinedAction.keylayout | 0 .../Test_unsupportedCharacters.keylayout | 0 .../data/tests-xkb-kmn/Test copy.keylayout | 596 ++++++++++++++++++ .../test/data/tests-xkb-kmn/Test.keylayout | 596 ++++++++++++++++++ .../test/data/tests-xkb-kmn/Test.xkb | 596 ++++++++++++++++++ .../test/data/tests-xkb-kmn/Test_C0.keylayout | 45 ++ .../tests-xkb-kmn/Test_C0_C1_C2_C3.keylayout | 58 ++ .../test/data/tests-xkb-kmn/Test_C1.keylayout | 43 ++ .../test/data/tests-xkb-kmn/Test_C2.keylayout | 43 ++ .../tests-xkb-kmn/Test_C2_several.keylayout | 73 +++ .../test/data/tests-xkb-kmn/Test_C3.keylayout | 53 ++ .../tests-xkb-kmn/Test_C3_several.keylayout | 59 ++ .../tests-xkb-kmn/Test_ExtraWarning.keylayout | 76 +++ .../Test_ambiguous_keys.keylayout | 57 ++ .../tests-xkb-kmn/Test_characters.keylayout | 51 ++ ...ifferentAmountOfKeysInBehaviours.keylayout | 45 ++ .../Test_differentEncodings.keylayout | 37 ++ .../Test_duplicate_keys.keylayout | 61 ++ .../Test_duplicate_missing_keycode.keylayout | 49 ++ .../Test_duplicate_missing_keys.keylayout | 59 ++ .../tests-xkb-kmn/Test_maxKeyCode.keylayout | 38 ++ .../tests-xkb-kmn/Test_messages.keylayout | 80 +++ .../Test_messages_controlCharacter.keylayout | 57 ++ .../Test_messages_superior_C2.keylayout | 72 +++ .../Test_messages_superior_C3.keylayout | 59 ++ .../tests-xkb-kmn/Test_modifier.keylayout | 103 +++ .../Test_modifierNoCaps.keylayout | 108 ++++ ...eyMapThanKeyMapselectAndJisERROR.keylayout | 83 +++ ..._moreKeyMapThanKeyMapselectERROR.keylayout | 78 +++ ..._moreKeymapSelectThanKeymapERROR.keylayout | 65 ++ .../tests-xkb-kmn/Test_nr_elements.keylayout | 45 ++ .../Test_onlyOneKeymap.keylayout | 39 ++ .../Test_undefinedAction.keylayout | 58 ++ .../Test_unsupportedCharacters.keylayout | 58 ++ .../data/{ => tests-xkb-kmn}/keylayout.dtd | 0 .../test/keylayout-to-kmn-converter.tests.ts | 116 ++-- .../kmc-convert/test/kmn-file-reader.tests.ts | 4 +- .../kmc-convert/test/kmn-file-writer.tests.ts | 4 +- .../test/kmnXKB-file-writer.tests.ts | 16 +- .../kmc-convert/test/xkb-file-reader.tests.ts | 4 +- .../test/xkb-to-kmn-converter.tests.ts | 112 ++-- 71 files changed, 4264 insertions(+), 128 deletions(-) rename developer/src/kmc-convert/test/data/{Test.keylayout => tests-keylayout-kmn/Test copy.keylayout} (100%) rename developer/src/kmc-convert/test/data/{Test.xkb => tests-keylayout-kmn/Test.keylayout} (100%) create mode 100644 developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test.xkb rename developer/src/kmc-convert/test/data/{ => tests-keylayout-kmn}/Test_C0.keylayout (100%) rename developer/src/kmc-convert/test/data/{ => tests-keylayout-kmn}/Test_C0_C1_C2_C3.keylayout (100%) rename developer/src/kmc-convert/test/data/{ => tests-keylayout-kmn}/Test_C1.keylayout (100%) rename developer/src/kmc-convert/test/data/{ => tests-keylayout-kmn}/Test_C2.keylayout (100%) rename developer/src/kmc-convert/test/data/{ => tests-keylayout-kmn}/Test_C2_several.keylayout (100%) rename developer/src/kmc-convert/test/data/{ => tests-keylayout-kmn}/Test_C3.keylayout (100%) rename developer/src/kmc-convert/test/data/{ => tests-keylayout-kmn}/Test_C3_several.keylayout (100%) rename developer/src/kmc-convert/test/data/{ => tests-keylayout-kmn}/Test_ExtraWarning.keylayout (100%) rename developer/src/kmc-convert/test/data/{ => tests-keylayout-kmn}/Test_ambiguous_keys.keylayout (100%) rename developer/src/kmc-convert/test/data/{ => tests-keylayout-kmn}/Test_characters.keylayout (100%) rename developer/src/kmc-convert/test/data/{ => tests-keylayout-kmn}/Test_differentAmountOfKeysInBehaviours.keylayout (100%) rename developer/src/kmc-convert/test/data/{ => tests-keylayout-kmn}/Test_differentEncodings.keylayout (100%) rename developer/src/kmc-convert/test/data/{ => tests-keylayout-kmn}/Test_duplicate_keys.keylayout (100%) rename developer/src/kmc-convert/test/data/{ => tests-keylayout-kmn}/Test_duplicate_missing_keycode.keylayout (100%) rename developer/src/kmc-convert/test/data/{ => tests-keylayout-kmn}/Test_duplicate_missing_keys.keylayout (100%) rename developer/src/kmc-convert/test/data/{ => tests-keylayout-kmn}/Test_maxKeyCode.keylayout (100%) rename developer/src/kmc-convert/test/data/{ => tests-keylayout-kmn}/Test_messages.keylayout (100%) rename developer/src/kmc-convert/test/data/{ => tests-keylayout-kmn}/Test_messages_controlCharacter.keylayout (100%) rename developer/src/kmc-convert/test/data/{ => tests-keylayout-kmn}/Test_messages_superior_C2.keylayout (100%) rename developer/src/kmc-convert/test/data/{ => tests-keylayout-kmn}/Test_messages_superior_C3.keylayout (100%) rename developer/src/kmc-convert/test/data/{ => tests-keylayout-kmn}/Test_modifier.keylayout (100%) rename developer/src/kmc-convert/test/data/{ => tests-keylayout-kmn}/Test_modifierNoCaps.keylayout (100%) rename developer/src/kmc-convert/test/data/{ => tests-keylayout-kmn}/Test_moreKeyMapThanKeyMapselectAndJisERROR.keylayout (100%) rename developer/src/kmc-convert/test/data/{ => tests-keylayout-kmn}/Test_moreKeyMapThanKeyMapselectERROR.keylayout (100%) rename developer/src/kmc-convert/test/data/{ => tests-keylayout-kmn}/Test_moreKeymapSelectThanKeymapERROR.keylayout (100%) rename developer/src/kmc-convert/test/data/{ => tests-keylayout-kmn}/Test_nr_elements.keylayout (100%) rename developer/src/kmc-convert/test/data/{ => tests-keylayout-kmn}/Test_onlyOneKeymap.keylayout (100%) rename developer/src/kmc-convert/test/data/{ => tests-keylayout-kmn}/Test_undefinedAction.keylayout (100%) rename developer/src/kmc-convert/test/data/{ => tests-keylayout-kmn}/Test_unsupportedCharacters.keylayout (100%) create mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test copy.keylayout create mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test.keylayout create mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test.xkb create mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_C0.keylayout create mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_C0_C1_C2_C3.keylayout create mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_C1.keylayout create mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_C2.keylayout create mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_C2_several.keylayout create mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_C3.keylayout create mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_C3_several.keylayout create mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_ExtraWarning.keylayout create mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_ambiguous_keys.keylayout create mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_characters.keylayout create mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_differentAmountOfKeysInBehaviours.keylayout create mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_differentEncodings.keylayout create mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_duplicate_keys.keylayout create mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_duplicate_missing_keycode.keylayout create mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_duplicate_missing_keys.keylayout create mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_maxKeyCode.keylayout create mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_messages.keylayout create mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_messages_controlCharacter.keylayout create mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_messages_superior_C2.keylayout create mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_messages_superior_C3.keylayout create mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_modifier.keylayout create mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_modifierNoCaps.keylayout create mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_moreKeyMapThanKeyMapselectAndJisERROR.keylayout create mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_moreKeyMapThanKeyMapselectERROR.keylayout create mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_moreKeymapSelectThanKeymapERROR.keylayout create mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_nr_elements.keylayout create mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_onlyOneKeymap.keylayout create mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_undefinedAction.keylayout create mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_unsupportedCharacters.keylayout rename developer/src/kmc-convert/test/data/{ => tests-xkb-kmn}/keylayout.dtd (100%) diff --git a/developer/src/kmc-convert/test/data/Test.keylayout b/developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test copy.keylayout similarity index 100% rename from developer/src/kmc-convert/test/data/Test.keylayout rename to developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test copy.keylayout diff --git a/developer/src/kmc-convert/test/data/Test.xkb b/developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test.keylayout similarity index 100% rename from developer/src/kmc-convert/test/data/Test.xkb rename to developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test.keylayout diff --git a/developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test.xkb b/developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test.xkb new file mode 100644 index 00000000000..76fd91b4db6 --- /dev/null +++ b/developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test.xkb @@ -0,0 +1,596 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/Test_C0.keylayout b/developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test_C0.keylayout similarity index 100% rename from developer/src/kmc-convert/test/data/Test_C0.keylayout rename to developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test_C0.keylayout diff --git a/developer/src/kmc-convert/test/data/Test_C0_C1_C2_C3.keylayout b/developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test_C0_C1_C2_C3.keylayout similarity index 100% rename from developer/src/kmc-convert/test/data/Test_C0_C1_C2_C3.keylayout rename to developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test_C0_C1_C2_C3.keylayout diff --git a/developer/src/kmc-convert/test/data/Test_C1.keylayout b/developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test_C1.keylayout similarity index 100% rename from developer/src/kmc-convert/test/data/Test_C1.keylayout rename to developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test_C1.keylayout diff --git a/developer/src/kmc-convert/test/data/Test_C2.keylayout b/developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test_C2.keylayout similarity index 100% rename from developer/src/kmc-convert/test/data/Test_C2.keylayout rename to developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test_C2.keylayout diff --git a/developer/src/kmc-convert/test/data/Test_C2_several.keylayout b/developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test_C2_several.keylayout similarity index 100% rename from developer/src/kmc-convert/test/data/Test_C2_several.keylayout rename to developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test_C2_several.keylayout diff --git a/developer/src/kmc-convert/test/data/Test_C3.keylayout b/developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test_C3.keylayout similarity index 100% rename from developer/src/kmc-convert/test/data/Test_C3.keylayout rename to developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test_C3.keylayout diff --git a/developer/src/kmc-convert/test/data/Test_C3_several.keylayout b/developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test_C3_several.keylayout similarity index 100% rename from developer/src/kmc-convert/test/data/Test_C3_several.keylayout rename to developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test_C3_several.keylayout diff --git a/developer/src/kmc-convert/test/data/Test_ExtraWarning.keylayout b/developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test_ExtraWarning.keylayout similarity index 100% rename from developer/src/kmc-convert/test/data/Test_ExtraWarning.keylayout rename to developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test_ExtraWarning.keylayout diff --git a/developer/src/kmc-convert/test/data/Test_ambiguous_keys.keylayout b/developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test_ambiguous_keys.keylayout similarity index 100% rename from developer/src/kmc-convert/test/data/Test_ambiguous_keys.keylayout rename to developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test_ambiguous_keys.keylayout diff --git a/developer/src/kmc-convert/test/data/Test_characters.keylayout b/developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test_characters.keylayout similarity index 100% rename from developer/src/kmc-convert/test/data/Test_characters.keylayout rename to developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test_characters.keylayout diff --git a/developer/src/kmc-convert/test/data/Test_differentAmountOfKeysInBehaviours.keylayout b/developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test_differentAmountOfKeysInBehaviours.keylayout similarity index 100% rename from developer/src/kmc-convert/test/data/Test_differentAmountOfKeysInBehaviours.keylayout rename to developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test_differentAmountOfKeysInBehaviours.keylayout diff --git a/developer/src/kmc-convert/test/data/Test_differentEncodings.keylayout b/developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test_differentEncodings.keylayout similarity index 100% rename from developer/src/kmc-convert/test/data/Test_differentEncodings.keylayout rename to developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test_differentEncodings.keylayout diff --git a/developer/src/kmc-convert/test/data/Test_duplicate_keys.keylayout b/developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test_duplicate_keys.keylayout similarity index 100% rename from developer/src/kmc-convert/test/data/Test_duplicate_keys.keylayout rename to developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test_duplicate_keys.keylayout diff --git a/developer/src/kmc-convert/test/data/Test_duplicate_missing_keycode.keylayout b/developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test_duplicate_missing_keycode.keylayout similarity index 100% rename from developer/src/kmc-convert/test/data/Test_duplicate_missing_keycode.keylayout rename to developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test_duplicate_missing_keycode.keylayout diff --git a/developer/src/kmc-convert/test/data/Test_duplicate_missing_keys.keylayout b/developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test_duplicate_missing_keys.keylayout similarity index 100% rename from developer/src/kmc-convert/test/data/Test_duplicate_missing_keys.keylayout rename to developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test_duplicate_missing_keys.keylayout diff --git a/developer/src/kmc-convert/test/data/Test_maxKeyCode.keylayout b/developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test_maxKeyCode.keylayout similarity index 100% rename from developer/src/kmc-convert/test/data/Test_maxKeyCode.keylayout rename to developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test_maxKeyCode.keylayout diff --git a/developer/src/kmc-convert/test/data/Test_messages.keylayout b/developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test_messages.keylayout similarity index 100% rename from developer/src/kmc-convert/test/data/Test_messages.keylayout rename to developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test_messages.keylayout diff --git a/developer/src/kmc-convert/test/data/Test_messages_controlCharacter.keylayout b/developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test_messages_controlCharacter.keylayout similarity index 100% rename from developer/src/kmc-convert/test/data/Test_messages_controlCharacter.keylayout rename to developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test_messages_controlCharacter.keylayout diff --git a/developer/src/kmc-convert/test/data/Test_messages_superior_C2.keylayout b/developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test_messages_superior_C2.keylayout similarity index 100% rename from developer/src/kmc-convert/test/data/Test_messages_superior_C2.keylayout rename to developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test_messages_superior_C2.keylayout diff --git a/developer/src/kmc-convert/test/data/Test_messages_superior_C3.keylayout b/developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test_messages_superior_C3.keylayout similarity index 100% rename from developer/src/kmc-convert/test/data/Test_messages_superior_C3.keylayout rename to developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test_messages_superior_C3.keylayout diff --git a/developer/src/kmc-convert/test/data/Test_modifier.keylayout b/developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test_modifier.keylayout similarity index 100% rename from developer/src/kmc-convert/test/data/Test_modifier.keylayout rename to developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test_modifier.keylayout diff --git a/developer/src/kmc-convert/test/data/Test_modifierNoCaps.keylayout b/developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test_modifierNoCaps.keylayout similarity index 100% rename from developer/src/kmc-convert/test/data/Test_modifierNoCaps.keylayout rename to developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test_modifierNoCaps.keylayout diff --git a/developer/src/kmc-convert/test/data/Test_moreKeyMapThanKeyMapselectAndJisERROR.keylayout b/developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test_moreKeyMapThanKeyMapselectAndJisERROR.keylayout similarity index 100% rename from developer/src/kmc-convert/test/data/Test_moreKeyMapThanKeyMapselectAndJisERROR.keylayout rename to developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test_moreKeyMapThanKeyMapselectAndJisERROR.keylayout diff --git a/developer/src/kmc-convert/test/data/Test_moreKeyMapThanKeyMapselectERROR.keylayout b/developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test_moreKeyMapThanKeyMapselectERROR.keylayout similarity index 100% rename from developer/src/kmc-convert/test/data/Test_moreKeyMapThanKeyMapselectERROR.keylayout rename to developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test_moreKeyMapThanKeyMapselectERROR.keylayout diff --git a/developer/src/kmc-convert/test/data/Test_moreKeymapSelectThanKeymapERROR.keylayout b/developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test_moreKeymapSelectThanKeymapERROR.keylayout similarity index 100% rename from developer/src/kmc-convert/test/data/Test_moreKeymapSelectThanKeymapERROR.keylayout rename to developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test_moreKeymapSelectThanKeymapERROR.keylayout diff --git a/developer/src/kmc-convert/test/data/Test_nr_elements.keylayout b/developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test_nr_elements.keylayout similarity index 100% rename from developer/src/kmc-convert/test/data/Test_nr_elements.keylayout rename to developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test_nr_elements.keylayout diff --git a/developer/src/kmc-convert/test/data/Test_onlyOneKeymap.keylayout b/developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test_onlyOneKeymap.keylayout similarity index 100% rename from developer/src/kmc-convert/test/data/Test_onlyOneKeymap.keylayout rename to developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test_onlyOneKeymap.keylayout diff --git a/developer/src/kmc-convert/test/data/Test_undefinedAction.keylayout b/developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test_undefinedAction.keylayout similarity index 100% rename from developer/src/kmc-convert/test/data/Test_undefinedAction.keylayout rename to developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test_undefinedAction.keylayout diff --git a/developer/src/kmc-convert/test/data/Test_unsupportedCharacters.keylayout b/developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test_unsupportedCharacters.keylayout similarity index 100% rename from developer/src/kmc-convert/test/data/Test_unsupportedCharacters.keylayout rename to developer/src/kmc-convert/test/data/tests-keylayout-kmn/Test_unsupportedCharacters.keylayout diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test copy.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test copy.keylayout new file mode 100644 index 00000000000..76fd91b4db6 --- /dev/null +++ b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test copy.keylayout @@ -0,0 +1,596 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test.keylayout new file mode 100644 index 00000000000..76fd91b4db6 --- /dev/null +++ b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test.keylayout @@ -0,0 +1,596 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test.xkb b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test.xkb new file mode 100644 index 00000000000..76fd91b4db6 --- /dev/null +++ b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test.xkb @@ -0,0 +1,596 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_C0.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_C0.keylayout new file mode 100644 index 00000000000..d8c49ea62ae --- /dev/null +++ b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_C0.keylayout @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_C0_C1_C2_C3.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_C0_C1_C2_C3.keylayout new file mode 100644 index 00000000000..f1f3ebab1e5 --- /dev/null +++ b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_C0_C1_C2_C3.keylayout @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_C1.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_C1.keylayout new file mode 100644 index 00000000000..e785e58ca18 --- /dev/null +++ b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_C1.keylayout @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_C2.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_C2.keylayout new file mode 100644 index 00000000000..aa6b60997bc --- /dev/null +++ b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_C2.keylayout @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_C2_several.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_C2_several.keylayout new file mode 100644 index 00000000000..d51369c934c --- /dev/null +++ b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_C2_several.keylayout @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_C3.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_C3.keylayout new file mode 100644 index 00000000000..6275a230bbf --- /dev/null +++ b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_C3.keylayout @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_C3_several.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_C3_several.keylayout new file mode 100644 index 00000000000..7fff380f2cc --- /dev/null +++ b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_C3_several.keylayout @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_ExtraWarning.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_ExtraWarning.keylayout new file mode 100644 index 00000000000..0d36b2a5fea --- /dev/null +++ b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_ExtraWarning.keylayout @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_ambiguous_keys.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_ambiguous_keys.keylayout new file mode 100644 index 00000000000..97778e876ee --- /dev/null +++ b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_ambiguous_keys.keylayout @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_characters.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_characters.keylayout new file mode 100644 index 00000000000..2aae8f1bb46 --- /dev/null +++ b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_characters.keylayout @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_differentAmountOfKeysInBehaviours.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_differentAmountOfKeysInBehaviours.keylayout new file mode 100644 index 00000000000..4b770866cd6 --- /dev/null +++ b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_differentAmountOfKeysInBehaviours.keylayout @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_differentEncodings.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_differentEncodings.keylayout new file mode 100644 index 00000000000..c526f8c2af8 --- /dev/null +++ b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_differentEncodings.keylayout @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_duplicate_keys.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_duplicate_keys.keylayout new file mode 100644 index 00000000000..a5cb09069bf --- /dev/null +++ b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_duplicate_keys.keylayout @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_duplicate_missing_keycode.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_duplicate_missing_keycode.keylayout new file mode 100644 index 00000000000..39da3300f4f --- /dev/null +++ b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_duplicate_missing_keycode.keylayout @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_duplicate_missing_keys.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_duplicate_missing_keys.keylayout new file mode 100644 index 00000000000..b3670561432 --- /dev/null +++ b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_duplicate_missing_keys.keylayout @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_maxKeyCode.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_maxKeyCode.keylayout new file mode 100644 index 00000000000..a5f9e178b99 --- /dev/null +++ b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_maxKeyCode.keylayout @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_messages.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_messages.keylayout new file mode 100644 index 00000000000..5d8d1b86820 --- /dev/null +++ b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_messages.keylayout @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_messages_controlCharacter.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_messages_controlCharacter.keylayout new file mode 100644 index 00000000000..f97abb984d2 --- /dev/null +++ b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_messages_controlCharacter.keylayout @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_messages_superior_C2.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_messages_superior_C2.keylayout new file mode 100644 index 00000000000..3416bb5e8ff --- /dev/null +++ b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_messages_superior_C2.keylayout @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_messages_superior_C3.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_messages_superior_C3.keylayout new file mode 100644 index 00000000000..f95afe40db5 --- /dev/null +++ b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_messages_superior_C3.keylayout @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_modifier.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_modifier.keylayout new file mode 100644 index 00000000000..67ccf4db63e --- /dev/null +++ b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_modifier.keylayout @@ -0,0 +1,103 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_modifierNoCaps.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_modifierNoCaps.keylayout new file mode 100644 index 00000000000..9656413d7e6 --- /dev/null +++ b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_modifierNoCaps.keylayout @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_moreKeyMapThanKeyMapselectAndJisERROR.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_moreKeyMapThanKeyMapselectAndJisERROR.keylayout new file mode 100644 index 00000000000..13be153d756 --- /dev/null +++ b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_moreKeyMapThanKeyMapselectAndJisERROR.keylayout @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_moreKeyMapThanKeyMapselectERROR.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_moreKeyMapThanKeyMapselectERROR.keylayout new file mode 100644 index 00000000000..3bd9b5ba491 --- /dev/null +++ b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_moreKeyMapThanKeyMapselectERROR.keylayout @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_moreKeymapSelectThanKeymapERROR.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_moreKeymapSelectThanKeymapERROR.keylayout new file mode 100644 index 00000000000..25d178237cb --- /dev/null +++ b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_moreKeymapSelectThanKeymapERROR.keylayout @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_nr_elements.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_nr_elements.keylayout new file mode 100644 index 00000000000..7a32f4b3c25 --- /dev/null +++ b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_nr_elements.keylayout @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_onlyOneKeymap.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_onlyOneKeymap.keylayout new file mode 100644 index 00000000000..8f173994576 --- /dev/null +++ b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_onlyOneKeymap.keylayout @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_undefinedAction.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_undefinedAction.keylayout new file mode 100644 index 00000000000..4e6f0ce8023 --- /dev/null +++ b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_undefinedAction.keylayout @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_unsupportedCharacters.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_unsupportedCharacters.keylayout new file mode 100644 index 00000000000..d393b332ee6 --- /dev/null +++ b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_unsupportedCharacters.keylayout @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/data/keylayout.dtd b/developer/src/kmc-convert/test/data/tests-xkb-kmn/keylayout.dtd similarity index 100% rename from developer/src/kmc-convert/test/data/keylayout.dtd rename to developer/src/kmc-convert/test/data/tests-xkb-kmn/keylayout.dtd diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index a7010ef1e7d..f8e7173bc02 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -23,29 +23,29 @@ describe('KeylayoutToKmnConverter', function () { describe('RunSpecialTestFiles', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); [ - [makePathToFixture('../data/Test_C0.keylayout')], - [makePathToFixture('../data/Test_C1.keylayout')], - [makePathToFixture('../data/Test_C2.keylayout')], - [makePathToFixture('../data/Test_C2_several.keylayout')], - [makePathToFixture('../data/Test_C3.keylayout')], - [makePathToFixture('../data/Test_C3_several.keylayout')], - [makePathToFixture('../data/Test_C0_C1_C2_C3.keylayout')], - [makePathToFixture('../data/Test_maxKeyCode.keylayout')], - [makePathToFixture('../data/Test_messages.keylayout')], - [makePathToFixture('../data/Test_messages_controlCharacter.keylayout')], - [makePathToFixture('../data/Test_messages_superior_C2.keylayout')], - [makePathToFixture('../data/Test_messages_superior_C3.keylayout')], - [makePathToFixture('../data/Test_duplicate_missing_keycode.keylayout')], - [makePathToFixture('../data/Test_modifier.keylayout')], - [makePathToFixture('../data/Test_modifierNoCaps.keylayout')], - [makePathToFixture('../data/Test_differentAmountOfKeysInBehaviours.keylayout')], - [makePathToFixture('../data/Test_duplicate_missing_keys.keylayout')], - [makePathToFixture('../data/Test_duplicate_keys.keylayout')], - [makePathToFixture('../data/Test_ambiguous_keys.keylayout')], - [makePathToFixture('../data/Test_nr_elements.keylayout')], - [makePathToFixture('../data/Test.keylayout')], - [makePathToFixture('../data/Test_differentEncodings.keylayout')], - [makePathToFixture('../data/Test_ExtraWarning.keylayout')], + [makePathToFixture('../data/tests-keylayout-kmn/Test_C0.keylayout')], + [makePathToFixture('../data/tests-keylayout-kmn/Test_C1.keylayout')], + [makePathToFixture('../data/tests-keylayout-kmn/Test_C2.keylayout')], + [makePathToFixture('../data/tests-keylayout-kmn/Test_C2_several.keylayout')], + [makePathToFixture('../data/tests-keylayout-kmn/Test_C3.keylayout')], + [makePathToFixture('../data/tests-keylayout-kmn/Test_C3_several.keylayout')], + [makePathToFixture('../data/tests-keylayout-kmn/Test_C0_C1_C2_C3.keylayout')], + [makePathToFixture('../data/tests-keylayout-kmn/Test_maxKeyCode.keylayout')], + [makePathToFixture('../data/tests-keylayout-kmn/Test_messages.keylayout')], + [makePathToFixture('../data/tests-keylayout-kmn/Test_messages_controlCharacter.keylayout')], + [makePathToFixture('../data/tests-keylayout-kmn/Test_messages_superior_C2.keylayout')], + [makePathToFixture('../data/tests-keylayout-kmn/Test_messages_superior_C3.keylayout')], + [makePathToFixture('../data/tests-keylayout-kmn/Test_duplicate_missing_keycode.keylayout')], + [makePathToFixture('../data/tests-keylayout-kmn/Test_modifier.keylayout')], + [makePathToFixture('../data/tests-keylayout-kmn/Test_modifierNoCaps.keylayout')], + [makePathToFixture('../data/tests-keylayout-kmn/Test_differentAmountOfKeysInBehaviours.keylayout')], + [makePathToFixture('../data/tests-keylayout-kmn/Test_duplicate_missing_keys.keylayout')], + [makePathToFixture('../data/tests-keylayout-kmn/Test_duplicate_keys.keylayout')], + [makePathToFixture('../data/tests-keylayout-kmn/Test_ambiguous_keys.keylayout')], + [makePathToFixture('../data/tests-keylayout-kmn/Test_nr_elements.keylayout')], + [makePathToFixture('../data/tests-keylayout-kmn/Test.keylayout')], + [makePathToFixture('../data/tests-keylayout-kmn/Test_differentEncodings.keylayout')], + [makePathToFixture('../data/tests-keylayout-kmn/Test_ExtraWarning.keylayout')], ].forEach(function (files) { it(files + " should give no errors ", async function () { sut.run(files[0]); @@ -57,17 +57,17 @@ describe('KeylayoutToKmnConverter', function () { describe('RunTestFiles resulting in errors ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); [ - [makePathToFixture('../data/Test_moreKeyMapThanKeyMapselectERROR.keylayout')], - [makePathToFixture('../data/Test_moreKeyMapThanKeyMapselectAndJisERROR.keylayout')], - [makePathToFixture('../data/Test_moreKeyMapThanKeyMapselectERROR.keylayout')], - [makePathToFixture('../data/Test_MissingkeyERROR.keylayout')], - [makePathToFixture('../data/Test_MissingkeyMapERROR.keylayout')], - [makePathToFixture('../data/Test_MissingLayoutsERROR.keylayout')], - [makePathToFixture('../data/Test_MissingmodifierMapERROR.keylayout')], - [makePathToFixture('../data/Test_MissingkeyMapSetERROR.keylayout')], - [makePathToFixture('../data/Test_MissingActionsERROR.keylayout')], - [makePathToFixture('../data/Test_MissingTerminatorsERROR.keylayout')], - [makePathToFixture('../data/Test_MissingAllERROR.keylayout')], + [makePathToFixture('../data/tests-keylayout-kmn/Test_moreKeyMapThanKeyMapselectERROR.keylayout')], + [makePathToFixture('../data/tests-keylayout-kmn/Test_moreKeyMapThanKeyMapselectAndJisERROR.keylayout')], + [makePathToFixture('../data/tests-keylayout-kmn/Test_moreKeyMapThanKeyMapselectERROR.keylayout')], + [makePathToFixture('../data/tests-keylayout-kmn/Test_MissingkeyERROR.keylayout')], + [makePathToFixture('../data/tests-keylayout-kmn/Test_MissingkeyMapERROR.keylayout')], + [makePathToFixture('../data/tests-keylayout-kmn/Test_MissingLayoutsERROR.keylayout')], + [makePathToFixture('../data/tests-keylayout-kmn/Test_MissingmodifierMapERROR.keylayout')], + [makePathToFixture('../data/tests-keylayout-kmn/Test_MissingkeyMapSetERROR.keylayout')], + [makePathToFixture('../data/tests-keylayout-kmn/Test_MissingActionsERROR.keylayout')], + [makePathToFixture('../data/tests-keylayout-kmn/Test_MissingTerminatorsERROR.keylayout')], + [makePathToFixture('../data/tests-keylayout-kmn/Test_MissingAllERROR.keylayout')], ].forEach(function (files) { it(files + " should give an error ", async function () { sut.run(files[0]); @@ -79,7 +79,7 @@ describe('KeylayoutToKmnConverter', function () { describe('RunSpecialTestFiles - create Error: unsupported characters', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); [ - [makePathToFixture('../data/Test_characters.keylayout')], + [makePathToFixture('../data/tests-keylayout-kmn/Test_characters.keylayout')], ].forEach(function (files) { it(files + " should give Error: unsupported characters ", async function () { sut.run(files[0]); @@ -91,7 +91,7 @@ describe('KeylayoutToKmnConverter', function () { describe('RunSpecialTestFiles - create Error: undefined action', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); [ - [makePathToFixture('../data/Test_undefinedAction.keylayout')], + [makePathToFixture('../data/tests-keylayout-kmn/Test_undefinedAction.keylayout')], ].forEach(function (files) { it(files + " should give Error: undefined action detected", async function () { sut.run(files[0]); @@ -127,7 +127,7 @@ describe('KeylayoutToKmnConverter', function () { }); it('run() should throw on unavailable input file name and null output file name', async function () { - const inputFilename = makePathToFixture('../data/Unavailable.keylayout'); + const inputFilename = makePathToFixture('../data/tests-keylayout-kmn/Unavailable.keylayout'); const result = sut.run(inputFilename, null); assert.isNotNull(result); assert.equal(compilerTestCallbacks.messages.length, 2); @@ -139,14 +139,14 @@ describe('KeylayoutToKmnConverter', function () { describe('Run kmc-convert with or without outputfile name', async function () { this.timeout(5000); // allow longer time for this test const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const infile = '../data/Test.keylayout'; + const infile = '../data/tests-keylayout-kmn/Test.keylayout'; [ - [makePathToFixture('../data/Test.kmn')], + [makePathToFixture('../data/tests-keylayout-kmn/Test.kmn')], [makePathToFixture('')], [], [null], - [makePathToFixture('../data/test_OtherOutputName.kmn')], - [makePathToFixture('../data/OutputXName.bb')], + [makePathToFixture('../data/tests-keylayout-kmn/test_OtherOutputName.kmn')], + [makePathToFixture('../data/tests-keylayout-kmn/OutputXName.bb')], ].forEach(function (files) { it(infile + " should run ", async function () { await NodeAssert.doesNotReject(async () => sut.run(makePathToFixture(infile), files[0])); @@ -160,12 +160,12 @@ describe('KeylayoutToKmnConverter', function () { const sutR = new KeylayoutFileReader(compilerTestCallbacks); // ProcessedData from usable file - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../data/tests-keylayout-kmn/Test.keylayout'); const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); const converted = sut.convertBound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); // ProcessedData from unavailable file - const inputFilenameUnavailable = makePathToFixture('../data/X.keylayout'); + const inputFilenameUnavailable = makePathToFixture('../data/tests-keylayout-kmn/X.keylayout'); const readUnavailable = sutR.read(compilerTestCallbacks.loadFile(inputFilenameUnavailable)); const convertedUnavailable = sut.convertBound.convert(readUnavailable, inputFilenameUnavailable.replace(/\.keylayout$/, '.kmn')); @@ -322,7 +322,7 @@ describe('KeylayoutToKmnConverter', function () { describe('getModifierArrayFromKeyModifierArray ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sutR = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../data/tests-keylayout-kmn/Test.keylayout'); const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); const converted = sut.convertBound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); [ @@ -348,7 +348,7 @@ describe('KeylayoutToKmnConverter', function () { describe('getKeyModifierArrayFromActionID ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sutR = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../data/tests-keylayout-kmn/Test.keylayout'); const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); [ ['A_16', [{ "key": "32", "behavior": "5" }]], @@ -374,7 +374,7 @@ describe('KeylayoutToKmnConverter', function () { describe('getActionIdFromActionNext ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sutR = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../data/tests-keylayout-kmn/Test.keylayout'); const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); [ ['none', ''], @@ -400,7 +400,7 @@ describe('KeylayoutToKmnConverter', function () { describe('getActionIndexFromActionId ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sutR = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../data/tests-keylayout-kmn/Test.keylayout'); const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); [ ['none', -1], @@ -424,7 +424,7 @@ describe('KeylayoutToKmnConverter', function () { describe('getOutputFromActionIdNone ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sutR = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../data/tests-keylayout-kmn/Test.keylayout'); const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); [ ['A_14', 'u'], @@ -454,7 +454,7 @@ describe('KeylayoutToKmnConverter', function () { describe('getKeybehaviorModOutputArrayFromKeyActionbehaviorOutputArray ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sutR = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../data/tests-keylayout-kmn/Test.keylayout'); const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); const b1KeycodeArr: KeylayoutFileData[] = [ @@ -562,7 +562,7 @@ describe('KeylayoutToKmnConverter', function () { describe('getActionStateOutputArrayFromActionState ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sutR = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../data/tests-keylayout-kmn/Test.keylayout'); const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); [['1', [ { "id": "A_0", "state": "1", "output": "ˆ" }, @@ -609,7 +609,7 @@ describe('KeylayoutToKmnConverter', function () { describe('getActionOutputbehaviorKeyModiFromActionIDStateOutput ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sutR = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../data/tests-keylayout-kmn/Test.keylayout'); const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); const converted = sut.convertBound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); [ @@ -644,7 +644,7 @@ describe('KeylayoutToKmnConverter', function () { describe('getKeyActionOutputArrayFromActionStateOutputArray ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sutR = new KeylayoutFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../data/tests-keylayout-kmn/Test.keylayout'); const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); const b6ActionIdArr: ActionStateOutput[] = [ @@ -751,35 +751,35 @@ describe('KeylayoutToKmnConverter', function () { const sutR = new KeylayoutFileReader(compilerTestCallbacks); [ [ - ['../data/Test_C0.keylayout'], + ['../data/tests-keylayout-kmn/Test_C0.keylayout'], [new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_A', new TextEncoder().encode('a')), new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_A', new TextEncoder().encode('A')), new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_S', new TextEncoder().encode('s')), new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_D', new TextEncoder().encode('d'))] ], [ - ['../data/Test_C1.keylayout'], + ['../data/tests-keylayout-kmn/Test_C1.keylayout'], [new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_S', new TextEncoder().encode('s')), new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_S', new TextEncoder().encode('S'))] ], [ - ['../data/Test_C2.keylayout'], + ['../data/tests-keylayout-kmn/Test_C2.keylayout'], [new Rule("C2", '', '', 0, 0, 'NCAPS', 'K_U', 1, 1, 'CAPS', 'K_A', new TextEncoder().encode('Â'))], ], [ - ['../data/Test_C3.keylayout'], + ['../data/tests-keylayout-kmn/Test_C3.keylayout'], [new Rule("C3", 'NCAPS SHIFT', 'K_D', 2, 1, 'NCAPS', 'K_U', 1, 2, 'CAPS', 'K_A', new TextEncoder().encode('Â'))] ], [ - ['../data/Test_C3_several.keylayout'], + ['../data/tests-keylayout-kmn/Test_C3_several.keylayout'], [new Rule("C3", 'NCAPS RALT', 'K_8', 3, 1, 'CAPS', 'K_U', 1, 3, 'NCAPS', 'K_A', new TextEncoder().encode('â')), new Rule("C3", 'NCAPS RALT', 'K_8', 3, 0, 'CAPS', 'K_U', 1, 0, 'NCAPS RALT', 'K_A', new TextEncoder().encode('â')), new Rule("C3", 'NCAPS RALT', 'K_8', 3, 0, 'NCAPS RALT', 'K_U', 2, 2, 'NCAPS', 'K_A', new TextEncoder().encode('â')), new Rule("C3", 'NCAPS RALT', 'K_8', 3, 0, 'NCAPS RALT', 'K_U', 2, 0, 'NCAPS RALT', 'K_A', new TextEncoder().encode('â'))] ], [ - ['../data/Test_C0_C1_C2_C3.keylayout'], + ['../data/tests-keylayout-kmn/Test_C0_C1_C2_C3.keylayout'], [new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_A', new TextEncoder().encode('A')), new Rule("C2", '', '', 0, 0, 'NCAPS RALT', 'K_EQUAL', 1, 1, 'CAPS', 'K_D', new TextEncoder().encode('Â')), new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_S', new TextEncoder().encode('S')), diff --git a/developer/src/kmc-convert/test/kmn-file-reader.tests.ts b/developer/src/kmc-convert/test/kmn-file-reader.tests.ts index c68e0e52415..5b955dae9df 100644 --- a/developer/src/kmc-convert/test/kmn-file-reader.tests.ts +++ b/developer/src/kmc-convert/test/kmn-file-reader.tests.ts @@ -22,7 +22,7 @@ describe('KeylayoutFileReader', function () { const sutR = new KeylayoutFileReader(compilerTestCallbacks); it('read() should return filled array on correct input', async function () { - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../data/tests-keylayout-kmn/Test.keylayout'); const result = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); assert.isNotEmpty(result); }); @@ -38,7 +38,7 @@ describe('KeylayoutFileReader', function () { }); it('read() should return empty array on unavailable file name', async function () { - const inputFilenameUnavailable = makePathToFixture('../data/X.keylayout'); + const inputFilenameUnavailable = makePathToFixture('../data/tests-keylayout-kmn/X.keylayout'); const result = sutR.read(compilerTestCallbacks.loadFile(inputFilenameUnavailable)); assert.isNull(result); }); diff --git a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts index 3d47c8636a7..4558d7da508 100644 --- a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts +++ b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts @@ -22,7 +22,7 @@ describe('KmnFileWriter', function () { }); describe("writeDataRules() ", function () { - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../data/tests-keylayout-kmn/Test.keylayout'); const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sutR = new KeylayoutFileReader(compilerTestCallbacks); const sutW = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); @@ -40,7 +40,7 @@ describe('KmnFileWriter', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sutR = new KeylayoutFileReader(compilerTestCallbacks); const sutW = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../data/tests-keylayout-kmn/Test.keylayout'); const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); const converted = sut.convertBound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); diff --git a/developer/src/kmc-convert/test/kmnXKB-file-writer.tests.ts b/developer/src/kmc-convert/test/kmnXKB-file-writer.tests.ts index 8db24fc66e2..e3ffb2386d3 100644 --- a/developer/src/kmc-convert/test/kmnXKB-file-writer.tests.ts +++ b/developer/src/kmc-convert/test/kmnXKB-file-writer.tests.ts @@ -22,7 +22,7 @@ describe('KmnXKBFileWriter', function () { }); describe("Xkb-kmn: writeDataRules() ", function () { - const inputFilename = makePathToFixture('../data/Test.xkb'); + const inputFilename = makePathToFixture('../data/tests-xkb-kmn/Test.xkb'); const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sutR = new XkbFileReader(compilerTestCallbacks); const sutW = new KmnXKBFileWriter(compilerTestCallbacks, compilerTestOptions); @@ -40,7 +40,7 @@ describe('KmnXKBFileWriter', function () { const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sutR = new XkbFileReader(compilerTestCallbacks); const sutW = new KmnXKBFileWriter(compilerTestCallbacks, compilerTestOptions); - const inputFilename = makePathToFixture('../data/Test.xkb'); + const inputFilename = makePathToFixture('../data/tests-xkb-kmn/Test.xkb'); const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); const converted = sut.convertBound.convert(read, inputFilename.replace(/\.xkb$/, '.kmn')); @@ -422,7 +422,7 @@ describe('KmnXKBFileWriter', function () { const sutW = new KmnXKBFileWriter(compilerTestCallbacks, compilerTestOptions); [ [ - [ /* see ../data/Test_C0.xkb */ + [ /* see ../data/tests-xkb-kmn/Test_C0.xkb */ new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_A', new TextEncoder().encode('a')), new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_A', new TextEncoder().encode('A')), new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_S', new TextEncoder().encode('s')), @@ -434,7 +434,7 @@ describe('KmnXKBFileWriter', function () { "+ [NCAPS K_D] > 'd'\n"] ], [ - [ /* see ../data/Test_C1.xkb */ + [ /* see ../data/tests-xkb-kmn/Test_C1.xkb */ new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_S', new TextEncoder().encode('s')), new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_S', new TextEncoder().encode('S')) ], @@ -442,14 +442,14 @@ describe('KmnXKBFileWriter', function () { "+ [CAPS K_S] > 'S'\n"] ], [ - [ /* see ../data/Test_C2.xkb */ + [ /* see ../data/tests-xkb-kmn/Test_C2.xkb */ new Rule("C2", '', '', 0, 0, 'NCAPS', 'K_U', 1, 1, 'CAPS', 'K_A', new TextEncoder().encode('Â')) ], ["+ [NCAPS K_U] > dk(A1)\n" + "dk(A1) + [CAPS K_A] > 'Â'\n\n"] ], [ - [ /* see ../data/Test_C3.xkb */ + [ /* see ../data/tests-xkb-kmn/Test_C3.xkb */ new Rule("C3", 'NCAPS SHIFT', 'K_D', 2, 1, 'NCAPS', 'K_U', 1, 2, 'CAPS', 'K_A', new TextEncoder().encode('Â')) ], ["+ [NCAPS SHIFT K_D] > dk(A2)\n" + @@ -458,7 +458,7 @@ describe('KmnXKBFileWriter', function () { ] ], [ - [ /* see ../data/Test_C0_C1_C2_C3.xkb */ + [ /* see ../data/tests-xkb-kmn/Test_C0_C1_C2_C3.xkb */ new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_A', new TextEncoder().encode('A')), new Rule("C2", '', '', 0, 0, 'NCAPS RALT', 'K_EQUAL', 1, 1, 'CAPS', 'K_D', new TextEncoder().encode('Â')), new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_S', new TextEncoder().encode('S')), @@ -492,7 +492,7 @@ describe('KmnXKBFileWriter', function () { "dk(B5) + [CAPS K_D] > 'Â'\n\n"] ], [ - [ /* see ../data/Test_C3_several.xkb */ + [ /* see ../data/tests-xkb-kmn/Test_C3_several.xkb */ new Rule("C3", 'NCAPS RALT', 'K_8', 3, 1, 'CAPS', 'K_U', 1, 3, 'NCAPS', 'K_A', new TextEncoder().encode('â')), new Rule("C3", 'NCAPS RALT', 'K_8', 3, 0, 'CAPS', 'K_U', 1, 0, 'NCAPS RALT', 'K_A', new TextEncoder().encode('â')), new Rule("C3", 'NCAPS RALT', 'K_8', 3, 0, 'NCAPS RALT', 'K_U', 2, 2, 'NCAPS', 'K_A', new TextEncoder().encode('â')), diff --git a/developer/src/kmc-convert/test/xkb-file-reader.tests.ts b/developer/src/kmc-convert/test/xkb-file-reader.tests.ts index 0df6b4f2273..936dbc32a6a 100644 --- a/developer/src/kmc-convert/test/xkb-file-reader.tests.ts +++ b/developer/src/kmc-convert/test/xkb-file-reader.tests.ts @@ -22,7 +22,7 @@ describe('XkbFileReader', function () { const sutR = new XkbFileReader(compilerTestCallbacks); it('read() should return filled array on correct input', async function () { - const inputFilename = makePathToFixture('../data/Test.xkb'); + const inputFilename = makePathToFixture('../data/tests-xkb-kmn/Test.xkb'); const result = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); assert.isNotEmpty(result); }); @@ -38,7 +38,7 @@ describe('XkbFileReader', function () { }); it('read() should return empty array on unavailable file name', async function () { - const inputFilenameUnavailable = makePathToFixture('../data/X.xkb'); + const inputFilenameUnavailable = makePathToFixture('../data/tests-xkb-kmn/X.xkb'); const result = sutR.read(compilerTestCallbacks.loadFile(inputFilenameUnavailable)); assert.isNull(result); }); diff --git a/developer/src/kmc-convert/test/xkb-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/xkb-to-kmn-converter.tests.ts index 91a2dd1025c..ed00fc22d49 100644 --- a/developer/src/kmc-convert/test/xkb-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/xkb-to-kmn-converter.tests.ts @@ -23,29 +23,29 @@ describe('XkbToKmnConverter', function () { describe('Xkb-kmn: RunSpecialTestFiles', function () { const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); [ - [makePathToFixture('../data/Test_C0.keylayout')], - [makePathToFixture('../data/Test_C1.keylayout')], - [makePathToFixture('../data/Test_C2.keylayout')], - [makePathToFixture('../data/Test_C2_several.keylayout')], - [makePathToFixture('../data/Test_C3.keylayout')], - [makePathToFixture('../data/Test_C3_several.keylayout')], - [makePathToFixture('../data/Test_C0_C1_C2_C3.keylayout')], - [makePathToFixture('../data/Test_maxKeyCode.keylayout')], - [makePathToFixture('../data/Test_messages.keylayout')], - [makePathToFixture('../data/Test_messages_controlCharacter.keylayout')], - [makePathToFixture('../data/Test_messages_superior_C2.keylayout')], - [makePathToFixture('../data/Test_messages_superior_C3.keylayout')], - [makePathToFixture('../data/Test_duplicate_missing_keycode.keylayout')], - [makePathToFixture('../data/Test_modifier.keylayout')], - [makePathToFixture('../data/Test_modifierNoCaps.keylayout')], - [makePathToFixture('../data/Test_differentAmountOfKeysInBehaviours.keylayout')], - [makePathToFixture('../data/Test_duplicate_missing_keys.keylayout')], - [makePathToFixture('../data/Test_duplicate_keys.keylayout')], - [makePathToFixture('../data/Test_ambiguous_keys.keylayout')], - [makePathToFixture('../data/Test_nr_elements.keylayout')], - [makePathToFixture('../data/Test.keylayout')], - [makePathToFixture('../data/Test_differentEncodings.keylayout')], - [makePathToFixture('../data/Test_ExtraWarning.keylayout')], + [makePathToFixture('../data/tests-xkb-kmn/Test_C0.keylayout')], + [makePathToFixture('../data/tests-xkb-kmn/Test_C1.keylayout')], + [makePathToFixture('../data/tests-xkb-kmn/Test_C2.keylayout')], + [makePathToFixture('../data/tests-xkb-kmn/Test_C2_several.keylayout')], + [makePathToFixture('../data/tests-xkb-kmn/Test_C3.keylayout')], + [makePathToFixture('../data/tests-xkb-kmn/Test_C3_several.keylayout')], + [makePathToFixture('../data/tests-xkb-kmn/Test_C0_C1_C2_C3.keylayout')], + [makePathToFixture('../data/tests-xkb-kmn/Test_maxKeyCode.keylayout')], + [makePathToFixture('../data/tests-xkb-kmn/Test_messages.keylayout')], + [makePathToFixture('../data/tests-xkb-kmn/Test_messages_controlCharacter.keylayout')], + [makePathToFixture('../data/tests-xkb-kmn/Test_messages_superior_C2.keylayout')], + [makePathToFixture('../data/tests-xkb-kmn/Test_messages_superior_C3.keylayout')], + [makePathToFixture('../data/tests-xkb-kmn/Test_duplicate_missing_keycode.keylayout')], + [makePathToFixture('../data/tests-xkb-kmn/Test_modifier.keylayout')], + [makePathToFixture('../data/tests-xkb-kmn/Test_modifierNoCaps.keylayout')], + [makePathToFixture('../data/tests-xkb-kmn/Test_differentAmountOfKeysInBehaviours.keylayout')], + [makePathToFixture('../data/tests-xkb-kmn/Test_duplicate_missing_keys.keylayout')], + [makePathToFixture('../data/tests-xkb-kmn/Test_duplicate_keys.keylayout')], + [makePathToFixture('../data/tests-xkb-kmn/Test_ambiguous_keys.keylayout')], + [makePathToFixture('../data/tests-xkb-kmn/Test_nr_elements.keylayout')], + [makePathToFixture('../data/tests-xkb-kmn/Test.keylayout')], + [makePathToFixture('../data/tests-xkb-kmn/Test_differentEncodings.keylayout')], + [makePathToFixture('../data/tests-xkb-kmn/Test_ExtraWarning.keylayout')], ].forEach(function (files) { it(files + " should give no errors ", async function () { sut.run(files[0]); @@ -57,15 +57,15 @@ describe('XkbToKmnConverter', function () { describe('Xkb-kmn: RunTestFiles resulting in errors ', function () { const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); [ - [makePathToFixture('../data/Test_DifferentAmountOfMapSelectInKeyMapERROR.keylayout')], - [makePathToFixture('../data/Test_MissingkeyERROR.keylayout')], - [makePathToFixture('../data/Test_MissingkeyMapERROR.keylayout')], - [makePathToFixture('../data/Test_MissingLayoutsERROR.keylayout')], - [makePathToFixture('../data/Test_MissingmodifierMapERROR.keylayout')], - [makePathToFixture('../data/Test_MissingkeyMapSetERROR.keylayout')], - [makePathToFixture('../data/Test_MissingActionsERROR.keylayout')], - [makePathToFixture('../data/Test_MissingTerminatorsERROR.keylayout')], - [makePathToFixture('../data/Test_MissingAllERROR.keylayout')], + [makePathToFixture('../data/tests-xkb-kmn/Test_DifferentAmountOfMapSelectInKeyMapERROR.keylayout')], + [makePathToFixture('../data/tests-xkb-kmn/Test_MissingkeyERROR.keylayout')], + [makePathToFixture('../data/tests-xkb-kmn/Test_MissingkeyMapERROR.keylayout')], + [makePathToFixture('../data/tests-xkb-kmn/Test_MissingLayoutsERROR.keylayout')], + [makePathToFixture('../data/tests-xkb-kmn/Test_MissingmodifierMapERROR.keylayout')], + [makePathToFixture('../data/tests-xkb-kmn/Test_MissingkeyMapSetERROR.keylayout')], + [makePathToFixture('../data/tests-xkb-kmn/Test_MissingActionsERROR.keylayout')], + [makePathToFixture('../data/tests-xkb-kmn/Test_MissingTerminatorsERROR.keylayout')], + [makePathToFixture('../data/tests-xkb-kmn/Test_MissingAllERROR.keylayout')], ].forEach(function (files) { it(files + " should give an error ", async function () { sut.run(files[0]); @@ -77,7 +77,7 @@ describe('XkbToKmnConverter', function () { describe('Xkb-kmn: RunSpecialTestFiles - create Error: unsupported characters', function () { const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); [ - [makePathToFixture('../data/Test_characters.keylayout')], + [makePathToFixture('../data/tests-xkb-kmn/Test_characters.keylayout')], ].forEach(function (files) { it(files + " should give Error: unsupported characters ", async function () { sut.run(files[0]); @@ -89,7 +89,7 @@ describe('XkbToKmnConverter', function () { describe('Xkb-kmn: RunSpecialTestFiles - create Error: undefined action', function () { const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); [ - [makePathToFixture('../data/Test_undefinedAction.keylayout')], + [makePathToFixture('../data/tests-xkb-kmn/Test_undefinedAction.keylayout')], ].forEach(function (files) { it(files + " should give Error: undefined action detected", async function () { sut.run(files[0]); @@ -125,7 +125,7 @@ describe('XkbToKmnConverter', function () { }); it('run() should throw on unavailable input file name and null output file name', async function () { - const inputFilename = makePathToFixture('../data/Unavailable.keylayout'); + const inputFilename = makePathToFixture('../data/tests-xkb-kmn/Unavailable.keylayout'); const result = sut.run(inputFilename, null); assert.isNotNull(result); assert.equal(compilerTestCallbacks.messages.length, 2); @@ -137,14 +137,14 @@ describe('XkbToKmnConverter', function () { describe('Xkb-kmn: Run kmc-convert with or without outputfile name', async function () { this.timeout(5000); // allow longer time for this test const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const infile = '../data/Test.keylayout'; + const infile = '../data/tests-xkb-kmn/Test.keylayout'; [ - [makePathToFixture('../data/Test.kmn')], + [makePathToFixture('../data/tests-xkb-kmn/Test.kmn')], [makePathToFixture('')], [], [null], - [makePathToFixture('../data/test_OtherOutputName.kmn')], - [makePathToFixture('../data/OutputXName.bb')], + [makePathToFixture('../data/tests-xkb-kmn/test_OtherOutputName.kmn')], + [makePathToFixture('../data/tests-xkb-kmn/OutputXName.bb')], ].forEach(function (files) { it(infile + " should run ", async function () { await NodeAssert.doesNotReject(async () => sut.run(makePathToFixture(infile), files[0])); @@ -158,12 +158,12 @@ describe('XkbToKmnConverter', function () { const sutR = new XkbFileReader(compilerTestCallbacks); // ProcessedData from usable file - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../data/tests-xkb-kmn/Test.keylayout'); const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); const converted = sut.convertBound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); // ProcessedData from unavailable file - const inputFilenameUnavailable = makePathToFixture('../data/X.keylayout'); + const inputFilenameUnavailable = makePathToFixture('../data/tests-xkb-kmn/X.keylayout'); const readUnavailable = sutR.read(compilerTestCallbacks.loadFile(inputFilenameUnavailable)); const convertedUnavailable = sut.convertBound.convert(readUnavailable, inputFilenameUnavailable.replace(/\.keylayout$/, '.kmn')); @@ -320,7 +320,7 @@ describe('XkbToKmnConverter', function () { describe('Xkb-kmn: getModifierArrayFromKeyModifierArray ', function () { const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sutR = new XkbFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../data/tests-xkb-kmn/Test.keylayout'); const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); const converted = sut.convertBound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); [ @@ -345,7 +345,7 @@ describe('XkbToKmnConverter', function () { describe('Xkb-kmn: getKeyModifierArrayFromActionID ', function () { const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sutR = new XkbFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../data/tests-xkb-kmn/Test.keylayout'); const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); [ ['A_16', [{ "key": "32", "behavior": "5" }]], @@ -371,7 +371,7 @@ describe('XkbToKmnConverter', function () { describe('Xkb-kmn: getActionIdFromActionNext ', function () { const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sutR = new XkbFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../data/tests-xkb-kmn/Test.keylayout'); const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); [ ['none', ''], @@ -397,7 +397,7 @@ describe('XkbToKmnConverter', function () { describe('Xkb-kmn: getActionIndexFromActionId ', function () { const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sutR = new XkbFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../data/tests-xkb-kmn/Test.keylayout'); const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); [ ['none', -1], @@ -421,7 +421,7 @@ describe('XkbToKmnConverter', function () { describe('Xkb-kmn: getOutputFromActionIdNone ', function () { const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sutR = new XkbFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../data/tests-xkb-kmn/Test.keylayout'); const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); [ ['A_14', 'u'], @@ -451,7 +451,7 @@ describe('XkbToKmnConverter', function () { describe('Xkb-kmn: getKeybehaviorModOutputArrayFromKeyActionbehaviorOutputArray ', function () { const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sutR = new XkbFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../data/tests-xkb-kmn/Test.keylayout'); const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); const b1KeycodeArr: KeylayoutFileData[] = [ @@ -559,7 +559,7 @@ describe('XkbToKmnConverter', function () { describe('Xkb-kmn: getActionStateOutputArrayFromActionState ', function () { const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sutR = new XkbFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../data/tests-xkb-kmn/Test.keylayout'); const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); [['1', [ { "id": "A_0", "state": "1", "output": "ˆ" }, @@ -606,7 +606,7 @@ describe('XkbToKmnConverter', function () { describe('Xkb-kmn: getActionOutputbehaviorKeyModiFromActionIDStateOutput ', function () { const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sutR = new XkbFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../data/tests-xkb-kmn/Test.keylayout'); const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); const converted = sut.convertBound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); [ @@ -641,7 +641,7 @@ describe('XkbToKmnConverter', function () { describe('Xkb-kmn: getKeyActionOutputArrayFromActionStateOutputArray ', function () { const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sutR = new XkbFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/Test.keylayout'); + const inputFilename = makePathToFixture('../data/tests-xkb-kmn/Test.keylayout'); const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); const b6ActionIdArr: ActionStateOutput[] = [ @@ -748,35 +748,35 @@ describe('XkbToKmnConverter', function () { const sutR = new XkbFileReader(compilerTestCallbacks); [ [ - ['../data/Test_C0.keylayout'], + ['../data/tests-xkb-kmn/Test_C0.keylayout'], [new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_A', new TextEncoder().encode('a')), new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_A', new TextEncoder().encode('A')), new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_S', new TextEncoder().encode('s')), new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_D', new TextEncoder().encode('d'))] ], [ - ['../data/Test_C1.keylayout'], + ['../data/tests-xkb-kmn/Test_C1.keylayout'], [new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_S', new TextEncoder().encode('s')), new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_S', new TextEncoder().encode('S'))] ], [ - ['../data/Test_C2.keylayout'], + ['../data/tests-xkb-kmn/Test_C2.keylayout'], [new Rule("C2", '', '', 0, 0, 'NCAPS', 'K_U', 1, 1, 'CAPS', 'K_A', new TextEncoder().encode('Â'))], ], [ - ['../data/Test_C3.keylayout'], + ['../data/tests-xkb-kmn/Test_C3.keylayout'], [new Rule("C3", 'NCAPS SHIFT', 'K_D', 2, 1, 'NCAPS', 'K_U', 1, 2, 'CAPS', 'K_A', new TextEncoder().encode('Â'))] ], [ - ['../data/Test_C3_several.keylayout'], + ['../data/tests-xkb-kmn/Test_C3_several.keylayout'], [new Rule("C3", 'NCAPS RALT', 'K_8', 3, 1, 'CAPS', 'K_U', 1, 3, 'NCAPS', 'K_A', new TextEncoder().encode('â')), new Rule("C3", 'NCAPS RALT', 'K_8', 3, 0, 'CAPS', 'K_U', 1, 0, 'NCAPS RALT', 'K_A', new TextEncoder().encode('â')), new Rule("C3", 'NCAPS RALT', 'K_8', 3, 0, 'NCAPS RALT', 'K_U', 2, 2, 'NCAPS', 'K_A', new TextEncoder().encode('â')), new Rule("C3", 'NCAPS RALT', 'K_8', 3, 0, 'NCAPS RALT', 'K_U', 2, 0, 'NCAPS RALT', 'K_A', new TextEncoder().encode('â'))] ], [ - ['../data/Test_C0_C1_C2_C3.keylayout'], + ['../data/tests-xkb-kmn/Test_C0_C1_C2_C3.keylayout'], [new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_A', new TextEncoder().encode('A')), new Rule("C2", '', '', 0, 0, 'NCAPS RALT', 'K_EQUAL', 1, 1, 'CAPS', 'K_D', new TextEncoder().encode('Â')), new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_S', new TextEncoder().encode('S')), From 98f2332db80e1c24cd47779244faa3c5f7e9d715 Mon Sep 17 00:00:00 2001 From: Sabine Date: Thu, 7 May 2026 09:22:48 +0200 Subject: [PATCH 241/251] feat(developer): move keylayout-kmn source files to seperate folders for each conversion --- developer/src/kmc-convert/src/converter-class-factory.ts | 2 +- .../keylayout-to-kmn-converter.ts | 5 +++-- .../keylayout-file-reader.ts | 0 .../kmn-file-writer.ts | 2 +- .../kmc-convert/test/keylayout-to-kmn-converter.tests.ts | 4 ++-- developer/src/kmc-convert/test/kmn-file-reader.tests.ts | 2 +- developer/src/kmc-convert/test/kmn-file-writer.tests.ts | 6 +++--- 7 files changed, 11 insertions(+), 10 deletions(-) rename developer/src/kmc-convert/src/{keylayout-to-kmn => kmc-convert-convert}/keylayout-to-kmn-converter.ts (99%) rename developer/src/kmc-convert/src/{keylayout-to-kmn => kmc-convert-read}/keylayout-file-reader.ts (100%) rename developer/src/kmc-convert/src/{keylayout-to-kmn => kmc-convert-write}/kmn-file-writer.ts (99%) diff --git a/developer/src/kmc-convert/src/converter-class-factory.ts b/developer/src/kmc-convert/src/converter-class-factory.ts index 549513e3ecd..fd224919c29 100644 --- a/developer/src/kmc-convert/src/converter-class-factory.ts +++ b/developer/src/kmc-convert/src/converter-class-factory.ts @@ -3,7 +3,7 @@ * * Lists all the available converters and finds matching converter */ -import { KeylayoutToKmnConverter } from './keylayout-to-kmn/keylayout-to-kmn-converter.js'; +import { KeylayoutToKmnConverter } from './kmc-convert-convert/keylayout-to-kmn-converter.js'; import { XkbToKmnConverter } from './xkb-to-kmn/xkb-to-kmn-converter.js'; const converters = [ diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/kmc-convert-convert/keylayout-to-kmn-converter.ts similarity index 99% rename from developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts rename to developer/src/kmc-convert/src/kmc-convert-convert/keylayout-to-kmn-converter.ts index fec3a1f19d5..b65cdbadb8a 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/kmc-convert-convert/keylayout-to-kmn-converter.ts @@ -9,8 +9,9 @@ // ToDo-kmc-convert all warnings/squiggely lines will be adressed in PR #15860 import { CompilerCallbacks, CompilerOptions, KeymanCompilerResult, Keylayout } from "@keymanapp/developer-utils"; -import { KmnFileWriter } from './kmn-file-writer.js'; -import { KeylayoutFileReader } from './keylayout-file-reader.js'; + +import { KmnFileWriter } from './../kmc-convert-write/kmn-file-writer.js'; +import { KeylayoutFileReader } from './../kmc-convert-read/keylayout-file-reader.js'; import { ConverterMessages } from '../converter-messages.js'; import { ConverterArtifacts, ConverterToKmnArtifacts } from "../converter-artifacts.js"; diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts b/developer/src/kmc-convert/src/kmc-convert-read/keylayout-file-reader.ts similarity index 100% rename from developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts rename to developer/src/kmc-convert/src/kmc-convert-read/keylayout-file-reader.ts diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts b/developer/src/kmc-convert/src/kmc-convert-write/kmn-file-writer.ts similarity index 99% rename from developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts rename to developer/src/kmc-convert/src/kmc-convert-write/kmn-file-writer.ts index 081885296b1..2f3405c3853 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts +++ b/developer/src/kmc-convert/src/kmc-convert-write/kmn-file-writer.ts @@ -8,7 +8,7 @@ */ import { CompilerCallbacks, CompilerOptions } from "@keymanapp/developer-utils"; -import { KeylayoutToKmnConverter, ProcessedData, Rule } from './keylayout-to-kmn-converter.js'; +import { KeylayoutToKmnConverter, ProcessedData, Rule } from './../kmc-convert-convert/keylayout-to-kmn-converter.js'; import { ConverterMessages } from '../converter-messages.js'; import KEYMAN_VERSION from "@keymanapp/keyman-version"; diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts index f8e7173bc02..808468a58cd 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts @@ -10,8 +10,8 @@ import 'mocha'; import { assert } from 'chai'; import * as NodeAssert from 'node:assert'; import { compilerTestCallbacks, compilerTestOptions, makePathToFixture } from './helpers/index.js'; -import { ActionStateOutput, KeylayoutFileData, KeylayoutToKmnConverter, Rule } from '../src/keylayout-to-kmn/keylayout-to-kmn-converter.js'; -import { KeylayoutFileReader } from '../src/keylayout-to-kmn/keylayout-file-reader.js'; +import { ActionStateOutput, KeylayoutFileData, KeylayoutToKmnConverter, Rule } from '../src/kmc-convert-convert/keylayout-to-kmn-converter.js'; +import { KeylayoutFileReader } from '../src//kmc-convert-read/keylayout-file-reader.js'; import { ConverterMessages } from '../src/converter-messages.js'; describe('KeylayoutToKmnConverter', function () { diff --git a/developer/src/kmc-convert/test/kmn-file-reader.tests.ts b/developer/src/kmc-convert/test/kmn-file-reader.tests.ts index 5b955dae9df..419de530864 100644 --- a/developer/src/kmc-convert/test/kmn-file-reader.tests.ts +++ b/developer/src/kmc-convert/test/kmn-file-reader.tests.ts @@ -10,7 +10,7 @@ import 'mocha'; import { assert } from 'chai'; import { compilerTestCallbacks, makePathToFixture } from './helpers/index.js'; -import { KeylayoutFileReader } from '../src/keylayout-to-kmn/keylayout-file-reader.js'; +import { KeylayoutFileReader } from '../src//kmc-convert-read/keylayout-file-reader.js'; describe('KeylayoutFileReader', function () { diff --git a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts index 4558d7da508..8230b319895 100644 --- a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts +++ b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts @@ -11,9 +11,9 @@ import 'mocha'; import { assert } from 'chai'; import KEYMAN_VERSION from "@keymanapp/keyman-version"; import { compilerTestCallbacks, compilerTestOptions, makePathToFixture } from './helpers/index.js'; -import { KeylayoutToKmnConverter, ProcessedData, Rule } from '../src/keylayout-to-kmn/keylayout-to-kmn-converter.js'; -import { KmnFileWriter } from '../src/keylayout-to-kmn/kmn-file-writer.js'; -import { KeylayoutFileReader } from '../src/keylayout-to-kmn/keylayout-file-reader.js'; +import { KeylayoutToKmnConverter, ProcessedData, Rule } from '../src//kmc-convert-convert/keylayout-to-kmn-converter.js'; +import { KmnFileWriter } from '../src//kmc-convert-write/kmn-file-writer.js'; +import { KeylayoutFileReader } from '../src//kmc-convert-read/keylayout-file-reader.js'; describe('KmnFileWriter', function () { From ee75171794b5c17d3fc6f6b333bdac5da8b1db41 Mon Sep 17 00:00:00 2001 From: Sabine Date: Thu, 7 May 2026 09:51:06 +0200 Subject: [PATCH 242/251] feat(developer): move xkb-kmn source files to seperate folder --- .../src/converter-class-factory.ts | 2 +- .../xkb-to-kmn-converter.ts | 6 +- .../xkb-file-reader.ts | 0 .../src/xkb-to-kmn/kmnXKB-file-writer.ts | 1077 ----------------- .../test/kmnXKB-file-writer.tests.ts | 524 -------- .../kmc-convert/test/xkb-file-reader.tests.ts | 2 +- .../test/xkb-to-kmn-converter.tests.ts | 4 +- 7 files changed, 7 insertions(+), 1608 deletions(-) rename developer/src/kmc-convert/src/{xkb-to-kmn => kmc-convert-convert}/xkb-to-kmn-converter.ts (99%) rename developer/src/kmc-convert/src/{xkb-to-kmn => kmc-convert-read}/xkb-file-reader.ts (100%) delete mode 100644 developer/src/kmc-convert/src/xkb-to-kmn/kmnXKB-file-writer.ts delete mode 100644 developer/src/kmc-convert/test/kmnXKB-file-writer.tests.ts diff --git a/developer/src/kmc-convert/src/converter-class-factory.ts b/developer/src/kmc-convert/src/converter-class-factory.ts index fd224919c29..84981eb47b4 100644 --- a/developer/src/kmc-convert/src/converter-class-factory.ts +++ b/developer/src/kmc-convert/src/converter-class-factory.ts @@ -4,7 +4,7 @@ * Lists all the available converters and finds matching converter */ import { KeylayoutToKmnConverter } from './kmc-convert-convert/keylayout-to-kmn-converter.js'; -import { XkbToKmnConverter } from './xkb-to-kmn/xkb-to-kmn-converter.js'; +import { XkbToKmnConverter } from './kmc-convert-convert/xkb-to-kmn-converter.js'; const converters = [ KeylayoutToKmnConverter, diff --git a/developer/src/kmc-convert/src/xkb-to-kmn/xkb-to-kmn-converter.ts b/developer/src/kmc-convert/src/kmc-convert-convert/xkb-to-kmn-converter.ts similarity index 99% rename from developer/src/kmc-convert/src/xkb-to-kmn/xkb-to-kmn-converter.ts rename to developer/src/kmc-convert/src/kmc-convert-convert/xkb-to-kmn-converter.ts index 416bb884a92..015d4027c5b 100644 --- a/developer/src/kmc-convert/src/xkb-to-kmn/xkb-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/kmc-convert-convert/xkb-to-kmn-converter.ts @@ -8,8 +8,8 @@ */ import { CompilerCallbacks, CompilerOptions, KeymanCompilerResult, Keylayout } from "@keymanapp/developer-utils"; -import { KmnXKBFileWriter } from './kmnXKB-file-writer.js'; -import { XkbFileReader } from './xkb-file-reader.js'; +import { KmnFileWriter } from './../kmc-convert-write/kmn-file-writer.js'; +import { XkbFileReader } from './../kmc-convert-read/xkb-file-reader.js'; import { ConverterMessages } from '../converter-messages.js'; import { ConverterArtifacts, ConverterToKmnArtifacts } from "../converter-artifacts.js"; @@ -134,7 +134,7 @@ export class XkbToKmnConverter { } const processedData = await this.convert(jsonO, inputFilename, outputFilename); - const kmnFileWriter = new KmnXKBFileWriter(this.callbacks, this.options); + const kmnFileWriter = new KmnFileWriter(this.callbacks, this.options); // write to object/ConverterToKmnResult const outputKmn = kmnFileWriter.write(processedData); diff --git a/developer/src/kmc-convert/src/xkb-to-kmn/xkb-file-reader.ts b/developer/src/kmc-convert/src/kmc-convert-read/xkb-file-reader.ts similarity index 100% rename from developer/src/kmc-convert/src/xkb-to-kmn/xkb-file-reader.ts rename to developer/src/kmc-convert/src/kmc-convert-read/xkb-file-reader.ts diff --git a/developer/src/kmc-convert/src/xkb-to-kmn/kmnXKB-file-writer.ts b/developer/src/kmc-convert/src/xkb-to-kmn/kmnXKB-file-writer.ts deleted file mode 100644 index a35202b7de1..00000000000 --- a/developer/src/kmc-convert/src/xkb-to-kmn/kmnXKB-file-writer.ts +++ /dev/null @@ -1,1077 +0,0 @@ -/* - * Keyman is copyright (C) SIL Global. MIT License. - * - * Created by S. Schmitt on 2025-05-12 - * - * Write Keyman .kmn files from an in-memory representation generated - * - */ - -import { CompilerCallbacks, CompilerOptions } from "@keymanapp/developer-utils"; -import { XkbToKmnConverter, ProcessedData, Rule } from './xkb-to-kmn-converter.js'; -import { ConverterMessages } from '../converter-messages.js'; -import KEYMAN_VERSION from "@keymanapp/keyman-version"; - -export interface messageCharacter { - message: string; - character: string; -}; - -export class KmnXKBFileWriter { - - constructor(private callbacks: CompilerCallbacks, private options: CompilerOptions) { }; - - /** - * @brief member function to write data from object to a Uint8Array - * @param dataUkelele the array holding all keyboard data - * @return a Uint8Array holding data - */ - public write(dataUkelele: ProcessedData): Uint8Array { - let data: string = "\n"; - - // top part of kmn file: STORES - const dataStores = this.writeKmnFileHeader(dataUkelele); - - // bottom part of kmn file: RULES - const dataRules = this.writeDataRules(dataUkelele); - - if (dataRules) - data += dataStores + dataRules; - - try { - return new TextEncoder().encode(data); - } catch (err) { - this.callbacks.reportMessage(ConverterMessages.Error_UnableToWrite({ outputFilename: dataUkelele.kmnFilename, errorText: err })); - return null; - } - } - - /** - * @brief member function to create data for the header (stores) that will be printed to the resulting kmn file - * @param dataUkelele an object containing all data read from a .keylayout file - * @return string - all stores to be printed - */ - public writeKmnFileHeader(dataUkelele: ProcessedData): string { - - let data: string = ""; - - data += "c ..................................................................................................................\n"; - data += "c ..................................................................................................................\n"; - data += "c Keyman keyboard generated by kmn-convert version: " + KEYMAN_VERSION.VERSION + "\n"; - data += "c from Ukelele file: " + dataUkelele.keylayoutFilename + "\n"; - data += "c ..................................................................................................................\n"; - data += "c ..................................................................................................................\n"; - data += "\n"; - - data += "store(&TARGETS) \'desktop\'\n"; - - data += "\n"; - data += "begin Unicode > use(main)\n\n"; - data += "group(main) using keys\n\n"; - - data += "\n"; - return data; - } - - /** - * @brief member function to create data from rules that will be printed to the resulting kmn file - * @param dataUkelele an object containing all data read from a .keylayout file - * @return string - all rules to be printed - */ - public writeDataRules(dataUkelele: ProcessedData): string { - - const keylayoutKmnConverter = new XkbToKmnConverter(this.callbacks, this.options); - let data: string = ""; - - // filter array of all rules and remove duplicates - // during the process of creating Rule[], duplicate rules might occur - // (e.g. when in a keylayout file the same modifiers occur in several behaviors thus producing the same rules). - // This is to filter out those duplicate Rule objects - const uniqueDataRules: Rule[] = dataUkelele.rules.filter((curr) => { - return (!(curr.output.length === 0 || curr.output === undefined) - && (curr.key !== "") - && ((curr.ruleType === "C0") - || (curr.ruleType === "C1") - || (curr.ruleType === "C2" && (curr.deadkey !== "")) - || (curr.ruleType === "C3" && (curr.deadkey !== "") && (curr.prevDeadkey !== ""))) - ); - }).reduce((unique, o) => { - if (!unique.some((obj: Rule) => - new TextDecoder().decode(obj.output) === new TextDecoder().decode(o.output) - - && obj.ruleType === o.ruleType - && obj.modifierKey === o.modifierKey - && obj.key === o.key - - && obj.modifierDeadkey === o.modifierDeadkey - && obj.deadkey === o.deadkey - - && obj.modifierPrevDeadkey === o.modifierPrevDeadkey - && obj.prevDeadkey === o.prevDeadkey) - ) { - unique.push(o); - } - return unique; - }, []); - - //................................................ C0 C1 ................................................................ - - for (let k = 0; k < uniqueDataRules.length; k++) { - - if ((uniqueDataRules[k].ruleType === "C0") || (uniqueDataRules[k].ruleType === "C1")) { - - // lookup key nr of the key which is being processed - let keyNr: number = 0; - for (let j = 0; j <= XkbToKmnConverter.MAX_KEY_IDENTIFIER; j++) { - if (keylayoutKmnConverter.mapUkeleleKeycodeToVK(j) === uniqueDataRules[k].key) { - keyNr = j; - break; - } - } - - // skip keyNr 48 (K_TAB) and 36 (K_ENTER) - if ((keyNr === 48) || (keyNr === 36)) { - continue; - } - - // add a line after rules of each key - if ((k > 1) && (uniqueDataRules[k - 1].key !== uniqueDataRules[k].key) && (uniqueDataRules[k - 1].ruleType === uniqueDataRules[k].ruleType)) { - data += '\n'; - } - - // use of Unicode Character vs Unicode Codepoint; - // If it`s a ctrl character we print out the Unicode Codepoint else we print out the Unicode Character - let versionOutputCharacter; - const warnText = this.reviewRules(uniqueDataRules, k); - - const outputCharacter = new TextDecoder().decode(uniqueDataRules[k].output); - // TODO-kmc-convert: after merge of PR 14564 use functions from util instead of the ones in this class - // const outputUnicodeCharacter = util.convertToUnicodeCharacter(outputCharacter); - // const outputUnicodeCodePoint = util.convertToUnicodeCodePoint(outputCharacter); - - if ((outputCharacter !== undefined) || (outputCharacter !== "")) { - const characterMessage = this.writeCharacterOrUnicode(outputCharacter, warnText[2]); - versionOutputCharacter = characterMessage.character; - warnText[2] = characterMessage.message; - } - - // add a warning in front of rules in case unavailable modifiers or ambiguous rules are used - // if warning contains duplicate rules we do not write out the entire rule - // (even if there are other warnings for the same rule) since that rule had been written before - if (warnText[2].indexOf("duplicate") < 0) { - - let warningTextToWrite = ""; - if (!XkbToKmnConverter.SKIP_COMMENTED_LINES && (warnText[2].length > 0)) { - warningTextToWrite = warnText[2]; - } - - if (!((warnText[2].length > 0) && XkbToKmnConverter.SKIP_COMMENTED_LINES)) { - if (versionOutputCharacter === "'") { - data += warningTextToWrite - + "+ [" - + (uniqueDataRules[k].modifierKey + ' ' + uniqueDataRules[k].key).trim() - + `] > \"` - + versionOutputCharacter - + '\"\n'; - } - else { - data += warningTextToWrite - + "+ [" - + (uniqueDataRules[k].modifierKey + ' ' + uniqueDataRules[k].key).trim() - + `] > \'` - + versionOutputCharacter - + '\'\n'; - } - } - } - } - } - - //................................................ C2 ................................................................... - for (let k = 0; k < uniqueDataRules.length; k++) { - - if (uniqueDataRules[k].ruleType === "C2") { - - // use of Unicode Character vs Unicode Codepoint; - // If it`s a ctrl character we print out the Unicode Codepoint else we print out the Unicode Character - let versionOutputCharacter; - const warnText = this.reviewRules(uniqueDataRules, k); - - const outputCharacter = new TextDecoder().decode(uniqueDataRules[k].output); - // TODO-kmc-convert: after merge of PR 14564 use functions from util instead of the ones in this class - // const outputUnicodeCharacter = util.convertToUnicodeCharacter(outputCharacter); - // const outputUnicodeCodePoint = util.convertToUnicodeCodePoint(outputCharacter); - - if ((outputCharacter !== undefined) || (outputCharacter !== "")) { - const characterMessage = this.writeCharacterOrUnicode(outputCharacter, warnText[2]); - versionOutputCharacter = characterMessage.character; - warnText[2] = characterMessage.message; - } - - // add a warning in front of rules in case unavailable modifiers or ambiguous rules are used - // if warning contains duplicate rules we do not write out the entire rule - // (even if there are other warnings for the same rule) since that rule had been written before - if (warnText[1].indexOf("duplicate") < 0) { - - let warningTextToWrite = ""; - if (!XkbToKmnConverter.SKIP_COMMENTED_LINES && (warnText[1].length > 0)) { - warningTextToWrite = warnText[1]; - } - - if (!((warnText[1].length > 0) && XkbToKmnConverter.SKIP_COMMENTED_LINES)) { - data += warningTextToWrite - + "+ [" + (uniqueDataRules[k].modifierDeadkey + " " - + uniqueDataRules[k].deadkey).trim() - + "] > dk(A" + String(uniqueDataRules[k].idDeadkey) - + ")\n"; - } - } - - if ((warnText[2].indexOf("duplicate") < 0)) { - - let warningTextToWrite = ""; - if (!XkbToKmnConverter.SKIP_COMMENTED_LINES && (warnText[2].length > 0)) { - warningTextToWrite = warnText[2]; - } - - if (!((warnText[2].length > 0) && XkbToKmnConverter.SKIP_COMMENTED_LINES)) { - if (versionOutputCharacter === "'") { - data += warningTextToWrite - + "dk(A" - + (String(uniqueDataRules[k].idDeadkey) + ") + [" - + uniqueDataRules[k].modifierKey).trim() - + " " - + uniqueDataRules[k].key + '] > \"' - + versionOutputCharacter - + '\"\n'; - } - else { - data += warningTextToWrite - + "dk(A" - + (String(uniqueDataRules[k].idDeadkey) + ") + [" - + uniqueDataRules[k].modifierKey).trim() - + " " - + uniqueDataRules[k].key + "] > \'" - + versionOutputCharacter - + "\'\n"; - } - - - } - data += "\n"; - } - } - } - - //................................................ C3 ................................................................... - - for (let k = 0; k < uniqueDataRules.length; k++) { - if (uniqueDataRules[k].ruleType === "C3") { - - // use of Unicode Character vs Unicode Codepoint; - // If it`s a ctrl character we print out the Unicode Codepoint else we print out the Unicode Character - let versionOutputCharacter; - - const warnText = this.reviewRules(uniqueDataRules, k); - const outputCharacter = new TextDecoder().decode(uniqueDataRules[k].output); - // TODO-kmc-convert: after merge of PR 14564 use functions from util instead of the ones in this class - - if ((outputCharacter !== undefined) || (outputCharacter !== "")) { - const characterMessage = this.writeCharacterOrUnicode(outputCharacter, warnText[2]); - versionOutputCharacter = characterMessage.character; - warnText[2] = characterMessage.message; - } - - // add a warning in front of rules in case unavailable modifiers or ambiguous rules are used - // if warning contains duplicate rules we do not write out the entire rule - // (even if there are other warnings for the same rule) since that rule had been written before - if (warnText[0].indexOf("duplicate") < 0) { - - let warningTextToWrite = ""; - - if (!XkbToKmnConverter.SKIP_COMMENTED_LINES && (warnText[0].length > 0)) { - warningTextToWrite = warnText[0]; - } - - if (!((warnText[0].length > 0) && XkbToKmnConverter.SKIP_COMMENTED_LINES)) { - data += warningTextToWrite - + "+ [" - + (uniqueDataRules[k].modifierPrevDeadkey + " " - + uniqueDataRules[k].prevDeadkey).trim() - + "] > dk(A" - + String(uniqueDataRules[k].idPrevDeadkey) + ")\n"; - } - } - - if (warnText[1].indexOf("duplicate") < 0) { - - let warningTextToWrite = ""; - if (!XkbToKmnConverter.SKIP_COMMENTED_LINES && (warnText[1].length > 0)) { - warningTextToWrite = warnText[1]; - } - - if (!((warnText[1].length > 0) && XkbToKmnConverter.SKIP_COMMENTED_LINES)) { - data += warningTextToWrite - + "dk(A" + (String(uniqueDataRules[k].idPrevDeadkey) + ") + [" - + uniqueDataRules[k].modifierDeadkey).trim() - + " " - + uniqueDataRules[k].deadkey - + "] > dk(B" - + String(uniqueDataRules[k].idDeadkey) - + ")\n"; - } - } - - if (warnText[2].indexOf("duplicate") < 0) { - - let warningTextToWrite = ""; - if (!XkbToKmnConverter.SKIP_COMMENTED_LINES && (warnText[2].length > 0)) { - warningTextToWrite = warnText[2]; - } - - if (!((warnText[2].length > 0) && XkbToKmnConverter.SKIP_COMMENTED_LINES)) { - data += warningTextToWrite + "dk(B" - + (String(uniqueDataRules[k].idDeadkey) - + ") + [" - + uniqueDataRules[k].modifierKey).trim() - + " " - + uniqueDataRules[k].key - + "] > \'" - + versionOutputCharacter - + "\'\n"; - } - } - - if ((warnText[0].indexOf("duplicate") < 0) || (warnText[1].indexOf("duplicate") < 0) || (warnText[2].indexOf("duplicate") < 0)) { - data += "\n"; - } - } - } - return data; - } - - /** - * @brief member function to review rules for acceptable modifiers, duplicate or ambiguous rules and return an array containing possible warnings. - * Keyman can not handle duplicate rules so we need to make sure a rule is written only once by either omitting a duplicate rule or commenting out an ambiguous rule. - * Omitting rules and definition of comparisons e.g. 1-1, 2-4, 6-6 - * see https://docs.google.com/document/d/12J3NGO6RxIthCpZDTR8FYSRjiMgXJDLwPY2z9xqKzJ0/edit?tab=t.0#heading=h.pcz8rjyrl5ug - * @param rule : Rule[] - an array of all rules - * @param index the index of a rule in Rule[] - * @return a string[] containing possible warnings for a rule - */ - public reviewRules(rule: Rule[], index: number): string[] { - - const keylayoutKmnConverter = new XkbToKmnConverter(this.callbacks, this.options); - const warningText: string[] = Array(3).fill(""); - - // ------------------------- check unavailable modifiers ------------------------- - - if ((rule[index].ruleType === "C0") || (rule[index].ruleType === "C1")) { - if (!keylayoutKmnConverter.isAcceptableKeymanModifier(rule[index].modifierKey)) { - warningText[2] = "unavailable modifier : "; - } - } - - else if (rule[index].ruleType === "C2") { - if (!keylayoutKmnConverter.isAcceptableKeymanModifier(rule[index].modifierDeadkey)) { - warningText[1] = "unavailable modifier : "; - warningText[2] = "unavailable superior rule ( [" - + rule[index].modifierDeadkey + " " - + rule[index].deadkey - + "] > dk(A" - + rule[index].idDeadkey - + ") ) : "; - } - if (!keylayoutKmnConverter.isAcceptableKeymanModifier(rule[index].modifierKey)) { - warningText[2] = "unavailable modifier : "; - } - } - - else if (rule[index].ruleType === "C3") { - - if (!keylayoutKmnConverter.isAcceptableKeymanModifier(rule[index].modifierPrevDeadkey)) { - warningText[0] = "unavailable modifier : "; - warningText[1] = "unavailable superior rule ( [" - + rule[index].modifierPrevDeadkey + " " - + rule[index].prevDeadkey - + "] > dk(A" - + rule[index].idPrevDeadkey - + ") ) : "; - } - - if (!keylayoutKmnConverter.isAcceptableKeymanModifier(rule[index].modifierDeadkey)) { - warningText[1] = "unavailable modifier : "; - warningText[2] = "unavailable superior rule ( [" - + rule[index].modifierDeadkey + " " - + rule[index].deadkey - + "] > dk(B" - + rule[index].idDeadkey - + ") ) : "; - } - - if (!keylayoutKmnConverter.isAcceptableKeymanModifier(rule[index].modifierKey)) { - warningText[2] = "unavailable modifier : "; - } - } - - // ------------------------- check ambiguous/duplicate rules ------------------------- - - if ((rule[index].ruleType === "C0") || (rule[index].ruleType === "C1")) { - - // 1-1: + [CAPS K_N] > 'N' <-> + [CAPS K_N] > 'A' - const amb_1_1 = rule.filter((curr, idx) => - (curr.ruleType === "C0" || curr.ruleType === "C1") - && curr.modifierPrevDeadkey === "" - && curr.prevDeadkey === "" - && curr.modifierDeadkey === "" - && curr.deadkey === "" - && curr.modifierKey === rule[index].modifierKey - && curr.key === rule[index].key - && new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output) - && idx < index - ); - // 1-1: + [CAPS K_N] > 'N' <-> + [CAPS K_N] > 'N' - const dup_1_1 = rule.filter((curr, idx) => - (curr.ruleType === "C0" || curr.ruleType === "C1") - && curr.modifierPrevDeadkey === "" - && curr.prevDeadkey === "" - && curr.modifierDeadkey === "" - && curr.deadkey === "" - && curr.modifierKey === rule[index].modifierKey - && curr.key === rule[index].key - && new TextDecoder().decode(curr.output) === new TextDecoder().decode(rule[index].output) - && idx < index - ); - - // 4-1: + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > 'Ñ' - const amb_4_1 = rule.filter((curr, idx) => - ((curr.ruleType === "C3")) - && curr.modifierPrevDeadkey === rule[index].modifierKey - && curr.prevDeadkey === rule[index].key - ); - - // 2-1: + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > 'Ñ' - const amb_2_1 = rule.filter((curr, idx) => - ((curr.ruleType === "C2")) - && curr.modifierDeadkey === rule[index].modifierKey - && curr.deadkey === rule[index].key - ); - - if (amb_4_1.length > 0) { - warningText[2] = warningText[2] - + ("ambiguous rule: later: [" - + amb_4_1[0].modifierPrevDeadkey - + " " - + amb_4_1[0].prevDeadkey - + "] > dk(C" - + amb_2_1[0].idDeadkey - + ") "); - } - - if (amb_2_1.length > 0) { - warningText[2] = warningText[2] - + ("ambiguous rule: later: [" - + amb_2_1[0].modifierDeadkey - + " " - + amb_2_1[0].deadkey - + "] > dk(A" - + amb_2_1[0].idDeadkey - + ") "); - } - - if (amb_1_1.length > 0) { - warningText[2] = warningText[2] - + ("ambiguous rule: earlier: [" - + amb_1_1[0].modifierKey - + " " - + amb_1_1[0].key - + "] > \'" - + this.writeCharacterOrUnicode(new TextDecoder().decode(amb_1_1[0].output)).character - + "\' "); - } - - if (dup_1_1.length > 0) { - warningText[2] = warningText[2] - + ("duplicate rule: earlier: [" - + dup_1_1[0].modifierKey - + " " - + dup_1_1[0].key - + "] > \'" - + this.writeCharacterOrUnicode(new TextDecoder().decode(dup_1_1[0].output)).character - + "\' "); - } - } - - if (rule[index].ruleType === "C2") { - - // 2-2: + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(C3) - const amb_2_2 = rule.filter((curr, idx) => - curr.ruleType === "C2" - && curr.modifierDeadkey === rule[index].modifierDeadkey - && curr.deadkey === rule[index].deadkey - && curr.idDeadkey !== rule[index].idDeadkey - && idx < index - ); - - // 2-2: + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(C11) - const dup_2_2 = rule.filter((curr, idx) => - curr.ruleType === "C2" - && curr.modifierDeadkey === rule[index].modifierDeadkey - && curr.deadkey === rule[index].deadkey - && curr.idDeadkey === rule[index].idDeadkey - && idx < index - ); - - //3-3: dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'B' - const amb_3_3 = rule.filter((curr, idx) => - (curr.ruleType === "C2") - && curr.idDeadkey === rule[index].idDeadkey - && curr.modifierKey === rule[index].modifierKey - && curr.key === rule[index].key - && new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output) - && idx < index - ); - - //3-3: dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'Ã' - const dup_3_3 = rule.filter((curr, idx) => - (curr.ruleType === "C2") - && curr.idDeadkey === rule[index].idDeadkey - && rule[index].uniqueDeadkey === 0 - && curr.modifierKey === rule[index].modifierKey - && curr.key === rule[index].key - && new TextDecoder().decode(curr.output) === new TextDecoder().decode(rule[index].output) - && idx < index - ); - - // 4-2: + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(B11) - const amb_4_2 = rule.filter((curr, idx) => - ((curr.ruleType === "C3")) - && curr.modifierPrevDeadkey === rule[index].modifierDeadkey - && curr.prevDeadkey === rule[index].deadkey - && curr.idPrevDeadkey === rule[index].idDeadkey - ); - - if (amb_2_2.length > 0) { - warningText[1] = warningText[1] - + ("ambiguous rule: earlier: [" - + amb_2_2[0].modifierDeadkey - + " " - + amb_2_2[0].deadkey - + "] > dk(C" - + amb_2_2[0].idDeadkey - + ") "); - } - - if (dup_2_2.length > 0) { - warningText[1] = warningText[1] - + ("duplicate rule: earlier: [" - + dup_2_2[0].modifierDeadkey - + " " - + dup_2_2[0].deadkey - + "] > dk(C" - + dup_2_2[0].idDeadkey - + ") "); - } - - if (amb_3_3.length > 0) { - warningText[2] = warningText[2] - + ("ambiguous rule: earlier: dk(A" - + amb_3_3[0].idDeadkey - + ") + [" - + amb_3_3[0].modifierKey - + " " - + amb_3_3[0].key - + "] > \'" - + this.writeCharacterOrUnicode(new TextDecoder().decode(amb_3_3[0].output)).character - + "\' "); - } - - if (dup_3_3.length > 0) { - warningText[2] = warningText[2] - + ("duplicate rule: earlier: dk(A" - + dup_3_3[0].idDeadkey - + ") + [" - + dup_3_3[0].modifierKey - + " " - + dup_3_3[0].key - + "] > \'" - + this.writeCharacterOrUnicode(new TextDecoder().decode(dup_3_3[0].output)).character - + "\' "); - } - - if (amb_4_2.length > 0) { - warningText[0] = warningText[0] - + ("ambiguous rule: later: [" - + amb_4_2[0].modifierPrevDeadkey - + " " - + amb_4_2[0].prevDeadkey - + "] > dk(C" - + amb_4_2[0].idPrevDeadkey - + ") "); - } - } - - if (rule[index].ruleType === "C3") { - - // 2-4 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(B11) - const amb_2_4 = rule.filter((curr, idx) => - ((curr.ruleType === "C2")) - && curr.modifierDeadkey === rule[index].modifierPrevDeadkey - && curr.deadkey === rule[index].prevDeadkey - && curr.idDeadkey === rule[index].idPrevDeadkey - ); - - // 6-3 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'B' - const amb_6_3 = rule.filter((curr, idx) => - (curr.ruleType === "C2") - && curr.idPrevDeadkey === rule[index].idPrevDeadkey - && curr.modifierKey === rule[index].modifierKey - && curr.key === rule[index].key - && (new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output)) - ); - - // 6-3 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'Ã' - const dup_6_3 = rule.filter((curr, idx) => - (curr.ruleType === "C2") - && curr.idPrevDeadkey === rule[index].idPrevDeadkey - && curr.modifierKey === rule[index].modifierKey - && curr.key === rule[index].key - && new TextDecoder().decode(curr.output) === new TextDecoder().decode(rule[index].output) - ); - - // 4-4 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(C1) - const amb_4_4 = rule.filter((curr, idx) => - curr.ruleType === "C3" - && curr.modifierPrevDeadkey === rule[index].modifierPrevDeadkey - && curr.idPrevDeadkey !== rule[index].idPrevDeadkey - && curr.prevDeadkey === rule[index].prevDeadkey - && rule[index].uniquePrevDeadkey !== 0 - && idx < index - ); - - // 4-4 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(C11) - const dup_4_4 = rule.filter((curr, idx) => - curr.ruleType === "C3" - && curr.modifierPrevDeadkey === rule[index].modifierPrevDeadkey - && curr.prevDeadkey === rule[index].prevDeadkey - && curr.idPrevDeadkey === rule[index].idPrevDeadkey - && idx < index - ); - - // 5-5 dk(C1) + [SHIFT CAPS K_A] > dk(C2) <-> dk(C1) + [SHIFT CAPS K_A] > dk(C3) - const amb_5_5 = rule.filter((curr, idx) => ( - (curr.ruleType === "C3") - && curr.idPrevDeadkey === rule[index].idPrevDeadkey - && curr.modifierDeadkey === rule[index].modifierDeadkey - && curr.deadkey === rule[index].deadkey - && curr.idDeadkey === rule[index].idDeadkey) - && idx < index - && (rule[index].uniqueDeadkey !== 0 || rule[index].uniquePrevDeadkey !== 0) - ); - - // 5-5 dk(C1) + [SHIFT CAPS K_A] > dk(C2) <-> dk(C1) + [SHIFT CAPS K_A] > dk(C2) - const dup_5_5 = rule.filter((curr, idx) => - (curr.ruleType === "C3") - && curr.idPrevDeadkey === rule[index].idPrevDeadkey - && curr.modifierPrevDeadkey === rule[index].modifierPrevDeadkey - && curr.prevDeadkey === rule[index].prevDeadkey - && curr.modifierDeadkey === rule[index].modifierDeadkey - && curr.deadkey === rule[index].deadkey - && curr.idDeadkey === rule[index].idDeadkey - && rule[index].uniqueDeadkey === 0 - && idx < index - ); - - // 6-6 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'B' - const amb_6_6 = rule.filter((curr, idx) => - (curr.ruleType === "C3") - && curr.idPrevDeadkey === rule[index].idPrevDeadkey - && curr.modifierKey === rule[index].modifierKey - && curr.key === rule[index].key - && (new TextDecoder().decode(curr.output) !== new TextDecoder().decode(rule[index].output)) - && idx < index - ); - - // 6-6 dk(C11) + [SHIFT CAPS K_A] > 'Ã' <-> dk(C11) + [SHIFT CAPS K_A] > 'Ã' - const dup_6_6 = - rule.filter((curr, idx) => - (curr.ruleType === "C3") - && curr.idDeadkey === rule[index].idDeadkey - && curr.modifierKey === rule[index].modifierKey - && curr.key === rule[index].key - && (new TextDecoder().decode(curr.output) === new TextDecoder().decode(rule[index].output)) - && idx < index - ); - - if (amb_2_4.length > 0) { - warningText[0] = warningText[0] - + ("ambiguous rule: earlier: [" - + amb_2_4[0].modifierDeadkey - + " " - + amb_2_4[0].deadkey - + "] > dk(A" - + amb_2_4[0].idDeadkey - + ") "); - } - - if (amb_6_3.length > 0) { - warningText[1] = warningText[1] - + ("ambiguous rule: earlier: dk(C" - + amb_6_3[0].idDeadkey - + ") + [" - + amb_6_3[0].modifierKey - + " " - + amb_6_3[0].key - + "] > \'" - + this.writeCharacterOrUnicode(new TextDecoder().decode(amb_6_3[0].output)).character - + "\' "); - } - - if (dup_6_3.length > 0) { - warningText[1] = warningText[1] - + ("duplicate rule: earlier: dk(C" - + dup_6_3[0].idDeadkey - + ") + [" - + dup_6_3[0].modifierKey - + " " - + dup_6_3[0].key - + "] > \'" - + this.writeCharacterOrUnicode(new TextDecoder().decode(dup_6_3[0].output)).character - + "\' "); - } - - if (amb_4_4.length > 0) { - warningText[0] = warningText[0] - + ("ambiguous rule: earlier: [" - + amb_4_4[0].modifierPrevDeadkey - + " " - + amb_4_4[0].prevDeadkey - + "] > dk(C" - + amb_4_4[0].idPrevDeadkey - + ") "); - } - - if (dup_4_4.length > 0) { - warningText[0] = warningText[0] - + ("duplicate rule: earlier: [" - + dup_4_4[0].modifierPrevDeadkey - + " " - + dup_4_4[0].prevDeadkey - + "] > dk(C" - + dup_4_4[0].idPrevDeadkey - + ") "); - } - - if (amb_5_5.length > 0) { - warningText[1] = warningText[1] - + ("ambiguous rule: earlier: dk(B" - + amb_5_5[0].idPrevDeadkey - + ") + [" - + amb_5_5[0].modifierDeadkey - + " " - + amb_5_5[0].deadkey - + "] > dk(B" - + amb_5_5[0].idDeadkey - + ") "); - } - - if (dup_5_5.length > 0) { - warningText[1] = warningText[1] - + ("duplicate rule: earlier: dk(B" - + dup_5_5[0].idPrevDeadkey - + ") + [" - + dup_5_5[0].modifierDeadkey - + " " - + dup_5_5[0].deadkey - + "] > dk(B" - + dup_5_5[0].idDeadkey - + ") "); - } - - if (amb_6_6.length > 0) { - warningText[2] = warningText[2] - + ("ambiguous rule: earlier: dk(B" - + amb_6_6[0].idDeadkey - + ") + [" - + amb_6_6[0].modifierKey - + " " - + amb_6_6[0].key - + "] > \'" - + this.writeCharacterOrUnicode(new TextDecoder().decode(amb_6_6[0].output)).character - + "\' "); - } - - if (dup_6_6.length > 0) { - warningText[2] = warningText[2] - + ("duplicate rule: earlier: dk(B" - + dup_6_6[0].idDeadkey - + ") + [" - + dup_6_6[0].modifierKey - + " " - + dup_6_6[0].key - + "] > \'" - + this.writeCharacterOrUnicode(new TextDecoder().decode(dup_6_6[0].output)).character - + "\' "); - } - } - // In rare cases a rule might not be written out therefore we need to inform the user: - // usually we write the first occurance of an ambiguous C0/C1 rule and comment out the later - // assuming that if several C0/C1 rules are ambiguous the user prefers to use the first C0/C1 rule - // for C2/C3 rules we write the last occurance of an ambiguous rule and comment out the earlier - // assuming that if a C0/C1 and a C2/C3 rule is ambiguous the user prefers to use the C2/C3 rule over the C0/C1 rule - // if both happens, nothing would be written, therefore this messsage - - const extraWarning = "PLEASE CHECK THE FOLLOWING RULE AS IT WILL NOT BE WRITTEN ! "; - - if (warningText[0] !== "") { - warningText[0] = "c WARNING: " + warningText[0] + "here: "; - - if ((warningText[0].indexOf("earlier:") > 0) && (warningText[0].indexOf("later:") > 0)) { - warningText[0] = warningText[0] + extraWarning; - } - } - if (warningText[1] !== "") { - warningText[1] = "c WARNING: " + warningText[1] + "here: "; - - if ((warningText[1].indexOf("earlier:") > 0) && (warningText[1].indexOf("later:") > 0)) { - warningText[1] = warningText[1] + extraWarning; - } - } - - if (warningText[2] !== "") { - warningText[2] = "c WARNING: " + warningText[2] + "here: "; - - if ((warningText[2].indexOf("earlier:") > 0) && (warningText[2].indexOf("later:") > 0)) { - warningText[2] = warningText[2] + extraWarning; - } - } - return warningText; - } - - /** - * @brief member function to write a character as Unicode Character or Unicode Codepoint depending on the character that is to be written - * @param ctr : string - the character to be written - * @return a string containing the Unicode representation of the control character. - * A control character will be written as unicode (U+0004), - * a non-control character will be written as itself ( 'A', '1', '፩', '😎') - * null in case of an empty string or null or undefined input - */ - public writeCharacterOrUnicode(ctr: string, msg: string = ""): messageCharacter { - - if ((ctr === null) || (ctr === undefined) || (ctr.length === 0)) { - return null; - } - - let versionOutputCharacter; - const out: messageCharacter = { - message: msg, - character: ctr - }; - - const m_uni = /^U\+([0-9a-f]{1,6})$/i.exec(ctr); - const m_hex = /^&#x([0-9a-f]{1,6});$/i.exec(ctr); - const m_dec = /^&#([0-9]{1,7});$/.exec(ctr); - - // find the value of output character which may be specified in unicode, html hex or html dec format ( e.g. U+1234 -> 1234; ሴ -> 1234; ሴ -> 1234) - const ctr_val = ((m_uni || m_hex || m_dec) ? - m_uni ? parseInt(m_uni[1], 16) : m_hex ? parseInt(m_hex[1], 16) : parseInt(m_dec[1], 10) : XkbToKmnConverter.MAX_CTRL_CHARACTER - ); - - // for control charactersin 'U+...', '&#x...' or '&#...' format as well as in "" format - if ((ctr_val < XkbToKmnConverter.MAX_CTRL_CHARACTER) || (ctr.charCodeAt(0) < XkbToKmnConverter.MAX_CTRL_CHARACTER)) { - - // for control characters in 'U+...', '&#x...' or '&#...' format - if (ctr_val < XkbToKmnConverter.MAX_CTRL_CHARACTER) { - versionOutputCharacter = "U+" + ctr_val.toString(16).toUpperCase().padStart(4, '0'); - } - // for control characters in "" format - if (ctr.charCodeAt(0) < XkbToKmnConverter.MAX_CTRL_CHARACTER) { - versionOutputCharacter = "U+" + ctr.charCodeAt(0).toString(16).toUpperCase().padStart(4, '0'); - } - if (versionOutputCharacter) - out.character = versionOutputCharacter; - - // add a warning message - if (msg == "") { - out.message = "c WARNING: use of a control character "; - } - else { - out.message = msg + "; Use of a control character "; - } - } - else { - out.character = this.convertToUnicodeCharacter(ctr);; - } - return out; - } - - // TODO: move to util in PR 14569 - /** - * @brief function to convert a numeric character reference or a unicode value to a unicode character e.g. c -> c; U+1F60E -> 😎 - * @param inputString the value that will converted - * @return a unicode character like 'c', 'ሴ', '😎' or undefined if inputString is not recognized - */ - public convertToUnicodeCharacter_old(inputString: string): string { - - - // null, undefined will later be refused for conversion - if (inputString == null || inputString == undefined) { - return undefined; - } - - // U+ followed by 1.-6. hex digits will later be used for conversion - const m_uni = /^U\+([0-9a-f]{1,6})$/i.exec(inputString); - - // invalid U+ ( U+ followed by anything) will later be refused for conversion - const m_uni_inv = /^(U\+)+(.?)+$/i.exec(inputString); - - // &#x followed by 1.-6. hex digits will later be used for conversion - const m_hex = /^&#x([0-9a-f]{1,6});$/i.exec(inputString); - - // &# followed by 1.-6. decimal digits will later be used for conversion - const m_dec = /^&#([0-9]{1,7});$/.exec(inputString); - - // & followed by gt, lt, quot, amp, apos will later be used for conversion - const m_nam = /^&(gt|lt|quot|amp|apos);$/i.exec(inputString); - - // &# followed by anything will later be refused for conversion - const m_html_inv = /^(&#)+(.?)+$/i.exec(inputString); - - // one or more characters except starting with U+ or & will later be used for conversion - const m_chr = /^(?!U\+|&).+$/i.exec(inputString); - - // '&', '&#','&#x', or 'U+' with or without ; will later be refused for conversion - const m_chr_inv = /^((&;?)+|(&#;?)+|(&#x;?)+|(U\+)+;?)$|^$/i.exec(inputString); - - // valid 'U+xxxx' - if (m_uni) { - const codePoint_u = parseInt(m_uni[1], 16); - // Reject surrogates and invalid codepoints - if ((codePoint_u >= 0xD800 && codePoint_u <= 0xDFFF) || codePoint_u > 0x10FFFF) { - return undefined; - } - return String.fromCodePoint(codePoint_u); - } - - // invalid 'U+xxxx' - else if (m_uni_inv) { - return undefined; - } - - // valid '&#x...' - else if (m_hex) { - const codePoint_h = parseInt(m_hex[1], 16); - // Reject surrogates and invalid codepoints - if ((codePoint_h >= 0xD800 && codePoint_h <= 0xDFFF) || codePoint_h > 0x10FFFF) { - return undefined; - } - return String.fromCodePoint(codePoint_h); - } - // valid '&#...' - else if (m_dec) { - const codePoint_d = parseInt(m_dec[1], 10); - // Reject surrogates and invalid codepoints - if ((codePoint_d >= 0xD800 && codePoint_d <= 0xDFFF) || codePoint_d > 0x10FFFF) { - return undefined; - } - return String.fromCodePoint(codePoint_d); - } - // valid '>', '<',.. - else if (m_nam) { - switch (m_nam[1].toLowerCase()) { - case 'gt': return '>'; - case 'lt': return '<'; - case 'quot': return '"'; - case 'amp': return '&'; - case 'apos': return "'"; - default: return undefined; - } - } - // invalid '&...' - else if (m_html_inv) { - return undefined; - } - - // single 'U+', '&', '' - else if (m_chr_inv) { - return inputString; - } - - // if no matches so far, check for one or more characters ('a','ab', 'ẘ','😎', '😎😎', ) - else if (m_chr) { - return inputString; - } - return undefined; - } - public convertToUnicodeCharacter(inputString: string): string { - - - // null, undefined will later be refused for conversion - if (inputString == null || inputString == undefined) { - return undefined; - } - - // &#x followed by 1.-6. hex digits will later be used for conversion - const m_hex = /^&#x([0-9a-f]{1,6});$/i.exec(inputString); - - // &# followed by 1.-6. decimal digits will later be used for conversion - const m_dec = /^&#([0-9]{1,7});$/.exec(inputString); - - // & followed by gt, lt, quot, amp, apos will later be used for conversion - const m_nam = /^&(gt|lt|quot|amp|apos);$/i.exec(inputString); - - // &# followed by anything will later be refused for conversion - const m_html_inv = /^(&#)+(.?)+$/i.exec(inputString); - - // one or more characters except starting with & will later be used for conversion - const m_chr = /^(?!&).+$/i.exec(inputString); - - // '&', '&#','&#x' with or without ; will later be refused for conversion - const m_chr_inv = /^((&;?)+|(&#;?)+|(&#x;?)+;?)$|^$/i.exec(inputString); - - // valid '&#x...' - if (m_hex) { - const codePoint_h = parseInt(m_hex[1], 16); - // Reject surrogates and invalid codepoints - if ((codePoint_h >= 0xD800 && codePoint_h <= 0xDFFF) || codePoint_h > 0x10FFFF) { - return undefined; - } - return String.fromCodePoint(codePoint_h); - } - // valid '&#...' - else if (m_dec) { - const codePoint_d = parseInt(m_dec[1], 10); - // Reject surrogates and invalid codepoints - if ((codePoint_d >= 0xD800 && codePoint_d <= 0xDFFF) || codePoint_d > 0x10FFFF) { - return undefined; - } - return String.fromCodePoint(codePoint_d); - } - // valid '>', '<',.. - else if (m_nam) { - switch (m_nam[1].toLowerCase()) { - case 'gt': return '>'; - case 'lt': return '<'; - case 'quot': return '"'; - case 'amp': return '&'; - case 'apos': return "'"; - default: return undefined; - } - } - // invalid '&...' - else if (m_html_inv) { - return undefined; - } - - // single '&', '' - else if (m_chr_inv) { - return inputString; - } - - // if no matches so far, check for one or more characters ('a','ab', 'ẘ','😎', '😎😎', ) - else if (m_chr) { - return inputString; - } - return undefined; - } -} diff --git a/developer/src/kmc-convert/test/kmnXKB-file-writer.tests.ts b/developer/src/kmc-convert/test/kmnXKB-file-writer.tests.ts deleted file mode 100644 index e3ffb2386d3..00000000000 --- a/developer/src/kmc-convert/test/kmnXKB-file-writer.tests.ts +++ /dev/null @@ -1,524 +0,0 @@ -/* - * Keyman is copyright (C) SIL Global. MIT License. - * - * Created by S. Schmitt on 2025-05-12 - * - * Tests for XkbToKmnConverter, XkbFileReader, KmnXKBFileWriter - * - */ - -import 'mocha'; -import { assert } from 'chai'; -import KEYMAN_VERSION from "@keymanapp/keyman-version"; -import { compilerTestCallbacks, compilerTestOptions, makePathToFixture } from './helpers/index.js'; -import { XkbToKmnConverter, ProcessedData, Rule } from '../src/xkb-to-kmn/xkb-to-kmn-converter.js'; -import { KmnXKBFileWriter } from '../src/xkb-to-kmn/kmnXKB-file-writer.js'; -import { XkbFileReader } from '../src/xkb-to-kmn/xkb-file-reader.js'; - -describe('KmnXKBFileWriter', function () { - - before(function () { - compilerTestCallbacks.clear(); - }); - - describe("Xkb-kmn: writeDataRules() ", function () { - const inputFilename = makePathToFixture('../data/tests-xkb-kmn/Test.xkb'); - const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const sutR = new XkbFileReader(compilerTestCallbacks); - const sutW = new KmnXKBFileWriter(compilerTestCallbacks, compilerTestOptions); - const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); - const converted = sut.convertBound.convert(read, inputFilename.replace(/\.xkb$/, '.kmn')); - - it('writeDataRules() should return true (no error) if written', async function () { - const result = sutW.writeDataRules(converted); - assert.isTrue(result.length > 0); - }); - - }); - - describe("Xkb-kmn: writeKmnFileHeader() ", function () { - const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const sutR = new XkbFileReader(compilerTestCallbacks); - const sutW = new KmnXKBFileWriter(compilerTestCallbacks, compilerTestOptions); - const inputFilename = makePathToFixture('../data/tests-xkb-kmn/Test.xkb'); - const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); - const converted = sut.convertBound.convert(read, inputFilename.replace(/\.xkb$/, '.kmn')); - - const outExpectedFirst: string = - "c ..................................................................................................................\n" - + "c ..................................................................................................................\n" - + "c Keyman keyboard generated by kmn-convert version: " + KEYMAN_VERSION.VERSION + "\n" - + "c from Ukelele file: "; - - const outExpectedLast: string = - "\n" - + "c ..................................................................................................................\n" - + "c ..................................................................................................................\n" - + "\n" - + "store(&TARGETS) 'desktop'\n" - + "\n" - + "begin Unicode > use(main)\n\n" - + "group(main) using keys\n\n" - + "\n"; - - it(('writeKmnFileHeader should return store text with filename ').padEnd(62, " ") + 'on correct input', async function () { - const writtenCorrectName = sutW.writeKmnFileHeader(converted); - assert.equal(writtenCorrectName, (outExpectedFirst + converted.keylayoutFilename + outExpectedLast)); - }); - }); - - describe('Xkb-kmn: convertToUnicodeCharacter ', function () { - const sutW = new KmnXKBFileWriter(compilerTestCallbacks, compilerTestOptions); - [ - - ["<", '<'], - ["a", 'a'], - ["ሴ", 'ሴ'], - ["W̊", "W̊"], - ['😎', '😎'], - ["ab", 'ab'], - ["ሴЖ", 'ሴЖ'], - ["ẘẈ", "ẘẈ"], - ["😎😆", '😎😆'], - ["aሴ😆", 'aሴ😆'], - /* - ["U+0061", 'a'], - ["U+1234", 'ሴ'], - ["U+1E9A", "ẚ"], - ["U+1F60A", '😊'], - ["U+0001", '\u0001'], - ["U+1000000;", undefined], - */ - ["a", 'a'], - ["ሴ", 'ሴ'], - ["ẘ", "ẘ"], - ["😏", '😏'], - ["", '\u0002'], - ["�", undefined], - ["a", 'a'], - ["ሴ", 'ሴ'], - ["ẛ", "ẛ"], - ["😆", '😆'], - ["", '\u0003'], - ["󴉀", '󴉀'], - ["@", undefined], - [">", '>'], - ["<", '<'], - [""", '"'], - ["'", "'"], - [">", undefined], - ["␤", '␤'], - ["␕", '␕'], - ["", ''], - ["", ''], - [undefined, undefined], - [null, undefined], - /* - ["U+", undefined], - ['U+', undefined], - ['U+U+', undefined], - ['U+D799', '힙'], - ['U+D800', undefined], - ['U+D83D', undefined], - ['U+DFFF', undefined], - ['U+10FFFF', '􏿿'], - ['U+E000', ''], - ['U+1000000', undefined], - */ - ['&', '&'], - ['&;', '&;'], - ['&&', '&&'], - ['&&;', '&&;'], - ["&#&#", undefined], - ["&#x&#x", undefined], - ["&#", undefined], - ["&#;", undefined], - ["&#x", undefined], - ["&#x;", undefined], - ['&##', undefined], - ['&##;', undefined], - ["􏿿", "􏿿"], - ["􏿿", "􏿿"], - ["�", undefined], - ["�", undefined], - ['Ӓ56', undefined], - -//.................................................................. - - ["a", 'a'], - ["ሴ", 'ሴ'], - ["😎", '😎'], - ["", '\u0002'], - ["�", undefined], - ["a", 'a'], - ["ሴ", 'ሴ'], - ["😆", '😆'], - ["", '\u0003'], - ["󴉀", '󴉀'], - /*["U+0061", 'a'], - ["U+1234", 'ሴ'], - ["U+1F60E", '😎'], - ["U+0001", '\u0001'], - ["U+1000000;", undefined],*/ - ["@", undefined], - ["a", 'a'], - ["ሴ", 'ሴ'], - ['😎', '😎'], - ["W̊", "W̊"], - ["ab", 'ab'], - ["", ''], - ["␤", '␤'], - ["␕", '␕'], - ["", ''], - [undefined, undefined], - [null, undefined] - ].forEach(function (values) { - it(('should convert "' + values[0] + '"').padEnd(25, " ") + 'to "' + values[1] + '"', async function () { - const result = sutW.convertToUnicodeCharacter(values[0] as string); - assert.equal(result, values[1]); - }); - }); - }); - - describe('Xkb-kmn: reviewRules messages', function () { - const sutW = new KmnXKBFileWriter(compilerTestCallbacks, compilerTestOptions); - [ - [[new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'UNAVAILABLE', 'K_A', new TextEncoder().encode('A'))], - [''], - [''], - ['c WARNING: unavailable modifier : here: ']], - - [[new Rule("C1", '', '', 0, 0, 'CAPS', 'K_EQUAL', 0, 0, 'UNAVAILABLE', 'K_B', new TextEncoder().encode('B'))], - [''], - [''], - ['c WARNING: unavailable modifier : here: ']], - - [[new Rule("C2", '', '', 0, 0, 'CAPS', 'K_EQUAL', 0, 0, 'UNAVAILABLE', 'K_C', new TextEncoder().encode('C'),)], - [''], - [''], - ['c WARNING: unavailable modifier : here: ']], - - [[new Rule("C2", '', '', 0, 0, 'UNAVAILABLE_dk', 'K_EQUAL', 0, 0, 'UNAVAILABLE', 'K_C', new TextEncoder().encode('C'),)], - [''], - ['c WARNING: unavailable modifier : here: '], - ['c WARNING: unavailable modifier : here: ']], - - [[new Rule("C3", 'UNAVAILABLE_prev_dk', 'K_D', 0, 0, 'UNAVAILABLE_dk', 'K_EQUAL', 0, 0, 'SHIFT', 'K_C', new TextEncoder().encode('D'),)], - ['c WARNING: unavailable modifier : here: '], - ['c WARNING: unavailable modifier : here: '], - ['c WARNING: unavailable superior rule ( [UNAVAILABLE_dk K_EQUAL] > dk(B0) ) : here: ']], - - [[new Rule("C3", 'UNAVAILABLE_prev_dk', 'K_D', 0, 0, 'UNAVAILABLE_dk', 'K_EQUAL', 0, 0, 'UNAVAIL', 'K_C', new TextEncoder().encode('D'),)], - ['c WARNING: unavailable modifier : here: '], - ['c WARNING: unavailable modifier : here: '], - ['c WARNING: unavailable modifier : here: ']], - - [[new Rule("C3", 'CAPS', 'K_D', 0, 0, 'RALT', 'K_EQUAL', 0, 0, 'SHIFT', 'K_C', new TextEncoder().encode('D'),)], - [''], - [''], - ['']], - - [[new Rule("C3", 'X', 'K_X', 0, 0, 'Y', 'K_Y', 0, 0, 'SHIFT', 'K_Z', new TextEncoder().encode('D'),)], - ['c WARNING: unavailable modifier : here: '], - ['c WARNING: unavailable modifier : here: '], - ['c WARNING: unavailable superior rule ( [Y K_Y] > dk(B0) ) : here: ']], - - ].forEach(function (values: any, index: number) { - it(('rule " ' + values[0][0].ruleType + ' "') + 'should create "' + values[1] + ' | ' + values[2] + ' | ' + values[3] + '"', async function () { - const result: string[] = sutW.reviewRules(values[0], 0); - assert.equal(result[0], values[1][0]); - assert.equal(result[1], values[2][0]); - assert.equal(result[2], values[3][0]); - }); - }); - }); - - describe('Xkb-kmn: reviewRules messages duplicate and ambiguous', function () { - const sutW = new KmnXKBFileWriter(compilerTestCallbacks, compilerTestOptions); - [ - //all - [[ - new Rule("C3", 'LALT', 'K_A', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), - new Rule("C3", 'LALT', 'K_A', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')),], - ['c WARNING: duplicate rule: earlier: [LALT K_A] > dk(C0) here: '], - ["c WARNING: duplicate rule: earlier: dk(B0) + [SHIFT K_B] > dk(B0) here: "], - ["c WARNING: duplicate rule: earlier: dk(B0) + [CAPS K_C] > 'X' here: "]], - - //6-6 dup - [[ - new Rule("C3", 'LALT', 'K_A', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), - new Rule("C3", 'CTRL', 'K_D', 0, 0, 'NCAPS', 'K_E', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')),], - [''], - [""], - ["c WARNING: duplicate rule: earlier: dk(B0) + [CAPS K_C] > 'X' here: "]], - - //6-6 amb - [[ - new Rule("C3", 'LALT', 'K_A', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), - new Rule("C3", 'CTRL', 'K_D', 0, 0, 'NCAPS', 'K_E', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('Y')),], - [''], - [""], - ["c WARNING: ambiguous rule: earlier: dk(B0) + [CAPS K_C] > 'X' here: "]], - - // 5-5 amb - [[ - new Rule("C3", 'LALT', 'K_A', 0, 0, 'NCAPS', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), - new Rule("C3", 'LALT', 'K_A', 0, 0, 'NCAPS', 'K_B', 0, 1, 'RALT', 'K_F', new TextEncoder().encode('X')),], - ['c WARNING: duplicate rule: earlier: [LALT K_A] > dk(C0) here: '], - ["c WARNING: ambiguous rule: earlier: dk(B0) + [NCAPS K_B] > dk(B0) here: "], [''], - ], - - // 5-5 dup - [[ - new Rule("C3", 'LALT', 'K_A', 0, 0, 'NCAPS', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), - new Rule("C3", 'LALT', 'K_A', 0, 0, 'NCAPS', 'K_B', 0, 0, 'RALT', 'K_F', new TextEncoder().encode('X')),], - ['c WARNING: duplicate rule: earlier: [LALT K_A] > dk(C0) here: '], - ["c WARNING: duplicate rule: earlier: dk(B0) + [NCAPS K_B] > dk(B0) here: "], - ['']], - - // 4-2 amb - [[ - new Rule("C3", 'LALT', 'K_A', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), - new Rule("C2", '', '', 0, 0, 'LALT', 'K_A', 0, 0, 'RALT', 'K_F', new TextEncoder().encode('X')),], - ['c WARNING: ambiguous rule: later: [LALT K_A] > dk(C0) here: '], - [''], - ['']], - - // 4-4 amb - [[ - new Rule("C3", 'LALT', 'K_A', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), - new Rule("C3", 'LALT', 'K_A', 1, 1, 'NCAPS', 'K_E', 0, 0, 'RALT', 'K_F', new TextEncoder().encode('Y')),], - ['c WARNING: ambiguous rule: earlier: [LALT K_A] > dk(C0) here: '], - [""], - [''],], - - // 4-4 dup - [[ - new Rule("C3", 'LALT', 'K_A', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), - new Rule("C3", 'LALT', 'K_A', 0, 0, 'NCAPS', 'K_E', 0, 0, 'RALT', 'K_F', new TextEncoder().encode('X')),], - ['c WARNING: duplicate rule: earlier: [LALT K_A] > dk(C0) here: '], - [''], - ['']], - - // 4-2 amb - [[ - new Rule("C3", 'LALT', 'K_A', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), - new Rule("C2", '', '', 0, 0, 'LALT', 'K_A', 0, 0, 'RALT', 'K_F', new TextEncoder().encode('Y')),], - ['c WARNING: ambiguous rule: later: [LALT K_A] > dk(C0) here: '], - [''], - ['']], - - // 6-3 dup - [[ - new Rule("C2", '', '', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), - new Rule("C3", 'CTRL', 'K_D', 0, 0, 'NCAPS', 'K_E', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')),], - [''], - ["c WARNING: duplicate rule: earlier: dk(C0) + [CAPS K_C] > 'X' here: "], - [''],], - - // 6-3 amb - [[ - new Rule("C2", '', '', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), - new Rule("C3", 'CTRL', 'K_D', 0, 0, 'NCAPS', 'K_E', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('Y')),], - [''], - ["c WARNING: ambiguous rule: earlier: dk(C0) + [CAPS K_C] > 'X' here: "], - [''],], - - // 2-4 amb - [[ - new Rule("C2", '', '', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), - new Rule("C3", 'SHIFT', 'K_B', 0, 0, 'NCAPS', 'K_E', 0, 0, 'RALT', 'K_F', new TextEncoder().encode('Y')),], - ['c WARNING: ambiguous rule: earlier: [SHIFT K_B] > dk(A0) here: '], - [''], - ['']], - - //2-2 amb - [[ - new Rule("C2", '', '', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), - new Rule("C2", '', '', 0, 0, 'SHIFT', 'K_B', 1, 1, 'RALT', 'K_F', new TextEncoder().encode('Y')),], - [''], - ['c WARNING: ambiguous rule: earlier: [SHIFT K_B] > dk(C0) here: '], - ['']], - - // 2-2 dup - [[ - new Rule("C2", '', '', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), - new Rule("C2", '', '', 0, 0, 'SHIFT', 'K_B', 0, 0, 'RALT', 'K_F', new TextEncoder().encode('Y')),], - [''], - ['c WARNING: duplicate rule: earlier: [SHIFT K_B] > dk(C0) here: '], - ['']], - - // 3-3 dup - [[ - new Rule("C2", '', '', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), - new Rule("C2", '', '', 0, 0, 'NCAPS', 'K_E', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')),], - [''], - [''], - ["c WARNING: duplicate rule: earlier: dk(A0) + [CAPS K_C] > 'X' here: "]], - - // 3-3 amb - [[ - new Rule("C2", '', '', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), - new Rule("C2", '', '', 0, 0, 'NCAPS', 'K_E', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('Y')),], - [''], - [''], - ["c WARNING: ambiguous rule: earlier: dk(A0) + [CAPS K_C] > 'X' here: "]], - - // 2-1 amb - [[ - new Rule("C2", '', '', 0, 0, 'RALT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), - new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'RALT', 'K_B', new TextEncoder().encode('Y'))], - [''], - [''], - ['c WARNING: ambiguous rule: later: [RALT K_B] > dk(A0) here: ']], - - // 1-1 amb - [[ - new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), - new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('Y'))], - [''], - [''], - ["c WARNING: ambiguous rule: earlier: [CAPS K_C] > 'X' here: "]], - - // 1-1 amb - [[ - new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')), - new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X'))], - [''], - [''], - ["c WARNING: duplicate rule: earlier: [CAPS K_C] > 'X' here: "]], - - ].forEach(function (values: any, index: number) { - it('rule ' + values[0][0].ruleType + ' should create " ' + ' "' + values[1] + ' | ' + values[2] + ' | ' + values[3] + '"', async function () { - const result: string[] = sutW.reviewRules(values[0], 1); - assert.equal(result[0], values[1][0]); - assert.equal(result[1], values[2][0]); - assert.equal(result[2], values[3][0]); - }); - }); - }); - - describe('Xkb-kmn: reviewRules messages duplicate and ambiguous with Extra warning', function () { - const sutW = new KmnXKBFileWriter(compilerTestCallbacks, compilerTestOptions); - [[[ - new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'RALT', 'K_B', new TextEncoder().encode('X')), - new Rule("C2", '', '', 0, 0, 'RALT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('Y')), - new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'RALT', 'K_B', new TextEncoder().encode('Z')) - ], - [''], - [''], - ["c WARNING: ambiguous rule: later: [RALT K_B] > dk(A0) ambiguous rule: earlier: [RALT K_B] > 'X' here: PLEASE CHECK THE FOLLOWING RULE AS IT WILL NOT BE WRITTEN ! "]], - ].forEach(function (values: any, index: number) { - it(('rule ' + values[0][0].ruleType + ' should create " ' + ' "') + values[1] + ' | ' + values[2] + ' | ' + values[3] + '"', async function () { - const result: string[] = sutW.reviewRules(values[0], 2); - assert.equal(result[0], values[1][0]); - assert.equal(result[1], values[2][0]); - assert.equal(result[2], values[3][0]); - }); - }); - }); - - describe('Xkb-kmn: write from intermediate data array', function () { - const sutW = new KmnXKBFileWriter(compilerTestCallbacks, compilerTestOptions); - [ - [ - [ /* see ../data/tests-xkb-kmn/Test_C0.xkb */ - new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_A', new TextEncoder().encode('a')), - new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_A', new TextEncoder().encode('A')), - new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_S', new TextEncoder().encode('s')), - new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_D', new TextEncoder().encode('d')) - ], - ["+ [NCAPS K_A] > 'a'\n" + - "+ [CAPS K_A] > 'A'\n\n" + - "+ [NCAPS K_S] > 's'\n\n" + - "+ [NCAPS K_D] > 'd'\n"] - ], - [ - [ /* see ../data/tests-xkb-kmn/Test_C1.xkb */ - new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_S', new TextEncoder().encode('s')), - new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_S', new TextEncoder().encode('S')) - ], - ["+ [NCAPS K_S] > 's'\n" + - "+ [CAPS K_S] > 'S'\n"] - ], - [ - [ /* see ../data/tests-xkb-kmn/Test_C2.xkb */ - new Rule("C2", '', '', 0, 0, 'NCAPS', 'K_U', 1, 1, 'CAPS', 'K_A', new TextEncoder().encode('Â')) - ], - ["+ [NCAPS K_U] > dk(A1)\n" + - "dk(A1) + [CAPS K_A] > 'Â'\n\n"] - ], - [ - [ /* see ../data/tests-xkb-kmn/Test_C3.xkb */ - new Rule("C3", 'NCAPS SHIFT', 'K_D', 2, 1, 'NCAPS', 'K_U', 1, 2, 'CAPS', 'K_A', new TextEncoder().encode('Â')) - ], - ["+ [NCAPS SHIFT K_D] > dk(A2)\n" + - "dk(A2) + [NCAPS K_U] > dk(B1)\n" + - "dk(B1) + [CAPS K_A] > 'Â'\n\n" - ] - ], - [ - [ /* see ../data/tests-xkb-kmn/Test_C0_C1_C2_C3.xkb */ - new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_A', new TextEncoder().encode('A')), - new Rule("C2", '', '', 0, 0, 'NCAPS RALT', 'K_EQUAL', 1, 1, 'CAPS', 'K_D', new TextEncoder().encode('Â')), - new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_S', new TextEncoder().encode('S')), - new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'NCAPS RALT', 'K_U', new TextEncoder().encode('S')), - new Rule("C3", 'NCAPS RALT', 'K_8', 6, 1, 'CAPS', 'K_S', 2, 6, 'CAPS', 'K_D', new TextEncoder().encode('Â')), - new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'CAPS', 'K_U', 3, 3, 'CAPS', 'K_D', new TextEncoder().encode('Â')), - new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'NCAPS RALT', 'K_S', 4, 4, 'CAPS', 'K_D', new TextEncoder().encode('Â')), - new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'NCAPS RALT', 'K_U', 5, 5, 'CAPS', 'K_D', new TextEncoder().encode('Â')), - new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_S', new TextEncoder().encode('S')), - new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'NCAPS RALT', 'K_U', new TextEncoder().encode('S')), - new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'CAPS', 'K_S', 2, 0, 'CAPS', 'K_D', new TextEncoder().encode('Â')), - new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'CAPS', 'K_U', 3, 0, 'CAPS', 'K_D', new TextEncoder().encode('Â')), - new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'NCAPS RALT', 'K_S', 4, 0, 'CAPS', 'K_D', new TextEncoder().encode('Â')), - new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'NCAPS RALT', 'K_U', 5, 0, 'CAPS', 'K_D', new TextEncoder().encode('Â')), - new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_U', new TextEncoder().encode('U')), - ], - ["+ [CAPS K_A] > 'A'\n" + - "+ [CAPS K_S] > 'S'\n\n" + - "+ [NCAPS RALT K_U] > 'S'\n" + - "+ [CAPS K_U] > 'U'\n" + - "+ [NCAPS RALT K_EQUAL] > dk(A1)\n" + - "dk(A1) + [CAPS K_D] > 'Â'\n\n" + - "+ [NCAPS RALT K_8] > dk(A6)\n" + - "dk(A6) + [CAPS K_S] > dk(B2)\n" + - "dk(B2) + [CAPS K_D] > 'Â'\n\n" + - "dk(A6) + [CAPS K_U] > dk(B3)\n" + - "dk(B3) + [CAPS K_D] > 'Â'\n\n" + - "dk(A6) + [NCAPS RALT K_S] > dk(B4)\n" + - "dk(B4) + [CAPS K_D] > 'Â'\n\n" + - "dk(A6) + [NCAPS RALT K_U] > dk(B5)\n" + - "dk(B5) + [CAPS K_D] > 'Â'\n\n"] - ], - [ - [ /* see ../data/tests-xkb-kmn/Test_C3_several.xkb */ - new Rule("C3", 'NCAPS RALT', 'K_8', 3, 1, 'CAPS', 'K_U', 1, 3, 'NCAPS', 'K_A', new TextEncoder().encode('â')), - new Rule("C3", 'NCAPS RALT', 'K_8', 3, 0, 'CAPS', 'K_U', 1, 0, 'NCAPS RALT', 'K_A', new TextEncoder().encode('â')), - new Rule("C3", 'NCAPS RALT', 'K_8', 3, 0, 'NCAPS RALT', 'K_U', 2, 2, 'NCAPS', 'K_A', new TextEncoder().encode('â')), - new Rule("C3", 'NCAPS RALT', 'K_8', 3, 0, 'NCAPS RALT', 'K_U', 2, 0, 'NCAPS RALT', 'K_A', new TextEncoder().encode('â')) - ], - ["+ [NCAPS RALT K_8] > dk(A3)\n" + - "dk(A3) + [CAPS K_U] > dk(B1)\n" + - "dk(B1) + [NCAPS K_A] > 'â'\n\n" + - "dk(B1) + [NCAPS RALT K_A] > 'â'\n\n" + - "dk(A3) + [NCAPS RALT K_U] > dk(B2)\n" + - "dk(B2) + [NCAPS K_A] > 'â'\n\n" + - "dk(B2) + [NCAPS RALT K_A] > 'â'\n\n" - ] - ], - ].forEach(function (values: any) { - it(('an array of Rules should create a set of kmn rules '), async function () { - const data: ProcessedData = { - keylayoutFilename: "", - kmnFilename: "", - modifiers: [[]], - rules: values[0] - }; - const result1 = sutW.writeDataRules(data); - assert.isTrue(result1 === values[1][0]); - }); - }); - }); - -}); diff --git a/developer/src/kmc-convert/test/xkb-file-reader.tests.ts b/developer/src/kmc-convert/test/xkb-file-reader.tests.ts index 936dbc32a6a..e6099b87bf8 100644 --- a/developer/src/kmc-convert/test/xkb-file-reader.tests.ts +++ b/developer/src/kmc-convert/test/xkb-file-reader.tests.ts @@ -10,7 +10,7 @@ import 'mocha'; import { assert } from 'chai'; import { compilerTestCallbacks, makePathToFixture } from './helpers/index.js'; -import { XkbFileReader } from '../src/xkb-to-kmn/xkb-file-reader.js'; +import { XkbFileReader } from '../src/kmc-convert-read/xkb-file-reader.js'; describe('XkbFileReader', function () { diff --git a/developer/src/kmc-convert/test/xkb-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/xkb-to-kmn-converter.tests.ts index ed00fc22d49..7082f319913 100644 --- a/developer/src/kmc-convert/test/xkb-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/xkb-to-kmn-converter.tests.ts @@ -10,8 +10,8 @@ import 'mocha'; import { assert } from 'chai'; import * as NodeAssert from 'node:assert'; import { compilerTestCallbacks, compilerTestOptions, makePathToFixture } from './helpers/index.js'; -import { ActionStateOutput, KeylayoutFileData, XkbToKmnConverter, Rule } from '../src/xkb-to-kmn/xkb-to-kmn-converter.js'; -import { XkbFileReader } from '../src/xkb-to-kmn/xkb-file-reader.js'; +import { ActionStateOutput, KeylayoutFileData, XkbToKmnConverter, Rule } from '../src/kmc-convert-convert/xkb-to-kmn-converter.js'; +import { XkbFileReader } from '../src/kmc-convert-read/xkb-file-reader.js'; import { ConverterMessages } from '../src/converter-messages.js'; describe('XkbToKmnConverter', function () { From 596c25dd3ee9a22c868991205326045837ce50f5 Mon Sep 17 00:00:00 2001 From: Sabine Date: Thu, 7 May 2026 09:53:24 +0200 Subject: [PATCH 243/251] feat(developer): add (empty) dummy files for structure --- .../src/kmc-convert-convert/inkey-to-kmn-converter.ts | 3 +++ .../src/kmc-convert-convert/inkey-to-ldml-converter.ts | 3 +++ .../src/kmc-convert-convert/keylayout-to-ldml-converter.ts | 3 +++ .../src/kmc-convert-convert/kmn-to-ldml-converter.ts | 3 +++ .../src/kmc-convert-convert/ldml-to-kmn-converter.ts | 3 +++ .../src/kmc-convert-convert/msklc-to-kmn-converter.ts | 3 +++ .../src/kmc-convert-convert/msklc-to-ldml-converter.ts | 3 +++ .../src/kmc-convert/src/kmc-convert-read/inkey-file-reader.ts | 3 +++ .../src/kmc-convert/src/kmc-convert-read/kmn-file-reader.ts | 3 +++ .../src/kmc-convert/src/kmc-convert-read/ldml-file-reader.ts | 3 +++ .../src/kmc-convert/src/kmc-convert-read/msklc-file-reader.ts | 4 ++++ .../src/kmc-convert/src/kmc-convert-write/ldml-file-writer.ts | 3 +++ 12 files changed, 37 insertions(+) create mode 100644 developer/src/kmc-convert/src/kmc-convert-convert/inkey-to-kmn-converter.ts create mode 100644 developer/src/kmc-convert/src/kmc-convert-convert/inkey-to-ldml-converter.ts create mode 100644 developer/src/kmc-convert/src/kmc-convert-convert/keylayout-to-ldml-converter.ts create mode 100644 developer/src/kmc-convert/src/kmc-convert-convert/kmn-to-ldml-converter.ts create mode 100644 developer/src/kmc-convert/src/kmc-convert-convert/ldml-to-kmn-converter.ts create mode 100644 developer/src/kmc-convert/src/kmc-convert-convert/msklc-to-kmn-converter.ts create mode 100644 developer/src/kmc-convert/src/kmc-convert-convert/msklc-to-ldml-converter.ts create mode 100644 developer/src/kmc-convert/src/kmc-convert-read/inkey-file-reader.ts create mode 100644 developer/src/kmc-convert/src/kmc-convert-read/kmn-file-reader.ts create mode 100644 developer/src/kmc-convert/src/kmc-convert-read/ldml-file-reader.ts create mode 100644 developer/src/kmc-convert/src/kmc-convert-read/msklc-file-reader.ts create mode 100644 developer/src/kmc-convert/src/kmc-convert-write/ldml-file-writer.ts diff --git a/developer/src/kmc-convert/src/kmc-convert-convert/inkey-to-kmn-converter.ts b/developer/src/kmc-convert/src/kmc-convert-convert/inkey-to-kmn-converter.ts new file mode 100644 index 00000000000..5e1a8c0d61b --- /dev/null +++ b/developer/src/kmc-convert/src/kmc-convert-convert/inkey-to-kmn-converter.ts @@ -0,0 +1,3 @@ + + +// tbd. diff --git a/developer/src/kmc-convert/src/kmc-convert-convert/inkey-to-ldml-converter.ts b/developer/src/kmc-convert/src/kmc-convert-convert/inkey-to-ldml-converter.ts new file mode 100644 index 00000000000..5e1a8c0d61b --- /dev/null +++ b/developer/src/kmc-convert/src/kmc-convert-convert/inkey-to-ldml-converter.ts @@ -0,0 +1,3 @@ + + +// tbd. diff --git a/developer/src/kmc-convert/src/kmc-convert-convert/keylayout-to-ldml-converter.ts b/developer/src/kmc-convert/src/kmc-convert-convert/keylayout-to-ldml-converter.ts new file mode 100644 index 00000000000..5e1a8c0d61b --- /dev/null +++ b/developer/src/kmc-convert/src/kmc-convert-convert/keylayout-to-ldml-converter.ts @@ -0,0 +1,3 @@ + + +// tbd. diff --git a/developer/src/kmc-convert/src/kmc-convert-convert/kmn-to-ldml-converter.ts b/developer/src/kmc-convert/src/kmc-convert-convert/kmn-to-ldml-converter.ts new file mode 100644 index 00000000000..5e1a8c0d61b --- /dev/null +++ b/developer/src/kmc-convert/src/kmc-convert-convert/kmn-to-ldml-converter.ts @@ -0,0 +1,3 @@ + + +// tbd. diff --git a/developer/src/kmc-convert/src/kmc-convert-convert/ldml-to-kmn-converter.ts b/developer/src/kmc-convert/src/kmc-convert-convert/ldml-to-kmn-converter.ts new file mode 100644 index 00000000000..5e1a8c0d61b --- /dev/null +++ b/developer/src/kmc-convert/src/kmc-convert-convert/ldml-to-kmn-converter.ts @@ -0,0 +1,3 @@ + + +// tbd. diff --git a/developer/src/kmc-convert/src/kmc-convert-convert/msklc-to-kmn-converter.ts b/developer/src/kmc-convert/src/kmc-convert-convert/msklc-to-kmn-converter.ts new file mode 100644 index 00000000000..5e1a8c0d61b --- /dev/null +++ b/developer/src/kmc-convert/src/kmc-convert-convert/msklc-to-kmn-converter.ts @@ -0,0 +1,3 @@ + + +// tbd. diff --git a/developer/src/kmc-convert/src/kmc-convert-convert/msklc-to-ldml-converter.ts b/developer/src/kmc-convert/src/kmc-convert-convert/msklc-to-ldml-converter.ts new file mode 100644 index 00000000000..5e1a8c0d61b --- /dev/null +++ b/developer/src/kmc-convert/src/kmc-convert-convert/msklc-to-ldml-converter.ts @@ -0,0 +1,3 @@ + + +// tbd. diff --git a/developer/src/kmc-convert/src/kmc-convert-read/inkey-file-reader.ts b/developer/src/kmc-convert/src/kmc-convert-read/inkey-file-reader.ts new file mode 100644 index 00000000000..5e1a8c0d61b --- /dev/null +++ b/developer/src/kmc-convert/src/kmc-convert-read/inkey-file-reader.ts @@ -0,0 +1,3 @@ + + +// tbd. diff --git a/developer/src/kmc-convert/src/kmc-convert-read/kmn-file-reader.ts b/developer/src/kmc-convert/src/kmc-convert-read/kmn-file-reader.ts new file mode 100644 index 00000000000..5e1a8c0d61b --- /dev/null +++ b/developer/src/kmc-convert/src/kmc-convert-read/kmn-file-reader.ts @@ -0,0 +1,3 @@ + + +// tbd. diff --git a/developer/src/kmc-convert/src/kmc-convert-read/ldml-file-reader.ts b/developer/src/kmc-convert/src/kmc-convert-read/ldml-file-reader.ts new file mode 100644 index 00000000000..5e1a8c0d61b --- /dev/null +++ b/developer/src/kmc-convert/src/kmc-convert-read/ldml-file-reader.ts @@ -0,0 +1,3 @@ + + +// tbd. diff --git a/developer/src/kmc-convert/src/kmc-convert-read/msklc-file-reader.ts b/developer/src/kmc-convert/src/kmc-convert-read/msklc-file-reader.ts new file mode 100644 index 00000000000..c27f478b68e --- /dev/null +++ b/developer/src/kmc-convert/src/kmc-convert-read/msklc-file-reader.ts @@ -0,0 +1,4 @@ + + +// tbd. + diff --git a/developer/src/kmc-convert/src/kmc-convert-write/ldml-file-writer.ts b/developer/src/kmc-convert/src/kmc-convert-write/ldml-file-writer.ts new file mode 100644 index 00000000000..5e1a8c0d61b --- /dev/null +++ b/developer/src/kmc-convert/src/kmc-convert-write/ldml-file-writer.ts @@ -0,0 +1,3 @@ + + +// tbd. From 13fbb4f823b8bb3b97e2c4468bd283554e2c5dca Mon Sep 17 00:00:00 2001 From: Sabine Date: Thu, 7 May 2026 10:41:10 +0200 Subject: [PATCH 244/251] feat(developer): move test.ts files to seperate folder --- .../keylayout-to-kmn-converter.tests.ts | 8 ++++---- .../xkb-to-kmn-converter.tests.ts | 8 ++++---- .../test/{ => kmc-convert-read}/kmn-file-reader.tests.ts | 4 ++-- .../test/{ => kmc-convert-read}/xkb-file-reader.tests.ts | 4 ++-- .../test/{ => kmc-convert-write}/kmn-file-writer.tests.ts | 8 ++++---- 5 files changed, 16 insertions(+), 16 deletions(-) rename developer/src/kmc-convert/test/{ => kmc-convert-convert}/keylayout-to-kmn-converter.tests.ts (99%) rename developer/src/kmc-convert/test/{ => kmc-convert-convert}/xkb-to-kmn-converter.tests.ts (99%) rename developer/src/kmc-convert/test/{ => kmc-convert-read}/kmn-file-reader.tests.ts (90%) rename developer/src/kmc-convert/test/{ => kmc-convert-read}/xkb-file-reader.tests.ts (90%) rename developer/src/kmc-convert/test/{ => kmc-convert-write}/kmn-file-writer.tests.ts (98%) diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/kmc-convert-convert/keylayout-to-kmn-converter.tests.ts similarity index 99% rename from developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts rename to developer/src/kmc-convert/test/kmc-convert-convert/keylayout-to-kmn-converter.tests.ts index 808468a58cd..ac2c8002c03 100644 --- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/kmc-convert-convert/keylayout-to-kmn-converter.tests.ts @@ -9,10 +9,10 @@ import 'mocha'; import { assert } from 'chai'; import * as NodeAssert from 'node:assert'; -import { compilerTestCallbacks, compilerTestOptions, makePathToFixture } from './helpers/index.js'; -import { ActionStateOutput, KeylayoutFileData, KeylayoutToKmnConverter, Rule } from '../src/kmc-convert-convert/keylayout-to-kmn-converter.js'; -import { KeylayoutFileReader } from '../src//kmc-convert-read/keylayout-file-reader.js'; -import { ConverterMessages } from '../src/converter-messages.js'; +import { compilerTestCallbacks, compilerTestOptions, makePathToFixture } from './../helpers/index.js'; +import { ActionStateOutput, KeylayoutFileData, KeylayoutToKmnConverter, Rule } from '../../src/kmc-convert-convert/keylayout-to-kmn-converter.js'; +import { KeylayoutFileReader } from '../../src//kmc-convert-read/keylayout-file-reader.js'; +import { ConverterMessages } from '../../src/converter-messages.js'; describe('KeylayoutToKmnConverter', function () { diff --git a/developer/src/kmc-convert/test/xkb-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/kmc-convert-convert/xkb-to-kmn-converter.tests.ts similarity index 99% rename from developer/src/kmc-convert/test/xkb-to-kmn-converter.tests.ts rename to developer/src/kmc-convert/test/kmc-convert-convert/xkb-to-kmn-converter.tests.ts index 7082f319913..278254743a3 100644 --- a/developer/src/kmc-convert/test/xkb-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/kmc-convert-convert/xkb-to-kmn-converter.tests.ts @@ -9,10 +9,10 @@ import 'mocha'; import { assert } from 'chai'; import * as NodeAssert from 'node:assert'; -import { compilerTestCallbacks, compilerTestOptions, makePathToFixture } from './helpers/index.js'; -import { ActionStateOutput, KeylayoutFileData, XkbToKmnConverter, Rule } from '../src/kmc-convert-convert/xkb-to-kmn-converter.js'; -import { XkbFileReader } from '../src/kmc-convert-read/xkb-file-reader.js'; -import { ConverterMessages } from '../src/converter-messages.js'; +import { compilerTestCallbacks, compilerTestOptions, makePathToFixture } from './../helpers/index.js'; +import { ActionStateOutput, KeylayoutFileData, XkbToKmnConverter, Rule } from '../../src/kmc-convert-convert/xkb-to-kmn-converter.js'; +import { XkbFileReader } from '../../src/kmc-convert-read/xkb-file-reader.js'; +import { ConverterMessages } from '../../src/converter-messages.js'; describe('XkbToKmnConverter', function () { diff --git a/developer/src/kmc-convert/test/kmn-file-reader.tests.ts b/developer/src/kmc-convert/test/kmc-convert-read/kmn-file-reader.tests.ts similarity index 90% rename from developer/src/kmc-convert/test/kmn-file-reader.tests.ts rename to developer/src/kmc-convert/test/kmc-convert-read/kmn-file-reader.tests.ts index 419de530864..a8ad780f375 100644 --- a/developer/src/kmc-convert/test/kmn-file-reader.tests.ts +++ b/developer/src/kmc-convert/test/kmc-convert-read/kmn-file-reader.tests.ts @@ -9,8 +9,8 @@ import 'mocha'; import { assert } from 'chai'; -import { compilerTestCallbacks, makePathToFixture } from './helpers/index.js'; -import { KeylayoutFileReader } from '../src//kmc-convert-read/keylayout-file-reader.js'; +import { compilerTestCallbacks, makePathToFixture } from './../helpers/index.js'; +import { KeylayoutFileReader } from '../../src//kmc-convert-read/keylayout-file-reader.js'; describe('KeylayoutFileReader', function () { diff --git a/developer/src/kmc-convert/test/xkb-file-reader.tests.ts b/developer/src/kmc-convert/test/kmc-convert-read/xkb-file-reader.tests.ts similarity index 90% rename from developer/src/kmc-convert/test/xkb-file-reader.tests.ts rename to developer/src/kmc-convert/test/kmc-convert-read/xkb-file-reader.tests.ts index e6099b87bf8..6f418de2435 100644 --- a/developer/src/kmc-convert/test/xkb-file-reader.tests.ts +++ b/developer/src/kmc-convert/test/kmc-convert-read/xkb-file-reader.tests.ts @@ -9,8 +9,8 @@ import 'mocha'; import { assert } from 'chai'; -import { compilerTestCallbacks, makePathToFixture } from './helpers/index.js'; -import { XkbFileReader } from '../src/kmc-convert-read/xkb-file-reader.js'; +import { compilerTestCallbacks, makePathToFixture } from './../helpers/index.js'; +import { XkbFileReader } from '../../src/kmc-convert-read/xkb-file-reader.js'; describe('XkbFileReader', function () { diff --git a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts b/developer/src/kmc-convert/test/kmc-convert-write/kmn-file-writer.tests.ts similarity index 98% rename from developer/src/kmc-convert/test/kmn-file-writer.tests.ts rename to developer/src/kmc-convert/test/kmc-convert-write/kmn-file-writer.tests.ts index 8230b319895..d4abee2ab62 100644 --- a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts +++ b/developer/src/kmc-convert/test/kmc-convert-write/kmn-file-writer.tests.ts @@ -10,10 +10,10 @@ import 'mocha'; import { assert } from 'chai'; import KEYMAN_VERSION from "@keymanapp/keyman-version"; -import { compilerTestCallbacks, compilerTestOptions, makePathToFixture } from './helpers/index.js'; -import { KeylayoutToKmnConverter, ProcessedData, Rule } from '../src//kmc-convert-convert/keylayout-to-kmn-converter.js'; -import { KmnFileWriter } from '../src//kmc-convert-write/kmn-file-writer.js'; -import { KeylayoutFileReader } from '../src//kmc-convert-read/keylayout-file-reader.js'; +import { compilerTestCallbacks, compilerTestOptions, makePathToFixture } from './../helpers/index.js'; +import { KeylayoutToKmnConverter, ProcessedData, Rule } from '../../src//kmc-convert-convert/keylayout-to-kmn-converter.js'; +import { KmnFileWriter } from '../../src//kmc-convert-write/kmn-file-writer.js'; +import { KeylayoutFileReader } from '../../src//kmc-convert-read/keylayout-file-reader.js'; describe('KmnFileWriter', function () { From f0721063b59e1b7db9a5672c660ea4f6120be4f9 Mon Sep 17 00:00:00 2001 From: Sabine Date: Fri, 8 May 2026 12:26:21 +0200 Subject: [PATCH 245/251] feat(developer): remove unneccessary files --- .../types/src/consts/virtual-key-constants.ts | 2 +- .../inkey-to-kmn-converter.ts | 3 - .../inkey-to-ldml-converter.ts | 3 - .../keylayout-to-ldml-converter.ts | 3 - .../kmn-to-ldml-converter.ts | 3 - .../ldml-to-kmn-converter.ts | 3 - .../msklc-to-kmn-converter.ts | 3 - .../msklc-to-ldml-converter.ts | 3 - .../src/kmc-convert-read/inkey-file-reader.ts | 3 - .../src/kmc-convert-read/kmn-file-reader.ts | 3 - .../src/kmc-convert-read/ldml-file-reader.ts | 3 - .../src/kmc-convert-read/msklc-file-reader.ts | 4 - .../src/kmc-convert-write/ldml-file-writer.ts | 3 - .../keylayout.dtd | 0 .../data/tests-xkb-kmn/Test copy.keylayout | 596 ------------------ .../test/data/tests-xkb-kmn/Test_C0.keylayout | 45 -- .../tests-xkb-kmn/Test_C0_C1_C2_C3.keylayout | 58 -- .../test/data/tests-xkb-kmn/Test_C1.keylayout | 43 -- .../test/data/tests-xkb-kmn/Test_C2.keylayout | 43 -- .../tests-xkb-kmn/Test_C2_several.keylayout | 73 --- .../test/data/tests-xkb-kmn/Test_C3.keylayout | 53 -- .../tests-xkb-kmn/Test_C3_several.keylayout | 59 -- .../tests-xkb-kmn/Test_ExtraWarning.keylayout | 76 --- .../Test_ambiguous_keys.keylayout | 57 -- .../tests-xkb-kmn/Test_characters.keylayout | 51 -- ...ifferentAmountOfKeysInBehaviours.keylayout | 45 -- .../Test_differentEncodings.keylayout | 37 -- .../Test_duplicate_keys.keylayout | 61 -- .../Test_duplicate_missing_keycode.keylayout | 49 -- .../Test_duplicate_missing_keys.keylayout | 59 -- .../tests-xkb-kmn/Test_maxKeyCode.keylayout | 38 -- .../tests-xkb-kmn/Test_messages.keylayout | 80 --- .../Test_messages_controlCharacter.keylayout | 57 -- .../Test_messages_superior_C2.keylayout | 72 --- .../Test_messages_superior_C3.keylayout | 59 -- .../tests-xkb-kmn/Test_modifier.keylayout | 103 --- .../Test_modifierNoCaps.keylayout | 108 ---- ...eyMapThanKeyMapselectAndJisERROR.keylayout | 83 --- ..._moreKeyMapThanKeyMapselectERROR.keylayout | 78 --- ..._moreKeymapSelectThanKeymapERROR.keylayout | 65 -- .../tests-xkb-kmn/Test_nr_elements.keylayout | 45 -- .../Test_onlyOneKeymap.keylayout | 39 -- .../Test_undefinedAction.keylayout | 58 -- .../Test_unsupportedCharacters.keylayout | 58 -- .../test/data/tests-xkb-kmn/de_simple | 60 ++ 45 files changed, 61 insertions(+), 2386 deletions(-) delete mode 100644 developer/src/kmc-convert/src/kmc-convert-convert/inkey-to-kmn-converter.ts delete mode 100644 developer/src/kmc-convert/src/kmc-convert-convert/inkey-to-ldml-converter.ts delete mode 100644 developer/src/kmc-convert/src/kmc-convert-convert/keylayout-to-ldml-converter.ts delete mode 100644 developer/src/kmc-convert/src/kmc-convert-convert/kmn-to-ldml-converter.ts delete mode 100644 developer/src/kmc-convert/src/kmc-convert-convert/ldml-to-kmn-converter.ts delete mode 100644 developer/src/kmc-convert/src/kmc-convert-convert/msklc-to-kmn-converter.ts delete mode 100644 developer/src/kmc-convert/src/kmc-convert-convert/msklc-to-ldml-converter.ts delete mode 100644 developer/src/kmc-convert/src/kmc-convert-read/inkey-file-reader.ts delete mode 100644 developer/src/kmc-convert/src/kmc-convert-read/kmn-file-reader.ts delete mode 100644 developer/src/kmc-convert/src/kmc-convert-read/ldml-file-reader.ts delete mode 100644 developer/src/kmc-convert/src/kmc-convert-read/msklc-file-reader.ts delete mode 100644 developer/src/kmc-convert/src/kmc-convert-write/ldml-file-writer.ts rename developer/src/kmc-convert/test/data/{tests-xkb-kmn => tests-keylayout-kmn}/keylayout.dtd (100%) delete mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test copy.keylayout delete mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_C0.keylayout delete mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_C0_C1_C2_C3.keylayout delete mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_C1.keylayout delete mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_C2.keylayout delete mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_C2_several.keylayout delete mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_C3.keylayout delete mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_C3_several.keylayout delete mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_ExtraWarning.keylayout delete mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_ambiguous_keys.keylayout delete mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_characters.keylayout delete mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_differentAmountOfKeysInBehaviours.keylayout delete mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_differentEncodings.keylayout delete mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_duplicate_keys.keylayout delete mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_duplicate_missing_keycode.keylayout delete mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_duplicate_missing_keys.keylayout delete mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_maxKeyCode.keylayout delete mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_messages.keylayout delete mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_messages_controlCharacter.keylayout delete mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_messages_superior_C2.keylayout delete mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_messages_superior_C3.keylayout delete mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_modifier.keylayout delete mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_modifierNoCaps.keylayout delete mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_moreKeyMapThanKeyMapselectAndJisERROR.keylayout delete mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_moreKeyMapThanKeyMapselectERROR.keylayout delete mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_moreKeymapSelectThanKeymapERROR.keylayout delete mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_nr_elements.keylayout delete mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_onlyOneKeymap.keylayout delete mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_undefinedAction.keylayout delete mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_unsupportedCharacters.keylayout create mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/de_simple diff --git a/common/web/types/src/consts/virtual-key-constants.ts b/common/web/types/src/consts/virtual-key-constants.ts index 7b083241bdc..ca1719f280a 100644 --- a/common/web/types/src/consts/virtual-key-constants.ts +++ b/common/web/types/src/consts/virtual-key-constants.ts @@ -39,7 +39,7 @@ export const USVirtualKeyCodes = { K_7:55, K_8:56, K_9:57, - K_A:65, + K_A:65, /*34.*/ K_B:66, K_C:67, K_D:68, diff --git a/developer/src/kmc-convert/src/kmc-convert-convert/inkey-to-kmn-converter.ts b/developer/src/kmc-convert/src/kmc-convert-convert/inkey-to-kmn-converter.ts deleted file mode 100644 index 5e1a8c0d61b..00000000000 --- a/developer/src/kmc-convert/src/kmc-convert-convert/inkey-to-kmn-converter.ts +++ /dev/null @@ -1,3 +0,0 @@ - - -// tbd. diff --git a/developer/src/kmc-convert/src/kmc-convert-convert/inkey-to-ldml-converter.ts b/developer/src/kmc-convert/src/kmc-convert-convert/inkey-to-ldml-converter.ts deleted file mode 100644 index 5e1a8c0d61b..00000000000 --- a/developer/src/kmc-convert/src/kmc-convert-convert/inkey-to-ldml-converter.ts +++ /dev/null @@ -1,3 +0,0 @@ - - -// tbd. diff --git a/developer/src/kmc-convert/src/kmc-convert-convert/keylayout-to-ldml-converter.ts b/developer/src/kmc-convert/src/kmc-convert-convert/keylayout-to-ldml-converter.ts deleted file mode 100644 index 5e1a8c0d61b..00000000000 --- a/developer/src/kmc-convert/src/kmc-convert-convert/keylayout-to-ldml-converter.ts +++ /dev/null @@ -1,3 +0,0 @@ - - -// tbd. diff --git a/developer/src/kmc-convert/src/kmc-convert-convert/kmn-to-ldml-converter.ts b/developer/src/kmc-convert/src/kmc-convert-convert/kmn-to-ldml-converter.ts deleted file mode 100644 index 5e1a8c0d61b..00000000000 --- a/developer/src/kmc-convert/src/kmc-convert-convert/kmn-to-ldml-converter.ts +++ /dev/null @@ -1,3 +0,0 @@ - - -// tbd. diff --git a/developer/src/kmc-convert/src/kmc-convert-convert/ldml-to-kmn-converter.ts b/developer/src/kmc-convert/src/kmc-convert-convert/ldml-to-kmn-converter.ts deleted file mode 100644 index 5e1a8c0d61b..00000000000 --- a/developer/src/kmc-convert/src/kmc-convert-convert/ldml-to-kmn-converter.ts +++ /dev/null @@ -1,3 +0,0 @@ - - -// tbd. diff --git a/developer/src/kmc-convert/src/kmc-convert-convert/msklc-to-kmn-converter.ts b/developer/src/kmc-convert/src/kmc-convert-convert/msklc-to-kmn-converter.ts deleted file mode 100644 index 5e1a8c0d61b..00000000000 --- a/developer/src/kmc-convert/src/kmc-convert-convert/msklc-to-kmn-converter.ts +++ /dev/null @@ -1,3 +0,0 @@ - - -// tbd. diff --git a/developer/src/kmc-convert/src/kmc-convert-convert/msklc-to-ldml-converter.ts b/developer/src/kmc-convert/src/kmc-convert-convert/msklc-to-ldml-converter.ts deleted file mode 100644 index 5e1a8c0d61b..00000000000 --- a/developer/src/kmc-convert/src/kmc-convert-convert/msklc-to-ldml-converter.ts +++ /dev/null @@ -1,3 +0,0 @@ - - -// tbd. diff --git a/developer/src/kmc-convert/src/kmc-convert-read/inkey-file-reader.ts b/developer/src/kmc-convert/src/kmc-convert-read/inkey-file-reader.ts deleted file mode 100644 index 5e1a8c0d61b..00000000000 --- a/developer/src/kmc-convert/src/kmc-convert-read/inkey-file-reader.ts +++ /dev/null @@ -1,3 +0,0 @@ - - -// tbd. diff --git a/developer/src/kmc-convert/src/kmc-convert-read/kmn-file-reader.ts b/developer/src/kmc-convert/src/kmc-convert-read/kmn-file-reader.ts deleted file mode 100644 index 5e1a8c0d61b..00000000000 --- a/developer/src/kmc-convert/src/kmc-convert-read/kmn-file-reader.ts +++ /dev/null @@ -1,3 +0,0 @@ - - -// tbd. diff --git a/developer/src/kmc-convert/src/kmc-convert-read/ldml-file-reader.ts b/developer/src/kmc-convert/src/kmc-convert-read/ldml-file-reader.ts deleted file mode 100644 index 5e1a8c0d61b..00000000000 --- a/developer/src/kmc-convert/src/kmc-convert-read/ldml-file-reader.ts +++ /dev/null @@ -1,3 +0,0 @@ - - -// tbd. diff --git a/developer/src/kmc-convert/src/kmc-convert-read/msklc-file-reader.ts b/developer/src/kmc-convert/src/kmc-convert-read/msklc-file-reader.ts deleted file mode 100644 index c27f478b68e..00000000000 --- a/developer/src/kmc-convert/src/kmc-convert-read/msklc-file-reader.ts +++ /dev/null @@ -1,4 +0,0 @@ - - -// tbd. - diff --git a/developer/src/kmc-convert/src/kmc-convert-write/ldml-file-writer.ts b/developer/src/kmc-convert/src/kmc-convert-write/ldml-file-writer.ts deleted file mode 100644 index 5e1a8c0d61b..00000000000 --- a/developer/src/kmc-convert/src/kmc-convert-write/ldml-file-writer.ts +++ /dev/null @@ -1,3 +0,0 @@ - - -// tbd. diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/keylayout.dtd b/developer/src/kmc-convert/test/data/tests-keylayout-kmn/keylayout.dtd similarity index 100% rename from developer/src/kmc-convert/test/data/tests-xkb-kmn/keylayout.dtd rename to developer/src/kmc-convert/test/data/tests-keylayout-kmn/keylayout.dtd diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test copy.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test copy.keylayout deleted file mode 100644 index 76fd91b4db6..00000000000 --- a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test copy.keylayout +++ /dev/null @@ -1,596 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_C0.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_C0.keylayout deleted file mode 100644 index d8c49ea62ae..00000000000 --- a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_C0.keylayout +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_C0_C1_C2_C3.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_C0_C1_C2_C3.keylayout deleted file mode 100644 index f1f3ebab1e5..00000000000 --- a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_C0_C1_C2_C3.keylayout +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_C1.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_C1.keylayout deleted file mode 100644 index e785e58ca18..00000000000 --- a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_C1.keylayout +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_C2.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_C2.keylayout deleted file mode 100644 index aa6b60997bc..00000000000 --- a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_C2.keylayout +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_C2_several.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_C2_several.keylayout deleted file mode 100644 index d51369c934c..00000000000 --- a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_C2_several.keylayout +++ /dev/null @@ -1,73 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_C3.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_C3.keylayout deleted file mode 100644 index 6275a230bbf..00000000000 --- a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_C3.keylayout +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_C3_several.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_C3_several.keylayout deleted file mode 100644 index 7fff380f2cc..00000000000 --- a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_C3_several.keylayout +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_ExtraWarning.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_ExtraWarning.keylayout deleted file mode 100644 index 0d36b2a5fea..00000000000 --- a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_ExtraWarning.keylayout +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_ambiguous_keys.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_ambiguous_keys.keylayout deleted file mode 100644 index 97778e876ee..00000000000 --- a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_ambiguous_keys.keylayout +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_characters.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_characters.keylayout deleted file mode 100644 index 2aae8f1bb46..00000000000 --- a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_characters.keylayout +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_differentAmountOfKeysInBehaviours.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_differentAmountOfKeysInBehaviours.keylayout deleted file mode 100644 index 4b770866cd6..00000000000 --- a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_differentAmountOfKeysInBehaviours.keylayout +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_differentEncodings.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_differentEncodings.keylayout deleted file mode 100644 index c526f8c2af8..00000000000 --- a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_differentEncodings.keylayout +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_duplicate_keys.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_duplicate_keys.keylayout deleted file mode 100644 index a5cb09069bf..00000000000 --- a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_duplicate_keys.keylayout +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_duplicate_missing_keycode.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_duplicate_missing_keycode.keylayout deleted file mode 100644 index 39da3300f4f..00000000000 --- a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_duplicate_missing_keycode.keylayout +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_duplicate_missing_keys.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_duplicate_missing_keys.keylayout deleted file mode 100644 index b3670561432..00000000000 --- a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_duplicate_missing_keys.keylayout +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_maxKeyCode.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_maxKeyCode.keylayout deleted file mode 100644 index a5f9e178b99..00000000000 --- a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_maxKeyCode.keylayout +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_messages.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_messages.keylayout deleted file mode 100644 index 5d8d1b86820..00000000000 --- a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_messages.keylayout +++ /dev/null @@ -1,80 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_messages_controlCharacter.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_messages_controlCharacter.keylayout deleted file mode 100644 index f97abb984d2..00000000000 --- a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_messages_controlCharacter.keylayout +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_messages_superior_C2.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_messages_superior_C2.keylayout deleted file mode 100644 index 3416bb5e8ff..00000000000 --- a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_messages_superior_C2.keylayout +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_messages_superior_C3.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_messages_superior_C3.keylayout deleted file mode 100644 index f95afe40db5..00000000000 --- a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_messages_superior_C3.keylayout +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_modifier.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_modifier.keylayout deleted file mode 100644 index 67ccf4db63e..00000000000 --- a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_modifier.keylayout +++ /dev/null @@ -1,103 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_modifierNoCaps.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_modifierNoCaps.keylayout deleted file mode 100644 index 9656413d7e6..00000000000 --- a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_modifierNoCaps.keylayout +++ /dev/null @@ -1,108 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_moreKeyMapThanKeyMapselectAndJisERROR.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_moreKeyMapThanKeyMapselectAndJisERROR.keylayout deleted file mode 100644 index 13be153d756..00000000000 --- a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_moreKeyMapThanKeyMapselectAndJisERROR.keylayout +++ /dev/null @@ -1,83 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_moreKeyMapThanKeyMapselectERROR.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_moreKeyMapThanKeyMapselectERROR.keylayout deleted file mode 100644 index 3bd9b5ba491..00000000000 --- a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_moreKeyMapThanKeyMapselectERROR.keylayout +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_moreKeymapSelectThanKeymapERROR.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_moreKeymapSelectThanKeymapERROR.keylayout deleted file mode 100644 index 25d178237cb..00000000000 --- a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_moreKeymapSelectThanKeymapERROR.keylayout +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_nr_elements.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_nr_elements.keylayout deleted file mode 100644 index 7a32f4b3c25..00000000000 --- a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_nr_elements.keylayout +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_onlyOneKeymap.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_onlyOneKeymap.keylayout deleted file mode 100644 index 8f173994576..00000000000 --- a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_onlyOneKeymap.keylayout +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_undefinedAction.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_undefinedAction.keylayout deleted file mode 100644 index 4e6f0ce8023..00000000000 --- a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_undefinedAction.keylayout +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_unsupportedCharacters.keylayout b/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_unsupportedCharacters.keylayout deleted file mode 100644 index d393b332ee6..00000000000 --- a/developer/src/kmc-convert/test/data/tests-xkb-kmn/Test_unsupportedCharacters.keylayout +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/de_simple b/developer/src/kmc-convert/test/data/tests-xkb-kmn/de_simple new file mode 100644 index 00000000000..61a0b63eb74 --- /dev/null +++ b/developer/src/kmc-convert/test/data/tests-xkb-kmn/de_simple @@ -0,0 +1,60 @@ +// Common Latin alphabet layout +// 0x1001E9E on key key , key , key added for testing purposes by SAB + +default partial +xkb_symbols "basic" { + + key { [ 1, exclam, onesuperior, exclamdown ] }; + key { [ 2, quotedbl, twosuperior, oneeighth ] }; + key { [ 3, section, threesuperior, sterling ] }; + key { [ 4, dollar, onequarter, currency ] }; + key { [ 5, percent, onehalf, threeeighths ] }; + key { [ 6, asciicircum, threequarters, fiveeighths] }; + key { [ 7, ampersand, braceleft, seveneighths ] }; + key { [ 8, asterisk, bracketleft, trademark ] }; + key { [ 9, parenleft, bracketright, plusminus ] }; + key { [ 0, parenright, braceright, degree ] }; + key { [ ssharp, question, backslash, 0x1001E9E ] }; + key { [ NoSymbol, NoSymbol, NoSymbol, 0x1001E9E] }; + + + key { [ q, Q, at, Greek_OMEGA ] }; + key { [ w, W, lstroke, Lstroke ] }; + key { [ e, E, EuroSign, EuroSign ] }; + key { [ r, R, paragraph, registered ] }; + key { [ t, T, tslash, Tslash ] }; + key { [ z, Z, leftarrow, yen ] }; + key { [ u, U, downarrow, uparrow ] }; + key { [ i, I, rightarrow, idotless ] }; + key { [ o, O, oslash, Ooblique ] }; + key { [ p, P, thorn, THORN ] }; + key { [udiaeresis, Udiaeresis, NoSymbol, NoSymbol ] }; + key { [ plus, asterisk, asciitilde, macron ] }; + + key { [ a, A, ae, AE ] }; + key { [ s, S, ssharp, section ] }; + key { [ d, D, eth, ETH ] }; + key { [ f, F, dstroke, ordfeminine ] }; + key { [ g, G, eng, ENG ] }; + key { [ h, H, hstroke, Hstroke ] }; + key { [ j, J, NoSymbol, NoSymbol ] }; + key { [ k, K, kra, ampersand ] }; + key { [ l, L, lstroke, Lstroke ] }; + key { [odiaeresis, Odiaeresis, NoSymbol, 0x1001E9E] }; + key { [adiaeresis, Adiaeresis, NoSymbol, NoSymbol ] }; + key { [NoSymbol, degree, U2032, U2033 ] }; + + key { [numbersign, apostrophe,rightsinglequotemark,NoSymbol ] }; + key { [ y, Y, guillemotright, U203A ] }; + key { [ x, X, guillemotleft, U2039 ] }; + key { [ c, C, cent, copyright ] }; + key { [ v, V, doublelowquotemark, singlelowquotemark ] }; + key { [ b, B, leftdoublequotemark, leftsinglequotemark ] }; + key { [ n, N, rightdoublequotemark, rightsinglequotemark] }; + key { [ m, M, mu, masculine ] }; + key { [ comma, semicolon, periodcentered, multiply ] }; + key { [ period, colon, U2026, division ] }; + key { [ minus, underscore, endash, emdash ] }; + key { [ less, greater, bar, 0x1001E9E ] }; + +}; From 8bac6da7abcc8f9cb9878e065410f280b5ca9622 Mon Sep 17 00:00:00 2001 From: Sabine Date: Fri, 8 May 2026 19:18:02 +0200 Subject: [PATCH 246/251] feat(developer): add/edit tests --- .../kmc-convert/test/data/tests-xkb-kmn/de | 1203 +++++++++++++++++ .../test/data/tests-xkb-kmn/de_simple | 2 +- .../keylayout-to-kmn-converter.tests.ts | 3 +- .../xkb-to-kmn-converter.tests.ts | 42 +- .../kmc-convert-read/kmn-file-reader.tests.ts | 4 +- .../kmc-convert-read/xkb-file-reader.tests.ts | 6 +- .../kmn-file-writer.tests.ts | 43 +- 7 files changed, 1233 insertions(+), 70 deletions(-) create mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/de diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/de b/developer/src/kmc-convert/test/data/tests-xkb-kmn/de new file mode 100644 index 00000000000..496514f8bda --- /dev/null +++ b/developer/src/kmc-convert/test/data/tests-xkb-kmn/de @@ -0,0 +1,1203 @@ +default +xkb_symbols "basic" { + + include "latin(type4)" + + name[Group1]="German"; + + key { [ 2, quotedbl, twosuperior, oneeighth ] }; + key { [ 3, section, threesuperior, sterling ] }; + key { [ 4, dollar, onequarter, currency ] }; + + key {type[Group1]="FOUR_LEVEL_PLUS_LOCK", symbols[Group1]= + [ssharp, question, backslash, questiondown, 0x1001E9E ]}; + key { [dead_acute, dead_grave, dead_cedilla, dead_ogonek ] }; + + key { [ e, E, EuroSign, EuroSign ] }; + key { [ z, Z, leftarrow, yen ] }; + key { [udiaeresis, Udiaeresis, dead_diaeresis, dead_abovering ] }; + key { [ plus, asterisk, asciitilde, macron ] }; + + key { [ s, S, U017F, U1E9E ] }; + key { [ j, J, dead_belowdot, dead_abovedot ] }; + key { [odiaeresis, Odiaeresis, dead_doubleacute, dead_belowdot ] }; + key { [adiaeresis, Adiaeresis, dead_circumflex, dead_caron ] }; + key { [dead_circumflex, degree, U2032, U2033 ] }; + + key { [numbersign, apostrophe, rightsinglequotemark, dead_breve ] }; + key { [ y, Y, guillemotright, U203A ] }; + key { [ x, X, guillemotleft, U2039 ] }; + key { [ v, V, doublelowquotemark, singlelowquotemark ] }; + key { [ b, B, leftdoublequotemark, leftsinglequotemark ] }; + key { [ n, N, rightdoublequotemark, rightsinglequotemark ] }; + key { [ comma, semicolon, periodcentered, multiply ] }; + key { [ period, colon, U2026, division ] }; + key { [ minus, underscore, endash, emdash ] }; + key { [ less, greater, bar, dead_belowmacron ] }; + + include "kpdl(comma)" +ẞß + include "level3(ralt_switch)" +}; + +partial alphanumeric_keys +xkb_symbols "deadtilde" { + // previous standard German layout with tilde as dead key + + include "de(basic)" + name[Group1]="German (dead tilde)"; + + key { [ plus, asterisk, dead_tilde, dead_macron ] }; +}; + +partial alphanumeric_keys +xkb_symbols "nodeadkeys" { + + // modify the basic German layout to not have any dead keys + + include "de(basic)" + name[Group1]="German (no dead keys)"; + + key { [asciicircum, degree, notsign, notsign ] }; + key { [ acute, grave, cedilla, cedilla ] }; + key { [ udiaeresis, Udiaeresis, diaeresis, diaeresis ] }; + key { [ plus, asterisk, asciitilde, macron ] }; + key { [ odiaeresis, Odiaeresis, doubleacute, doubleacute ] }; + key { [ adiaeresis, Adiaeresis, asciicircum, asciicircum ] }; + key { [ numbersign, apostrophe, rightsinglequotemark, grave ] }; +}; + +partial alphanumeric_keys +xkb_symbols "deadgraveacute" { + // modify the basic German layout to have only acute and grave + // as dead keys (tilde and circumflex are needed as spacing characters + // in many programming languages) + + include "de(basic)" + name[Group1]="German (dead grave acute)"; + + key { [asciicircum, degree, notsign, notsign ] }; + key { [ plus, asterisk, asciitilde, dead_macron ] }; + key { [ numbersign, apostrophe, rightsinglequotemark, grave ] }; +}; + +partial alphanumeric_keys +xkb_symbols "deadacute" { + // modify the basic German layout to have only acute as + // dead keys (ASCII grave, tilde and circumflex are needed as + // spacing characters in many programming languages and text formatters) + + include "de(deadgraveacute)" + + name[Group1]="German (dead acute)"; + + key { [dead_acute, grave, dead_cedilla, dead_ogonek ] }; + key { [numbersign, apostrophe, rightsinglequotemark, dead_grave ] }; +}; + +partial alphanumeric_keys +xkb_symbols "e1" { + // German extended layout E1 based on DIN 2137-1:2020-11 + // Designed for a 105-key keyboard + // https://de.wikipedia.org/wiki/Tastaturbelegung + + name[Group1]="German (E1)"; + + // first row + key.type[Group1] = "EIGHT_LEVEL"; + key { [ dead_circumflex, degree, multiply, NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol ] }; + key { [ 1, exclam, rightsinglequotemark, NoSymbol, onequarter, U25CA, NoSymbol, NoSymbol ] }; + key { [ 2, quotedbl, twosuperior, NoSymbol, onehalf, U00A6, NoSymbol, NoSymbol ] }; + key { [ 3, section, threesuperior, NoSymbol, threequarters, U00B6, NoSymbol, NoSymbol ] }; + key { [ 4, dollar, emdash, NoSymbol, currency, U2133, NoSymbol, NoSymbol ] }; + key { [ 5, percent, exclamdown, NoSymbol, U2030, U20B0, NoSymbol, NoSymbol ] }; + key { [ 6, ampersand, questiondown, NoSymbol, U2044, U204A, NoSymbol, NoSymbol ] }; + key { [ 7, slash, braceleft, NoSymbol, U2300, U2116, NoSymbol, NoSymbol ] }; + key { [ 8, parenleft, bracketleft, NoSymbol, U27E8, U27EA, NoSymbol, NoSymbol ] }; + key { [ 9, parenright, bracketright, NoSymbol, U27E9, U27EB, NoSymbol, NoSymbol ] }; + key { [ 0, equal, braceright, NoSymbol, division, U2205, NoSymbol, NoSymbol ] }; + key { [ ssharp, question, backslash, NoSymbol, notequal, U00AC, NoSymbol, NoSymbol ] }; + key { [ dead_acute, dead_grave, dead_abovedot, NoSymbol, sterling, U035C, NoSymbol, NoSymbol ] }; + + // second row + key.type[Group1] = "EIGHT_LEVEL_ALPHABETIC"; + key { [ q, Q, at, NoSymbol, masculine, U2642, NoSymbol, NoSymbol ] }; + key { [ w, W, dead_macron, NoSymbol, ordfeminine, U2640, NoSymbol, NoSymbol ] }; + key { [ e, E, EuroSign, NoSymbol, schwa, SCHWA, NoSymbol, NoSymbol ] }; + key { [ r, R, dead_doubleacute, NoSymbol, trademark, registered, NoSymbol, NoSymbol ] }; + key { [ t, T, dead_caron, NoSymbol, thorn, THORN, NoSymbol, NoSymbol ] }; + key { [ z, Z, dead_diaeresis, NoSymbol, U0292, U01B7, NoSymbol, NoSymbol ] }; + key { [ u, U, dead_breve, NoSymbol, rightarrow, leftarrow, NoSymbol, NoSymbol ] }; + key { [ i, I, dead_tilde, NoSymbol, idotless, U26A5, NoSymbol, NoSymbol ] }; + key { [ o, O, dead_abovering, NoSymbol, oslash, Oslash, NoSymbol, NoSymbol ] }; + key { [ p, P, dead_hook, NoSymbol, downarrow, uparrow, NoSymbol, NoSymbol ] }; + key { [ udiaeresis, Udiaeresis, dead_horn, NoSymbol, U2198, U2197, NoSymbol, NoSymbol ] }; + key.type[Group1] = "EIGHT_LEVEL"; + key { [ plus, asterisk, asciitilde, NoSymbol, plusminus, U2052, NoSymbol, NoSymbol ] }; + + // third row + key.type[Group1] = "EIGHT_LEVEL_ALPHABETIC"; + // Per DIN 2137-1:2018-12, p. 11-12, (Alt)Gr+a can either invoke + // a selection possibility for emojis or special characters, or + // output the U+263A smiley. + key { [ a, A, Multi_key, NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol ] }; + key { [ s, S, seconds, NoSymbol, U017F, U2211, NoSymbol, NoSymbol ] }; + key { [ d, D, minutes, NoSymbol, eth, ETH, NoSymbol, NoSymbol ] }; + key { [ f, F, ISO_Level5_Latch, NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol ] }; + key { [ g, G, U1E9E, NoSymbol, U02BF, U261B, NoSymbol, NoSymbol ] }; + key { [ h, H, dead_belowmacron, NoSymbol, U02BE, U261A, NoSymbol, NoSymbol ] }; + key { [ j, J, dead_cedilla, NoSymbol, U02B9, U02BA, NoSymbol, NoSymbol ] }; + key { [ k, K, dead_belowcomma, NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol ] }; + key { [ l, L, dead_ogonek, NoSymbol, lstroke, Lstroke, NoSymbol, NoSymbol ] }; + key { [ odiaeresis, Odiaeresis, dead_belowdot, NoSymbol, oe, OE, NoSymbol, NoSymbol ] }; + key { [ adiaeresis, Adiaeresis, dead_stroke, NoSymbol, ae, AE, NoSymbol, NoSymbol ] }; + key.type[Group1] = "EIGHT_LEVEL"; + key { [ numbersign, apostrophe, U2212, NoSymbol, U2020, U2021, NoSymbol, NoSymbol ] }; + + // fourth row + key.type[Group1] = "EIGHT_LEVEL_ALPHABETIC"; + key { [ y, Y, U203A, NoSymbol, U2423, U23D1, NoSymbol, NoSymbol ] }; + key { [ x, X, guillemotright, NoSymbol, doublelowquotemark, singlelowquotemark, NoSymbol, NoSymbol ] }; + key { [ c, C, U202F, NoSymbol, cent, copyright, NoSymbol, NoSymbol ] }; + key { [ v, V, guillemotleft, NoSymbol, leftdoublequotemark, leftsinglequotemark, NoSymbol, NoSymbol ] }; + key { [ b, B, U2039, NoSymbol, rightdoublequotemark, rightsinglequotemark, NoSymbol, NoSymbol ] }; + key { [ n, N, endash, NoSymbol, eng, ENG, NoSymbol, NoSymbol ] }; + // Per DIN 2137-1:2018-12, p. 12, U+2217 should be replaced by the + // 'middle asterisk' character as soon as it has been added to + // Unicode (see Unicode proposal L2/17-152). + key { [ m, M, mu, NoSymbol, U200C, U2217, NoSymbol, NoSymbol ] }; + key.type[Group1] = "EIGHT_LEVEL"; + key { [ comma, semicolon, U2011, NoSymbol, U02BB, U2661, NoSymbol, NoSymbol ] }; + key { [ period, colon, periodcentered, NoSymbol, ellipsis, U2713, NoSymbol, NoSymbol ] }; + key { [ minus, underscore, hyphen, NoSymbol, U2022, U25E6, NoSymbol, NoSymbol ] }; + + // fifth row + key.type[Group1] = "EIGHT_LEVEL"; + key { [ space, space, nobreakspace, NoSymbol, U200A, U2009, NoSymbol, NoSymbol ] }; + key.type[Group1] = "ONE_LEVEL"; + key { [ Shift_L ] }; + key { [ Shift_R ] }; + key { [ ISO_Level3_Shift ] }; + + // key exists only on the 105-key keyboard + key.type[Group1] = "EIGHT_LEVEL"; + key { [ less, greater, bar, NoSymbol, lessthanequal, greaterthanequal, NoSymbol, NoSymbol ] }; + + include "kpdl(comma)" + include "level3(modifier_mapping)" + include "level5(modifier_mapping)" + }; + +partial alphanumeric_keys +xkb_symbols "e2" { + // German extended layout E2 based on DIN 2137-1:2020-11 + // Designed for a 104-key keyboard + // https://de.wikipedia.org/wiki/Tastaturbelegung + + include "de(e1)" + name[Group1]="German (E2)"; + + // one key less: assign bar, less and greater to other keys + key.type[Group1] = "EIGHT_LEVEL"; + key { [ dead_circumflex, degree, bar, NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol ] }; + key { [ 2, quotedbl, less, NoSymbol, onehalf, U00A6, NoSymbol, NoSymbol ] }; + key { [ 3, section, greater, NoSymbol, threequarters, U00B6, NoSymbol, NoSymbol ] }; + key { [ plus, asterisk, asciitilde, NoSymbol, multiply, U2052, NoSymbol, NoSymbol ] }; + + // if E2 is used on a 105-key keyboard + key.type[Group1] = "ONE_LEVEL"; + key { [ ISO_Level3_Shift ] }; +}; + +partial alphanumeric_keys +xkb_symbols "T3" { + // German extended layout T3 based on DIN 2137-1:2012-06 + // Now obsolete, use de(e1) or de(e2) + + name[Group1]="German (T3)"; + + key.type[Group1] = "EIGHT_LEVEL"; + key { [ dead_circumflex, degree, multiply, NoSymbol, U204A, hyphen, bar, NoSymbol ] }; + key { [ 1, exclam, rightsinglequotemark, NoSymbol, onesuperior, exclamdown, U02B9, NoSymbol ] }; + key { [ 2, quotedbl, twosuperior, NoSymbol, twosuperior, currency, U02BA, NoSymbol ] }; + key { [ 3, section, threesuperior, NoSymbol, threesuperior, sterling, U02BF, NoSymbol ] }; + key { [ 4, dollar, emdash, NoSymbol, onequarter, 0x20AC, U02BE, NoSymbol ] }; + key { [ 5, percent, exclamdown, NoSymbol, onehalf, uparrow, U02C1, NoSymbol ] }; + key { [ 6, ampersand, questiondown, NoSymbol, threequarters, downarrow, U02C0, NoSymbol ] }; + key { [ 7, slash, braceleft, NoSymbol, oneeighth, leftarrow, braceleft, NoSymbol ] }; + key { [ 8, parenleft, bracketleft, NoSymbol, threeeighths, rightarrow, braceright, NoSymbol ] }; + key { [ 9, parenright, bracketright, NoSymbol, fiveeighths, plusminus, bracketleft, NoSymbol ] }; + key { [ 0, equal, braceright, NoSymbol, seveneighths, trademark, bracketright, NoSymbol ] }; + key { [ ssharp, question, backslash, NoSymbol, backslash, questiondown, U02BB, NoSymbol ] }; + key { [ dead_acute, dead_grave, dead_abovedot, NoSymbol, dead_cedilla, dead_ogonek, notsign, NoSymbol ] }; + + key.type[Group1] = "EIGHT_LEVEL_ALPHABETIC"; + key { [ q, Q, at, NoSymbol, U0242, U0241, U030D, NoSymbol ] }; + key { [ w, W, dead_caron, NoSymbol, U02B7, U2126, dead_abovedot, NoSymbol ] }; + key { [ e, E, EuroSign, NoSymbol, oe, OE, dead_breve, NoSymbol ] }; + key { [ r, R, dead_diaeresis, NoSymbol, paragraph, registered, dead_circumflex, NoSymbol ] }; + key { [ t, T, dead_macron, NoSymbol, UA78C, UA78B, dead_diaeresis, NoSymbol ] }; + key { [ z, Z, dead_doubleacute, NoSymbol, U027C, yen, dead_invertedbreve, NoSymbol ] }; + key { [ u, U, dead_breve, NoSymbol, U0223, U0222, dead_caron, NoSymbol ] }; + key { [ i, I, dead_tilde, NoSymbol, idotless, U214D, dead_abovecomma, NoSymbol ] }; + key { [ o, O, dead_abovering, NoSymbol, oslash, Oslash, dead_horn, NoSymbol ] }; + key { [ p, P, dead_hook, NoSymbol, thorn, THORN, dead_hook, NoSymbol ] }; + key { [ udiaeresis, Udiaeresis, dead_horn, NoSymbol, U017F, dead_abovering, dead_grave, NoSymbol ] }; + key.type[Group1] = "EIGHT_LEVEL"; + key { [ plus, asterisk, asciitilde, NoSymbol, dead_tilde, dead_macron, at, NoSymbol ] }; + + key.type[Group1] = "ONE_LEVEL"; + key { [ Caps_Lock ] }; + key.type[Group1] = "EIGHT_LEVEL_ALPHABETIC"; + key { [ a, A, lessthanequal, NoSymbol, ae, AE, U0329, NoSymbol ] }; + key { [ s, S, greaterthanequal, NoSymbol, ssharp, section, dead_belowdot, NoSymbol ] }; + key { [ d, D, U2300, NoSymbol, eth, ETH, dead_belowbreve, NoSymbol ] }; + key { [ f, F, minutes, NoSymbol, U0294, ordfeminine, dead_belowcircumflex, NoSymbol ] }; + key { [ g, G, seconds, NoSymbol, eng, ENG, dead_belowmacron, NoSymbol ] }; + key { [ h, H, U1E9E, NoSymbol, U0272, U019D, U0332, NoSymbol ] }; + key { [ j, J, dead_cedilla, NoSymbol, U0133, U0132, dead_belowring, NoSymbol ] }; + key { [ k, K, dead_belowcomma, NoSymbol, kra, dead_belowcomma, dead_stroke, NoSymbol ] }; + key { [ l, L, dead_ogonek, NoSymbol, lstroke, Lstroke, U0338, NoSymbol ] }; + key { [ odiaeresis, Odiaeresis, dead_belowdot, NoSymbol, dead_acute, dead_doubleacute, degree, NoSymbol ] }; + key { [ adiaeresis, Adiaeresis, dead_stroke, NoSymbol, U019B, U1E9E, minutes, NoSymbol ] }; + key.type[Group1] = "EIGHT_LEVEL"; + key { [ numbersign, apostrophe, registered, NoSymbol, schwa, SCHWA, seconds, NoSymbol ] }; + + key { [ less, greater, bar, NoSymbol, U0149, brokenbar, U266A, NoSymbol ] }; + key.type[Group1] = "EIGHT_LEVEL_ALPHABETIC"; + key { [ y, Y, U203A, NoSymbol, U0292, U01B7, guillemotleft, NoSymbol ] }; + key { [ x, X, guillemotright, NoSymbol, doublelowquotemark, singlelowquotemark, guillemotright, NoSymbol ] }; + key { [ c, C, copyright, NoSymbol, cent, copyright, Greek_horizbar, NoSymbol ] }; + key { [ v, V, guillemotleft, NoSymbol, leftdoublequotemark, leftsinglequotemark, U2039, NoSymbol ] }; + key { [ b, B, U2039, NoSymbol, rightdoublequotemark, rightsinglequotemark, U203A, NoSymbol ] }; + key { [ n, N, endash, NoSymbol, U019E, U0220, endash, NoSymbol ] }; + key { [ m, M, mu, NoSymbol, mu, masculine, emdash, NoSymbol ] }; + key.type[Group1] = "EIGHT_LEVEL"; + key { [ comma, semicolon, U02BB, NoSymbol, ellipsis, multiply, dollar, NoSymbol ] }; + key { [ period, colon, U200C, NoSymbol, periodcentered, division, numbersign, NoSymbol ] }; + key { [ minus, underscore, hyphen, NoSymbol, U0140, U013F, U2011, NoSymbol ] }; + + key { [ space, space, nobreakspace, NoSymbol, U202F, U200C, nobreakspace, NoSymbol ] }; + + include "kpdl(comma)" + + include "level5(modifier_mapping)" + include "level3(modifier_mapping)" + key.type[Group1] = "THREE_LEVEL"; + key { [ Shift_L, Shift_L, ISO_Level5_Latch ] }; + key { [ Shift_R, Shift_R, ISO_Level5_Latch ] }; + key { [ ISO_Level3_Shift, ISO_Level5_Latch, ISO_Level5_Latch ] }; + }; + +partial alphanumeric_keys +xkb_symbols "ro" { + // Adds Romanian-specific letters to the German basic layout. + // Romanian symbols are accessible by combining and + // 'a', 's', 't', 'i', 'ä (ä)' (+ for capital letters). + + include "de(basic)" + + name[Group1]="Romanian (Germany)"; + + key { [ t, T, U021b, U021a ] }; + key { [ i, I, icircumflex, Icircumflex ] }; + key { [ a, A, acircumflex, Acircumflex ] }; + key { [ s, S, U0219, U0218 ] }; + key { [ adiaeresis, Adiaeresis, abreve, Abreve ] }; +}; + +partial alphanumeric_keys +xkb_symbols "ro_nodeadkeys" { + // Adds Romanian-specific letters to the German nodeadkeys layout. + // Read the comment for de_ro ! + + include "de(nodeadkeys)" + name[Group1]="Romanian (Germany, no dead keys)"; + + key { [ t, T, U021b, U021a ] }; + key { [ i, I, icircumflex, Icircumflex ] }; + key { [ a, A, acircumflex, Acircumflex ] }; + key { [ s, S, U0219, U0218 ] }; + key { [ adiaeresis, Adiaeresis, abreve, Abreve ] }; +}; + +// German Dvorak keymap by Thorsten Staerk (www.staerk.de/thorsten) +// Have acute and grave as dead keys, tilde and circumflex alive as they are needed +// in many programming languages. +// to use this keymap, use a 105-key-keyboard and the command setxkbmap -model pc105 -layout dvorak -variant de +// source: http://www-lehre.informatik.uni-osnabrueck.de/~rfreund/dvorak.php +partial alphanumeric_keys +xkb_symbols "dvorak" { + include "us(dvorak)" + + name[Group1]="German (Dvorak)"; + + key { [ asciicircum, degree ] }; + + key { [ 1, exclam, onesuperior ] }; + key { [ 2, quotedbl, twosuperior ] }; + key { [ 3, section, threesuperior ] }; + key { [ 4, dollar, bar ] }; + key { [ 5, percent, bar ] }; + key { [ 6, ampersand, brokenbar ] }; + key { [ 7, slash, braceleft ] }; + key { [ 8, parenleft, bracketleft ] }; + key { [ 9, parenright, bracketright ] }; + key { [ 0, equal, braceright ] }; + key { [ plus, asterisk, asciitilde ] }; + key { [ less, greater, dead_grave ] }; + + key { [ udiaeresis, Udiaeresis, at ] }; + key { [ comma, semicolon, dead_diaeresis ] }; + key { [ period, colon ] }; + key { [ c, C, copyright, Cacute ] }; + key { [ t, T, trademark ] }; + key { [ z, Z, zabovedot, Zabovedot ] }; + key { [ question, ssharp ] }; + key { [ slash, backslash, dead_acute ] }; + + key { [ a, A, at, aogonek ] }; + key { [ o, O, oacute, Oacute ] }; + key { [ e, E, EuroSign, eogonek ] }; + key { [ i, I ] }; + key { [ u, U ] }; + key { [ h, H ] }; + key { [ d, D ] }; + key { [ r, R, registered ] }; + key { [ n, N, nacute, Nacute ] }; + key { [ s, S, sacute, Sacute] }; + key { [ l, L, lstroke, Lstroke ] }; + + key { [ odiaeresis, Odiaeresis ] }; + key { [ q, Q, at ] }; + key { [ m, M, mu ] }; + key { [ numbersign, apostrophe ] }; + + key { [ minus, underscore, hyphen, diaeresis] }; + + key { [ adiaeresis, Adiaeresis, bar ] }; + + include "level3(ralt_switch)" +}; + + +// German Neo-Layout Version 2 +// adopted 2004 by Hanno Behrens +// inspired by Dvorak/de-ergo http://www.goebel-consult.de/de-ergo/ +// +// Authors: +// Stephan Hilb +// +// Benjamin Kellermann +// Erik Streb +// and many other contributors +// +// http://www.neo-layout.org +// +// $Revision$, $Date$ + +partial alphanumeric_keys modifier_keys keypad_keys +xkb_symbols "neo_base" { + + // Levels in Neo jargon + // -------------------------------------------------------------- + // Ebene 1: normal + // Ebene 2: Shift + // Ebene 3: Mod3 + // Ebene 4: Mod4 (for marking something use Shift + Mod4) + // Ebene 5: Shift + Mod3 + // Ebene 6: Mod3 + Mod4 + // Compose (not a level): Mod3 + Tab + // Feststelltaste (Capslock): Shift + Shift + // Mod4-Lock: Mod4 + Mod4 + // Mod4-Lock: Shift + Mod3 + Tab + + // Legend + // =============== + // Levels in Xkbmap jargon to be found here in the definitions. + // These are the levels used, and Xorg's translations: + // -------------------------------------------------------------- + // Xorg: Level1 Level2 Level3 Level4 Level5 Level6 Level7 Level8 + // Neo: Ebene1 Ebene2 Ebene3 Ebene5 Ebene4 Pseudo-Ebene Ebene6 ??? + // Keys (Neo): None Shift Mod3 Mod3 + Shift Mod4 Mod4 + Shift Mod3 + Mod4 Mod3 + Mod4 + Shift + + + // Alphanumeric-keys + // =============== + key.type[Group1] = "EIGHT_LEVEL_LEVEL_FIVE_LOCK"; + + // Tab as Multi_key (Compose) + // -------------------------------------------------------------- + key { [ Tab, ISO_Left_Tab, Multi_key, ISO_Level5_Lock, NoSymbol, NoSymbol, NoSymbol, ISO_Level5_Lock ] }; + + + // Number row + // -------------------------------------------------------------- + key { [ dead_circumflex, dead_caron, U21BB, U02DE, dead_abovedot, Pointer_EnableKeys, dead_belowdot, NoSymbol ] }; + + key { [ 1, degree, onesuperior, onesubscript, ordfeminine, NoSymbol, notsign, NoSymbol ] }; + key { [ 2, section, twosuperior, twosubscript, masculine, NoSymbol, logicalor, NoSymbol ] }; + key { [ 3, U2113, threesuperior, threesubscript, numerosign, NoSymbol, logicaland, NoSymbol ] }; + key { [ 4, guillemotright, U203A, femalesymbol, NoSymbol, NoSymbol, U22A5, NoSymbol ] }; + key { [ 5, guillemotleft, U2039, malesymbol, periodcentered, NoSymbol, U2221, NoSymbol ] }; + key { [ 6, dollar, cent, U26A5, sterling, NoSymbol, U2225, NoSymbol ] }; + + key { [ 7, EuroSign, yen, U03F0, currency, NoSymbol, rightarrow, NoSymbol ] }; + key { [ 8, doublelowquotemark, singlelowquotemark, U27E8, Tab, ISO_Left_Tab, U221E, NoSymbol ] }; + key { [ 9, leftdoublequotemark, leftsinglequotemark, U27E9, KP_Divide, KP_Divide, variation, NoSymbol ] }; + key { [ 0, rightdoublequotemark, rightsinglequotemark, zerosubscript, KP_Multiply, KP_Multiply, emptyset, NoSymbol ] }; + + key { [ minus, emdash, NoSymbol, U2011, KP_Subtract, KP_Subtract, hyphen, NoSymbol ] }; + key { [ dead_grave, dead_cedilla, dead_abovering, dead_dasia, dead_diaeresis, NoSymbol, dead_macron, NoSymbol ] }; + + // Top row + // -------------------------------------------------------------- + key.type[Group1] = "EIGHT_LEVEL_ALPHABETIC_LEVEL_FIVE_LOCK"; + key { [ x, X, ellipsis, Greek_xi, Prior, Prior, Greek_XI, NoSymbol ] }; + key { [ v, V, underscore, NoSymbol, BackSpace, BackSpace, radical, NoSymbol ] }; + key { [ l, L, bracketleft, Greek_lambda, Up, Up, Greek_LAMBDA, NoSymbol ] }; + key { [ c, C, bracketright, Greek_chi, Delete, Delete, U2102, NoSymbol ] }; + key { [ w, W, asciicircum, Greek_omega, Next, Next, Greek_OMEGA, NoSymbol ] }; + + key { [ k, K, exclam, Greek_kappa, exclamdown, NoSymbol, multiply, NoSymbol ] }; + key { [ h, H, less, Greek_psi, KP_7, KP_7, Greek_PSI, NoSymbol ] }; + key { [ g, G, greater, Greek_gamma, KP_8, KP_8, Greek_GAMMA, NoSymbol ] }; + key { [ f, F, equal, Greek_phi, KP_9, KP_9, Greek_PHI, NoSymbol ] }; + key { [ q, Q, ampersand, U03D5, KP_Add, KP_Add, U211A, NoSymbol ] }; + + key { [ ssharp, U1E9E, U017F, Greek_finalsmallsigma, U2212, NoSymbol, jot, NoSymbol ] }; + + key.type[Group1] = "EIGHT_LEVEL_LEVEL_FIVE_LOCK"; + key { [ dead_acute, dead_tilde, dead_stroke, dead_psili, dead_doubleacute, NoSymbol, dead_breve, NoSymbol ] }; + + // Middle row + // -------------------------------------------------------------- + key.type[Group1] = "EIGHT_LEVEL_ALPHABETIC_LEVEL_FIVE_LOCK"; + key { [ u, U, backslash, NoSymbol, Home, Home, includedin, NoSymbol ] }; + key { [ i, I, slash, Greek_iota, Left, Left, integral, NoSymbol ] }; + key { [ a, A, braceleft, Greek_alpha, Down, Down, U2200, NoSymbol ] }; + key { [ e, E, braceright, Greek_epsilon, Right, Right, U2203, NoSymbol ] }; + key { [ o, O, asterisk, Greek_omicron, End, End, elementof, NoSymbol ] }; + + key { [ s, S, question, Greek_sigma, questiondown, NoSymbol, Greek_SIGMA, NoSymbol ] }; + key { [ n, N, parenleft, Greek_nu, KP_4, KP_4, U2115, NoSymbol ] }; + key { [ r, R, parenright, Greek_rho, KP_5, KP_5, U211D, NoSymbol ] }; + key { [ t, T, minus, Greek_tau, KP_6, KP_6, partialderivative, NoSymbol ] }; + key { [ d, D, colon, Greek_delta, KP_Separator, comma, Greek_DELTA, NoSymbol ] }; + + key { [ y, Y, at, Greek_upsilon, period, KP_Decimal, nabla, NoSymbol ] }; + + // Bottom row + // -------------------------------------------------------------- + key { [ udiaeresis, Udiaeresis, numbersign, NoSymbol, Escape, Escape, union, NoSymbol ] }; + key { [ odiaeresis, Odiaeresis, dollar, U03F5, Tab, Tab, intersection, NoSymbol ] }; + key { [ adiaeresis, Adiaeresis, bar, Greek_eta, Insert, Insert, U2135, NoSymbol ] }; + key { [ p, P, asciitilde, Greek_pi, Return, Return, Greek_PI, NoSymbol ] }; + key { [ z, Z, grave, Greek_zeta, Undo, Redo, U2124, NoSymbol ] }; + + key { [ b, B, plus, Greek_beta, colon, NoSymbol, U21D0, NoSymbol ] }; + key { [ m, M, percent, Greek_mu, KP_1, KP_1, ifonlyif, NoSymbol ] }; + key.type[Group1] = "EIGHT_LEVEL_LEVEL_FIVE_LOCK"; + key { [ comma, endash, quotedbl, U03F1, KP_2, KP_2, U21D2, NoSymbol ] }; + key { [ period, enfilledcircbullet, apostrophe, U03D1, KP_3, KP_3, U21A6, NoSymbol ] }; + key.type[Group1] = "EIGHT_LEVEL_ALPHABETIC_LEVEL_FIVE_LOCK"; + key { [ j, J, semicolon, Greek_theta, semicolon, NoSymbol, Greek_THETA, NoSymbol ] }; + key.type[Group1] = "EIGHT_LEVEL_LEVEL_FIVE_LOCK"; + + // Space key + // -------------------------------------------------------------- + key { [ space, space, space, nobreakspace, KP_0, KP_0, U202F, NoSymbol ] }; + + + // Keypad-keys + // =============== + + // The former Numlock key: + key { [ Tab, ISO_Left_Tab, equal, approxeq, notequal, Pointer_EnableKeys, identical, NoSymbol ] }; + + // Topmost row + // -------------------------------------------------------------- + key { [ KP_Divide, KP_Divide, division, U2300, U2044, NoSymbol, U2223, NoSymbol ] }; + key { [ KP_Multiply, KP_Multiply, U22C5, U2299, multiply, NoSymbol, U2297, NoSymbol ] }; + key { [ KP_Subtract, KP_Subtract, U2212, U2296, U2216, NoSymbol, U2238, NoSymbol ] }; + + // Top row + // -------------------------------------------------------------- + key { [ KP_7, U2714, U2195, U226A, KP_Home, KP_Home, upstile, NoSymbol ] }; + key { [ KP_8, U2718, uparrow, intersection, KP_Up, KP_Up, U22C2, NoSymbol ] }; + key { [ KP_9, dagger, U20D7, U226B, KP_Prior, KP_Prior, U2309, NoSymbol ] }; + key { [ KP_Add, KP_Add, plusminus, U2295, U2213, NoSymbol, U2214, NoSymbol ] }; + + // Middle row + // -------------------------------------------------------------- + key { [ KP_4, club, leftarrow, includedin, KP_Left, KP_Left, U2286, NoSymbol ] }; + key { [ KP_5, EuroSign, colon, U22B6, KP_Begin, KP_Begin, U22B7, NoSymbol ] }; + key { [ KP_6, U2023, rightarrow, includes, KP_Right, KP_Right, U2287, NoSymbol ] }; + + // Bottom row + // -------------------------------------------------------------- + key { [ KP_1, diamond, U2194, lessthanequal, KP_End, KP_End, downstile, NoSymbol ] }; + key { [ KP_2, heart, downarrow, union, KP_Down, KP_Down, U22C3, NoSymbol ] }; + key { [ KP_3, U2660, U21CC, greaterthanequal, KP_Next, KP_Next, U230B, NoSymbol ] }; + key { [ KP_Enter, KP_Enter, KP_Enter, KP_Enter, KP_Enter, KP_Enter, KP_Enter, NoSymbol ] }; + key { [ KP_Equal, NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol ] }; + + // Bottommost row + // -------------------------------------------------------------- + key { [ KP_0, U2423, percent, U2030, KP_Insert, KP_Insert, U25A1, NoSymbol ] }; + key { [ KP_Separator, period, comma, minutes, KP_Delete, KP_Delete, seconds, NoSymbol ] }; +}; + +partial alphanumeric_keys modifier_keys keypad_keys +xkb_symbols "neo" { + + include "de(neo_base)" + + name[Group1]= "German (Neo 2)"; + + include "shift(both_capslock)" + include "level3(caps_switch)" + include "level3(bksl_switch)" + include "level5(lsgt_switch_lock)" + include "level5(ralt_switch_lock)" +}; + +// Copied from macintosh_vndr/de +// olh@suse.de very close to MacOS map + +partial alphanumeric_keys +xkb_symbols "mac" { + + include "de" + name[Group1]= "German (Macintosh)"; + + key { [ 1, exclam, exclamdown, at ] }; + key { [ 5, percent, bracketleft ] }; + key { [ 6, ampersand, bracketright ] }; + key { [ 7, slash, bar, backslash ] }; + key { [ 8, parenleft, braceleft, asciitilde ] }; + key { [ 9, parenright, braceright ] }; + key { [ q, Q, guillemotleft, guillemotright ] }; + key { [ r, R, registered ] }; + key { [ u, U, diaeresis, Aacute ] }; + key { [ i, I, slash, Ucircumflex ] }; + key { [ udiaeresis, Udiaeresis, periodcentered, degree ] }; + key { [ plus, asterisk, asciitilde ] }; + key { [ a, A, aring, Aring ] }; + key { [ g, G, copyright ] }; + key { [ h, H, ordfeminine ] }; + key { [ l, L, at ] }; + key { [ odiaeresis, Odiaeresis, dead_acute ] }; + key { [ n, N, asciitilde ] }; +}; + +partial alphanumeric_keys +xkb_symbols "mac_nodeadkeys" { + // modify the standard German mac layout to not have any dead keys + include "de(mac)" + name[Group1]= "German (Macintosh, no dead keys)"; + + key { [ asciicircum, degree, notsign ] }; + key { [ 4, dollar, onequarter, currency ] }; + key { [ acute, grave, cedilla ] }; + key { [ udiaeresis, Udiaeresis, diaeresis ] }; + key { [ plus, asterisk, asciitilde, macron ] }; + key { [ odiaeresis, Odiaeresis, acute ] }; + key { [ adiaeresis, Adiaeresis, asciicircum ] }; + + key { [ numbersign, apostrophe, rightsinglequotemark ] }; +}; + +partial alphanumeric_keys +xkb_symbols "dsb" +{ + include "latin(basic)" + name[Group1] = "Lower Sorbian"; + key { [ z, Z, zcaron, Zcaron ] }; + key { [ x, X, zacute, Zacute ] }; + key { [ c, C, cacute, Cacute ] }; + key { [ v, V, ccaron, Ccaron ] }; + key { [ n, N, nacute, Nacute ] }; + key { [ s, S, sacute, Sacute ] }; + key { [ d, D, scaron, Scaron ] }; + key { [ f, F ] }; + key { [ q, Q ] }; + key { [ w, W ] }; + key { [ e, E, ecaron, Ecaron ] }; + key { [ r, R, racute, Racute ] }; + key { [ t, T, U20B5, EuroSign ] }; + key { [ o, O, oacute, Oacute ] }; + include "kpdl(comma)" + include "level3(ralt_switch)" +}; + +partial alphanumeric_keys +xkb_symbols "dsb_qwertz" +{ + include "latin(basic)" + name[Group1] = "Lower Sorbian (QWERTZ)"; + key { [ y, Y ] }; + key { [ x, X ] }; + key { [ c, C, cacute, Cacute ] }; + key { [ v, V, ccaron, Ccaron ] }; + key { [ n, N, nacute, Nacute ] }; + key { [ s, S, sacute, Sacute ] }; + key { [ d, D, scaron, Scaron ] }; + key { [ f, F ] }; + key { [ q, Q ] }; + key { [ w, W ] }; + key { [ e, E, ecaron, Ecaron ] }; + key { [ r, R, racute, Racute ] }; + key { [ t, T, U20B5, EuroSign ] }; + key { [ z, Z, zcaron, Zcaron ] }; + key { [ u, U, zacute, Zacute ] }; + key { [ o, O, oacute, Oacute ] }; + include "kpdl(comma)" + include "level3(ralt_switch)" +}; + +partial alphanumeric_keys +xkb_symbols "qwerty" { + + // This layout should work exactly as a de with the exception + // of 'Z' and 'Y' keys, which are in the qwerty style (ie. swapped). + // 2008 by Matej Košík + + include "de(basic)" + + name[Group1] = "German (QWERTY)"; + + key { [ z, Z, leftarrow, yen ] }; + key { [ y, Y, guillemotleft, less ] }; +}; + +// layout for Russian letters on an german keyboard +// based on US-RU layout by Ivan Popov 2005-07-17 +// adopted for german layout by Alexey Fisher 2010-08-19 + +partial alphanumeric_keys +xkb_symbols "ru" { + + include "de(basic)" + + name[Group1]= "Russian (Germany, phonetic)"; + + key { [ Cyrillic_a, Cyrillic_A ] }; + key { [ Cyrillic_be, Cyrillic_BE ] }; + key { [ Cyrillic_ve, Cyrillic_VE ] }; + key { [ Cyrillic_ghe, Cyrillic_GHE ] }; + key { [ Cyrillic_de, Cyrillic_DE ] }; + key { [ Cyrillic_ie, Cyrillic_IE ] }; + key { [ Cyrillic_io, Cyrillic_IO, asciitilde ] }; + key { [ Cyrillic_zhe, Cyrillic_ZHE ] }; + key { [ Cyrillic_ze, Cyrillic_ZE ] }; + key { [ Cyrillic_i, Cyrillic_I ] }; + key { [ Cyrillic_shorti, Cyrillic_SHORTI ] }; + key { [ Cyrillic_ka, Cyrillic_KA ] }; + key { [ Cyrillic_el, Cyrillic_EL ] }; + key { [ Cyrillic_em, Cyrillic_EM ] }; + key { [ Cyrillic_en, Cyrillic_EN ] }; + key { [ Cyrillic_o, Cyrillic_O ] }; + key { [ Cyrillic_pe, Cyrillic_PE ] }; + key { [ Cyrillic_er, Cyrillic_ER ] }; + key { [ Cyrillic_es, Cyrillic_ES ] }; + key { [ Cyrillic_te, Cyrillic_TE ] }; + key { [ Cyrillic_u, Cyrillic_U ] }; + key { [ Cyrillic_ef, Cyrillic_EF ] }; + key { [ Cyrillic_ha, Cyrillic_HA ] }; + key { [ Cyrillic_tse, Cyrillic_TSE ] }; + key { [ Cyrillic_che, Cyrillic_CHE ] }; + key { [ Cyrillic_sha, Cyrillic_SHA ] }; + key { [ Cyrillic_shcha, Cyrillic_SHCHA, plus, asterisk ] }; + key { [ Cyrillic_hardsign, Cyrillic_HARDSIGN ] }; + key { [ Cyrillic_yeru, Cyrillic_YERU ] }; + key { [ Cyrillic_softsign, Cyrillic_SOFTSIGN ] }; + key { [ Cyrillic_e, Cyrillic_E ] }; + key { [ Cyrillic_yu, Cyrillic_YU, numbersign, apostrophe ] }; + key { [ Cyrillic_ya, Cyrillic_YA ] }; + + include "level3(ralt_switch)" +}; + +// layout for Russian (recommended) letters on a german keyboard +// based on "Russisch für Deutsche, empfohlen" by B. Bendixen und H. Rothe http://russisch.urz.uni-leipzig.de/key2000.htm 2016-02-01 +// adapted for Linux by Niko Krause 2016-06-09 + +partial alphanumeric_keys +xkb_symbols "ru-recom" { + + include "de(basic)" + + name[Group1]= "Russian (Germany, recommended)"; + + key { [ Cyrillic_a, Cyrillic_A ] }; + key { [ Cyrillic_be, Cyrillic_BE ] }; + key { [ Cyrillic_ve, Cyrillic_VE ] }; + key { [ Cyrillic_ghe, Cyrillic_GHE, Ukrainian_ghe_with_upturn, Ukrainian_GHE_WITH_UPTURN ] }; + key { [ Cyrillic_de, Cyrillic_DE ] }; + key { [ Cyrillic_ie, Cyrillic_IE ] }; + key { [ Cyrillic_ya, Cyrillic_YA, asciicircum, degree ] }; + key { [ Cyrillic_ha, Cyrillic_HA ] }; + key { [ Cyrillic_tse, Cyrillic_TSE ] }; + key { [ Cyrillic_i, Cyrillic_I, Ukrainian_i, Ukrainian_I ] }; + key { [ Cyrillic_shorti, Cyrillic_SHORTI, Ukrainian_yi, Ukrainian_YI ] }; + key { [ Cyrillic_ka, Cyrillic_KA ] }; + key { [ Cyrillic_el, Cyrillic_EL ] }; + key { [ Cyrillic_em, Cyrillic_EM ] }; + key { [ Cyrillic_en, Cyrillic_EN ] }; + key { [ Cyrillic_o, Cyrillic_O ] }; + key { [ Cyrillic_pe, Cyrillic_PE ] }; + key { [ Cyrillic_er, Cyrillic_ER ] }; + key { [ Cyrillic_es, Cyrillic_ES, Cyrillic_ze, Cyrillic_ZE ] }; + key { [ Cyrillic_te, Cyrillic_TE ] }; + key { [ Cyrillic_u, Cyrillic_U ] }; + key { [ Cyrillic_ef, Cyrillic_EF ] }; + key { [ Cyrillic_zhe, Cyrillic_ZHE ] }; + key { [ Cyrillic_che, Cyrillic_CHE ] }; + key { [ Cyrillic_io, Cyrillic_IO ] }; + key { [ Cyrillic_yu, Cyrillic_YU ] }; + key { [ Cyrillic_sha, Cyrillic_SHA, plus, asterisk ] }; + key { [ Cyrillic_ze, Cyrillic_ZE ] }; + key { [ Cyrillic_yeru, Cyrillic_YERU ] }; + key { [ Cyrillic_softsign, Cyrillic_SOFTSIGN ] }; + key { [ Cyrillic_e, Cyrillic_E, Ukrainian_ie, Ukrainian_IE ] }; + key { [ Cyrillic_hardsign, Cyrillic_HARDSIGN, numbersign, apostrophe ] }; + key { [ Cyrillic_shcha, Cyrillic_SHCHA ] }; + + key { [ asciitilde, question, backslash, questiondown ] }; + key { [ U0301, U0300, U0323, U0307 ] }; + + include "level3(ralt_switch)" +}; + +// layout for Russian (transliteration) letters on a german keyboard +// based on "Russisch für Deutsche, Transliteration" by B. Bendixen und H. Rothe http://russisch.urz.uni-leipzig.de/key2000.htm 2016-02-01 +// adapted for Linux by Niko Krause 2016-06-09 + +partial alphanumeric_keys +xkb_symbols "ru-translit" { + + include "de(basic)" + + name[Group1]= "Russian (Germany, transliteration)"; + + key { [ Cyrillic_a, Cyrillic_A ] }; + key { [ Cyrillic_be, Cyrillic_BE ] }; + key { [ Cyrillic_sha, Cyrillic_SHA ] }; + key { [ Cyrillic_ghe, Cyrillic_GHE, Ukrainian_ghe_with_upturn, Ukrainian_GHE_WITH_UPTURN ] }; + key { [ Cyrillic_de, Cyrillic_DE ] }; + key { [ Cyrillic_ie, Cyrillic_IE ] }; + key { [ Cyrillic_ya, Cyrillic_YA, asciicircum, degree ] }; + key { [ Cyrillic_ha, Cyrillic_HA ] }; + key { [ Cyrillic_ze, Cyrillic_ZE ] }; + key { [ Cyrillic_i, Cyrillic_I, Ukrainian_i, Ukrainian_I ] }; + key { [ Cyrillic_shorti, Cyrillic_SHORTI, Ukrainian_yi, Ukrainian_YI ] }; + key { [ Cyrillic_ka, Cyrillic_KA ] }; + key { [ Cyrillic_el, Cyrillic_EL ] }; + key { [ Cyrillic_em, Cyrillic_EM ] }; + key { [ Cyrillic_en, Cyrillic_EN ] }; + key { [ Cyrillic_o, Cyrillic_O ] }; + key { [ Cyrillic_pe, Cyrillic_PE ] }; + key { [ Cyrillic_er, Cyrillic_ER ] }; + key { [ Cyrillic_es, Cyrillic_ES, Cyrillic_che, Cyrillic_CHE ] }; + key { [ Cyrillic_te, Cyrillic_TE ] }; + key { [ Cyrillic_u, Cyrillic_U ] }; + key { [ Cyrillic_ef, Cyrillic_EF ] }; + key { [ Cyrillic_zhe, Cyrillic_ZHE ] }; + key { [ Cyrillic_tse, Cyrillic_TSE ] }; + key { [ Cyrillic_io, Cyrillic_IO ] }; + key { [ Cyrillic_yu, Cyrillic_YU ] }; + key { [ Cyrillic_hardsign, Cyrillic_HARDSIGN, plus, asterisk ] }; + key { [ Cyrillic_che, Cyrillic_CHE ] }; + key { [ Cyrillic_yeru, Cyrillic_YERU ] }; + key { [ Cyrillic_ve, Cyrillic_VE ] }; + key { [ Cyrillic_e, Cyrillic_E, Ukrainian_ie, Ukrainian_IE ] }; + key { [ Cyrillic_softsign, Cyrillic_SOFTSIGN, numbersign, apostrophe ] }; + key { [ Cyrillic_shcha, Cyrillic_SHCHA ] }; + + key { [ asciitilde, question, backslash, questiondown ] }; + key { [ U0301, U0300, U0323, U0307 ] }; + + include "level3(ralt_switch)" +}; + +partial alphanumeric_keys +xkb_symbols "pl" { + + // Combined layout for entering both German and Polish symbols on a German physical + // keyboard. Based on German (no dead keys) and Polish (basic). Polish diacritics + // on AltGr+"acelnosxz". EuroSign moved to AE04 (AltGr+dollar key) to avoid conflict + // with Polish eogonek. + // + // https://github.com/kontextify/xkeyboard-config + + include "latin(type4)" + include "de(nodeadkeys)" + + name[Group1]= "Polish (Germany, no dead keys)"; + + key { [ 4, dollar, EuroSign, currency ] }; + + key { [ q, Q ] }; + key { [ w, W ] }; + key { [ e, E, eogonek, Eogonek ] }; + key { [ o, O, oacute, Oacute ] }; + key { [ a, A, aogonek, Aogonek ] }; + key { [ s, S, sacute, Sacute ] }; + key { [ f, F ] }; + key { [ z, Z, zabovedot, Zabovedot ] }; + key { [ x, X, zacute, Zacute ] }; + key { [ c, C, cacute, Cacute ] }; + key { [ n, N, nacute, Nacute ] }; + + include "kpdl(comma)" + + include "level3(ralt_switch)" +}; + +partial alphanumeric_keys +xkb_symbols "tr" { + + // add turkish-specific letters to the basic German layout. + // Turkish symbols are accessible with combination of and + // 'i', 's', 'g', 'c'' (+ for capital letters). + + include "de(basic)" + + name[Group1]="Turkish (Germany)"; + + key { [ i, I, U0131, U0130 ] }; + key { [ s, S, U015F, U015E ] }; + key { [ g, G, U011F, U011E ] }; + key { [ c, C, U0E7, U0C7 ] }; +}; + +partial alphanumeric_keys +xkb_symbols "us" { + include "us" + + name[Group1]="German (US)"; + + key { [ 3, numbersign, section, degree ] }; + key { [ minus, underscore, ssharp, U1E9E ] }; + + key { [ e, E, EuroSign, cent ] }; + key { [ u, U, udiaeresis, Udiaeresis ] }; + key { [ o, O, odiaeresis, Odiaeresis ] }; + key { [ bracketleft, braceleft, udiaeresis, Udiaeresis ] }; + + key { [ a, A, adiaeresis, Adiaeresis ] }; + key { [ s, S, ssharp, U1E9E ] }; + key { [ semicolon, colon, odiaeresis, Odiaeresis ] }; + key { [ apostrophe, quotedbl, adiaeresis, Adiaeresis ] }; + + key { [ c, C, Multi_key, Multi_key ] }; + key { [ m, M, dead_greek, Menu ] }; + + include "level3(ralt_switch)" +}; + +// EXTRAS: + +partial alphanumeric_keys +xkb_symbols "hu" { + + // modify the basic German layout to not have any dead keys and add Hungarian letters + + include "de(basic)" + name[Group1]="German (with Hungarian letters, no dead keys)"; + + key { [ y, Y, guillemotleft, less ] }; + key { [odiaeresis, Odiaeresis, eacute, Eacute ] }; + key { [adiaeresis, Adiaeresis, aacute, Aacute] }; + key { [ e, E, EuroSign, EuroSign ] }; + key { [ z, Z, leftarrow, yen ] }; + key { [ u, U, uacute, Uacute ] }; + key { [ i, I, iacute, Iacute ] }; + key { [ o, O, odoubleacute, Odoubleacute ] }; + key { [udiaeresis, Udiaeresis, udoubleacute, Udoubleacute ] }; + key { [ plus, asterisk, asciitilde, macron ] }; + key { [ acute, grave, oacute, Oacute ] }; + key { [numbersign, apostrophe, rightsinglequotemark, grave ] }; + key { [asciicircum, degree, notsign, notsign ] }; +}; + +partial alphanumeric_keys + xkb_symbols "sun_type6" { + include "sun_vndr/de(sun_type6)" +}; + +partial alphanumeric_keys +xkb_symbols "adnw_base" { + include "de(neo_base)" + + key.type[Group1] = "EIGHT_LEVEL_LEVEL_FIVE_LOCK"; + key { [ period, enfilledcircbullet, NoSymbol, U03D1, NoSymbol, NoSymbol, U21A6, NoSymbol ] }; + key { [ comma, endash, NoSymbol, U03F1, NoSymbol, NoSymbol, U21D2, NoSymbol ] }; + + key.type[Group1] = "EIGHT_LEVEL_ALPHABETIC_LEVEL_FIVE_LOCK"; + key { [ k, K, NoSymbol, Greek_kappa, NoSymbol, NoSymbol, multiply, NoSymbol ] }; + key { [ u, U, NoSymbol, NoSymbol, NoSymbol, NoSymbol, includedin, NoSymbol ] }; + key { [ udiaeresis, Udiaeresis, NoSymbol, NoSymbol, NoSymbol, NoSymbol, union, NoSymbol ] }; + key { [ adiaeresis, Adiaeresis, NoSymbol, Greek_eta, NoSymbol, NoSymbol, U2135, NoSymbol ] }; + key { [ v, V, NoSymbol, NoSymbol, NoSymbol, NoSymbol, radical, NoSymbol ] }; + key { [ g, G, NoSymbol, Greek_gamma, NoSymbol, NoSymbol, Greek_GAMMA, NoSymbol ] }; + key { [ c, C, NoSymbol, Greek_chi, NoSymbol, NoSymbol, U2102, NoSymbol ] }; + key { [ l, L, NoSymbol, Greek_lambda, NoSymbol, NoSymbol, Greek_LAMBDA, NoSymbol ] }; + key { [ j, J, NoSymbol, Greek_theta, NoSymbol, NoSymbol, Greek_THETA, NoSymbol ] }; + key { [ f, F, NoSymbol, Greek_phi, NoSymbol, NoSymbol, Greek_PHI, NoSymbol ] }; + key { [ h, H, NoSymbol, Greek_psi, NoSymbol, NoSymbol, Greek_PSI, NoSymbol ] }; + key { [ i, I, NoSymbol, Greek_iota, NoSymbol, NoSymbol, integral, NoSymbol ] }; + key { [ e, E, NoSymbol, Greek_epsilon, NoSymbol, NoSymbol, U2203, NoSymbol ] }; + key { [ a, A, NoSymbol, Greek_alpha, NoSymbol, NoSymbol, U2200, NoSymbol ] }; + key { [ o, O, NoSymbol, Greek_omicron, NoSymbol, NoSymbol, elementof, NoSymbol ] }; + key { [ d, D, NoSymbol, Greek_delta, NoSymbol, NoSymbol, Greek_DELTA, NoSymbol ] }; + key { [ t, T, NoSymbol, Greek_tau, NoSymbol, NoSymbol, partialderivative, NoSymbol ] }; + key { [ r, R, NoSymbol, Greek_rho, NoSymbol, NoSymbol, U211D, NoSymbol ] }; + key { [ n, N, NoSymbol, Greek_nu, NoSymbol, NoSymbol, U2115, NoSymbol ] }; + key { [ s, S, NoSymbol, Greek_sigma, NoSymbol, NoSymbol, Greek_SIGMA, NoSymbol ] }; + key { [ ssharp, U1E9E, NoSymbol, Greek_finalsmallsigma, NoSymbol, NoSymbol, jot, NoSymbol ] }; + key { [ x, X, NoSymbol, Greek_xi, NoSymbol, NoSymbol, Greek_XI, NoSymbol ] }; + key { [ y, Y, NoSymbol, Greek_upsilon, NoSymbol, NoSymbol, nabla, NoSymbol ] }; + key { [ odiaeresis, Odiaeresis, NoSymbol, U03F5, NoSymbol, NoSymbol, intersection, NoSymbol ] }; + key { [ q, Q, NoSymbol, U03D5, NoSymbol, NoSymbol, U211A, NoSymbol ] }; + key { [ b, B, NoSymbol, Greek_beta, NoSymbol, NoSymbol, U21D0, NoSymbol ] }; + key { [ p, P, NoSymbol, Greek_pi, NoSymbol, NoSymbol, Greek_PI, NoSymbol ] }; + key { [ w, W, NoSymbol, Greek_omega, NoSymbol, NoSymbol, Greek_OMEGA, NoSymbol ] }; + key { [ m, M, NoSymbol, Greek_mu, NoSymbol, NoSymbol, ifonlyif, NoSymbol ] }; + key { [ z, Z, NoSymbol, Greek_zeta, NoSymbol, NoSymbol, U2124, NoSymbol ] }; +}; + +partial alphanumeric_keys modifier_keys keypad_keys +xkb_symbols "adnw" { + + include "de(adnw_base)" + + name[Group1]= "German (Aus der Neo-Welt)"; + + include "shift(both_capslock)" + include "level3(caps_switch)" + include "level3(bksl_switch)" + include "level5(lsgt_switch_lock)" + include "level5(ralt_switch_lock)" +}; + +partial alphanumeric_keys +xkb_symbols "koy_base" { + include "de(neo_base)" + + key.type[Group1] = "EIGHT_LEVEL_LEVEL_FIVE_LOCK"; + key { [ period, enfilledcircbullet, NoSymbol, U03D1, NoSymbol, NoSymbol, U21A6, NoSymbol ] }; + key { [ comma, endash, NoSymbol, U03F1, NoSymbol, NoSymbol, U21D2, NoSymbol ] }; + + key.type[Group1] = "EIGHT_LEVEL_ALPHABETIC_LEVEL_FIVE_LOCK"; + key { [ k, K, NoSymbol, Greek_kappa, NoSymbol, NoSymbol, multiply, NoSymbol ] }; + key { [ o, O, NoSymbol, Greek_omicron, NoSymbol, NoSymbol, elementof, NoSymbol ] }; + key { [ y, Y, NoSymbol, Greek_upsilon, NoSymbol, NoSymbol, nabla, NoSymbol ] }; + key { [ v, V, NoSymbol, NoSymbol, NoSymbol, NoSymbol, radical, NoSymbol ] }; + key { [ g, G, NoSymbol, Greek_gamma, NoSymbol, NoSymbol, Greek_GAMMA, NoSymbol ] }; + key { [ c, C, NoSymbol, Greek_chi, NoSymbol, NoSymbol, U2102, NoSymbol ] }; + key { [ l, L, NoSymbol, Greek_lambda, NoSymbol, NoSymbol, Greek_LAMBDA, NoSymbol ] }; + key { [ ssharp, U1E9E, NoSymbol, Greek_finalsmallsigma, NoSymbol, NoSymbol, jot, NoSymbol ] }; + key { [ z, Z, NoSymbol, Greek_zeta, NoSymbol, NoSymbol, U2124, NoSymbol ] }; + key { [ h, H, NoSymbol, Greek_psi, NoSymbol, NoSymbol, Greek_PSI, NoSymbol ] }; + key { [ a, A, NoSymbol, Greek_alpha, NoSymbol, NoSymbol, U2200, NoSymbol ] }; + key { [ e, E, NoSymbol, Greek_epsilon, NoSymbol, NoSymbol, U2203, NoSymbol ] }; + key { [ i, I, NoSymbol, Greek_iota, NoSymbol, NoSymbol, integral, NoSymbol ] }; + key { [ u, U, NoSymbol, NoSymbol, NoSymbol, NoSymbol, includedin, NoSymbol ] }; + key { [ d, D, NoSymbol, Greek_delta, NoSymbol, NoSymbol, Greek_DELTA, NoSymbol ] }; + key { [ t, T, NoSymbol, Greek_tau, NoSymbol, NoSymbol, partialderivative, NoSymbol ] }; + key { [ r, R, NoSymbol, Greek_rho, NoSymbol, NoSymbol, U211D, NoSymbol ] }; + key { [ n, N, NoSymbol, Greek_nu, NoSymbol, NoSymbol, U2115, NoSymbol ] }; + key { [ s, S, NoSymbol, Greek_sigma, NoSymbol, NoSymbol, Greek_SIGMA, NoSymbol ] }; + key { [ f, F, NoSymbol, Greek_phi, NoSymbol, NoSymbol, Greek_PHI, NoSymbol ] }; + key { [ x, X, NoSymbol, Greek_xi, NoSymbol, NoSymbol, Greek_XI, NoSymbol ] }; + key { [ q, Q, NoSymbol, U03D5, NoSymbol, NoSymbol, U211A, NoSymbol ] }; + key { [ adiaeresis, Adiaeresis, NoSymbol, Greek_eta, NoSymbol, NoSymbol, U2135, NoSymbol ] }; + key { [ udiaeresis, Udiaeresis, NoSymbol, NoSymbol, NoSymbol, NoSymbol, union, NoSymbol ] }; + key { [ odiaeresis, Odiaeresis, NoSymbol, U03F5, NoSymbol, NoSymbol, intersection, NoSymbol ] }; + key { [ b, B, NoSymbol, Greek_beta, NoSymbol, NoSymbol, U21D0, NoSymbol ] }; + key { [ p, P, NoSymbol, Greek_pi, NoSymbol, NoSymbol, Greek_PI, NoSymbol ] }; + key { [ w, W, NoSymbol, Greek_omega, NoSymbol, NoSymbol, Greek_OMEGA, NoSymbol ] }; + key { [ m, M, NoSymbol, Greek_mu, NoSymbol, NoSymbol, ifonlyif, NoSymbol ] }; + key { [ j, J, NoSymbol, Greek_theta, NoSymbol, NoSymbol, Greek_THETA, NoSymbol ] }; +}; + +partial alphanumeric_keys modifier_keys keypad_keys +xkb_symbols "koy" { + + include "de(koy_base)" + + name[Group1]= "German (KOY)"; + + include "shift(both_capslock)" + include "level3(caps_switch)" + include "level3(bksl_switch)" + include "level5(lsgt_switch_lock)" + include "level5(ralt_switch_lock)" +}; + +partial alphanumeric_keys +xkb_symbols "bone_base" { + include "de(neo_base)" + + key.type[Group1] = "EIGHT_LEVEL_LEVEL_FIVE_LOCK"; + key { [ comma, endash, NoSymbol, U03F1, NoSymbol, NoSymbol, U21D2, NoSymbol ] }; + key { [ period, enfilledcircbullet, NoSymbol, U03D1, NoSymbol, NoSymbol, U21A6, NoSymbol ] }; + + key.type[Group1] = "EIGHT_LEVEL_ALPHABETIC_LEVEL_FIVE_LOCK"; + key { [ j, J, NoSymbol, Greek_theta, NoSymbol, NoSymbol, Greek_THETA, NoSymbol ] }; + key { [ d, D, NoSymbol, Greek_delta, NoSymbol, NoSymbol, Greek_DELTA, NoSymbol ] }; + key { [ u, U, NoSymbol, NoSymbol, NoSymbol, NoSymbol, includedin, NoSymbol ] }; + key { [ a, A, NoSymbol, Greek_alpha, NoSymbol, NoSymbol, U2200, NoSymbol ] }; + key { [ x, X, NoSymbol, Greek_xi, NoSymbol, NoSymbol, Greek_XI, NoSymbol ] }; + key { [ p, P, NoSymbol, Greek_pi, NoSymbol, NoSymbol, Greek_PI, NoSymbol ] }; + key { [ h, H, NoSymbol, Greek_psi, NoSymbol, NoSymbol, Greek_PSI, NoSymbol ] }; + key { [ l, L, NoSymbol, Greek_lambda, NoSymbol, NoSymbol, Greek_LAMBDA, NoSymbol ] }; + key { [ m, M, NoSymbol, Greek_mu, NoSymbol, NoSymbol, ifonlyif, NoSymbol ] }; + key { [ w, W, NoSymbol, Greek_omega, NoSymbol, NoSymbol, Greek_OMEGA, NoSymbol ] }; + key { [ ssharp, U1E9E, NoSymbol, Greek_finalsmallsigma, NoSymbol, NoSymbol, jot, NoSymbol ] }; + key { [ c, C, NoSymbol, Greek_chi, NoSymbol, NoSymbol, U2102, NoSymbol ] }; + key { [ t, T, NoSymbol, Greek_tau, NoSymbol, NoSymbol, partialderivative, NoSymbol ] }; + key { [ i, I, NoSymbol, Greek_iota, NoSymbol, NoSymbol, integral, NoSymbol ] }; + key { [ e, E, NoSymbol, Greek_epsilon, NoSymbol, NoSymbol, U2203, NoSymbol ] }; + key { [ o, O, NoSymbol, Greek_omicron, NoSymbol, NoSymbol, elementof, NoSymbol ] }; + key { [ b, B, NoSymbol, Greek_beta, NoSymbol, NoSymbol, U21D0, NoSymbol ] }; + key { [ n, N, NoSymbol, Greek_nu, NoSymbol, NoSymbol, U2115, NoSymbol ] }; + key { [ r, R, NoSymbol, Greek_rho, NoSymbol, NoSymbol, U211D, NoSymbol ] }; + key { [ s, S, NoSymbol, Greek_sigma, NoSymbol, NoSymbol, Greek_SIGMA, NoSymbol ] }; + key { [ g, G, NoSymbol, Greek_gamma, NoSymbol, NoSymbol, Greek_GAMMA, NoSymbol ] }; + key { [ q, Q, NoSymbol, U03D5, NoSymbol, NoSymbol, U211A, NoSymbol ] }; + key { [ f, F, NoSymbol, Greek_phi, NoSymbol, NoSymbol, Greek_PHI, NoSymbol ] }; + key { [ v, V, NoSymbol, NoSymbol, NoSymbol, NoSymbol, radical, NoSymbol ] }; + key { [ udiaeresis, Udiaeresis, NoSymbol, NoSymbol, NoSymbol, NoSymbol, union, NoSymbol ] }; + key { [ adiaeresis, Adiaeresis, NoSymbol, Greek_eta, NoSymbol, NoSymbol, U2135, NoSymbol ] }; + key { [ odiaeresis, Odiaeresis, NoSymbol, U03F5, NoSymbol, NoSymbol, intersection, NoSymbol ] }; + key { [ y, Y, NoSymbol, Greek_upsilon, NoSymbol, NoSymbol, nabla, NoSymbol ] }; + key { [ z, Z, NoSymbol, Greek_zeta, NoSymbol, NoSymbol, U2124, NoSymbol ] }; + key { [ k, K, NoSymbol, Greek_kappa, NoSymbol, NoSymbol, multiply, NoSymbol ] }; +}; + +partial alphanumeric_keys modifier_keys keypad_keys +xkb_symbols "bone" { + + include "de(bone_base)" + + name[Group1]= "German (Bone)"; + + include "shift(both_capslock)" + include "level3(caps_switch)" + include "level3(bksl_switch)" + include "level5(lsgt_switch_lock)" + include "level5(ralt_switch_lock)" +}; + +partial alphanumeric_keys +xkb_symbols "bone_eszett_home_base" { + include "de(bone_base)" + + key.type[Group1] = "EIGHT_LEVEL_ALPHABETIC_LEVEL_FIVE_LOCK"; + key { [ q, Q, NoSymbol, U03D5, NoSymbol, NoSymbol, U211A, NoSymbol ] }; + key { [ ssharp, U1E9E, NoSymbol, Greek_finalsmallsigma, NoSymbol, NoSymbol, jot, NoSymbol ] }; +}; + +partial alphanumeric_keys modifier_keys keypad_keys +xkb_symbols "bone_eszett_home" { + + include "de(bone_eszett_home_base)" + + name[Group1]= "German (Bone, eszett in the home row)"; + + include "shift(both_capslock)" + include "level3(caps_switch)" + include "level3(bksl_switch)" + include "level5(lsgt_switch_lock)" + include "level5(ralt_switch_lock)" +}; + +partial alphanumeric_keys +xkb_symbols "neo_qwertz_base" { + include "de(neo_base)" + + key.type[Group1] = "EIGHT_LEVEL_LEVEL_FIVE_LOCK"; + key { [ comma, endash, NoSymbol, U03F1, NoSymbol, NoSymbol, U21D2, NoSymbol ] }; + key { [ period, enfilledcircbullet, NoSymbol, U03D1, NoSymbol, NoSymbol, U21A6, NoSymbol ] }; + key { [ minus, emdash, NoSymbol, U2011, NoSymbol, NoSymbol, hyphen, NoSymbol ] }; + + key.type[Group1] = "EIGHT_LEVEL_ALPHABETIC_LEVEL_FIVE_LOCK"; + key { [ ssharp, U1E9E, NoSymbol, Greek_finalsmallsigma, NoSymbol, NoSymbol, jot, NoSymbol ] }; + key { [ q, Q, NoSymbol, U03D5, NoSymbol, NoSymbol, U211A, NoSymbol ] }; + key { [ w, W, NoSymbol, Greek_omega, NoSymbol, NoSymbol, Greek_OMEGA, NoSymbol ] }; + key { [ e, E, NoSymbol, Greek_epsilon, NoSymbol, NoSymbol, U2203, NoSymbol ] }; + key { [ r, R, NoSymbol, Greek_rho, NoSymbol, NoSymbol, U211D, NoSymbol ] }; + key { [ t, T, NoSymbol, Greek_tau, NoSymbol, NoSymbol, partialderivative, NoSymbol ] }; + key { [ z, Z, NoSymbol, Greek_zeta, NoSymbol, NoSymbol, U2124, NoSymbol ] }; + key { [ u, U, NoSymbol, NoSymbol, NoSymbol, NoSymbol, includedin, NoSymbol ] }; + key { [ i, I, NoSymbol, Greek_iota, NoSymbol, NoSymbol, integral, NoSymbol ] }; + key { [ o, O, NoSymbol, Greek_omicron, NoSymbol, NoSymbol, elementof, NoSymbol ] }; + key { [ p, P, NoSymbol, Greek_pi, NoSymbol, NoSymbol, Greek_PI, NoSymbol ] }; + key { [ udiaeresis, Udiaeresis, NoSymbol, NoSymbol, NoSymbol, NoSymbol, union, NoSymbol ] }; + key { [ a, A, NoSymbol, Greek_alpha, NoSymbol, NoSymbol, U2200, NoSymbol ] }; + key { [ s, S, NoSymbol, Greek_sigma, NoSymbol, NoSymbol, Greek_SIGMA, NoSymbol ] }; + key { [ d, D, NoSymbol, Greek_delta, NoSymbol, NoSymbol, Greek_DELTA, NoSymbol ] }; + key { [ f, F, NoSymbol, Greek_phi, NoSymbol, NoSymbol, Greek_PHI, NoSymbol ] }; + key { [ g, G, NoSymbol, Greek_gamma, NoSymbol, NoSymbol, Greek_GAMMA, NoSymbol ] }; + key { [ h, H, NoSymbol, Greek_psi, NoSymbol, NoSymbol, Greek_PSI, NoSymbol ] }; + key { [ j, J, NoSymbol, Greek_theta, NoSymbol, NoSymbol, Greek_THETA, NoSymbol ] }; + key { [ k, K, NoSymbol, Greek_kappa, NoSymbol, NoSymbol, multiply, NoSymbol ] }; + key { [ l, L, NoSymbol, Greek_lambda, NoSymbol, NoSymbol, Greek_LAMBDA, NoSymbol ] }; + key { [ odiaeresis, Odiaeresis, NoSymbol, U03F5, NoSymbol, NoSymbol, intersection, NoSymbol ] }; + key { [ adiaeresis, Adiaeresis, NoSymbol, Greek_eta, NoSymbol, NoSymbol, U2135, NoSymbol ] }; + key { [ y, Y, NoSymbol, Greek_upsilon, NoSymbol, NoSymbol, nabla, NoSymbol ] }; + key { [ x, X, NoSymbol, Greek_xi, NoSymbol, NoSymbol, Greek_XI, NoSymbol ] }; + key { [ c, C, NoSymbol, Greek_chi, NoSymbol, NoSymbol, U2102, NoSymbol ] }; + key { [ v, V, NoSymbol, NoSymbol, NoSymbol, NoSymbol, radical, NoSymbol ] }; + key { [ b, B, NoSymbol, Greek_beta, NoSymbol, NoSymbol, U21D0, NoSymbol ] }; + key { [ n, N, NoSymbol, Greek_nu, NoSymbol, NoSymbol, U2115, NoSymbol ] }; + key { [ m, M, NoSymbol, Greek_mu, NoSymbol, NoSymbol, ifonlyif, NoSymbol ] }; +}; + +partial alphanumeric_keys modifier_keys keypad_keys +xkb_symbols "neo_qwertz" { + + include "de(neo_qwertz_base)" + + name[Group1]= "German (Neo, QWERTZ)"; + + include "shift(both_capslock)" + include "level3(caps_switch)" + include "level3(bksl_switch)" + include "level5(lsgt_switch_lock)" + include "level5(ralt_switch_lock)" +}; + +partial alphanumeric_keys +xkb_symbols "neo_qwerty_base" { + include "de(neo_qwertz_base)" + + key.type[Group1] = "EIGHT_LEVEL_ALPHABETIC_LEVEL_FIVE_LOCK"; + key { [ y, Y, NoSymbol, Greek_upsilon, NoSymbol, NoSymbol, nabla, NoSymbol ] }; + key { [ z, Z, NoSymbol, Greek_zeta, NoSymbol, NoSymbol, U2124, NoSymbol ] }; +}; + +partial alphanumeric_keys modifier_keys keypad_keys +xkb_symbols "neo_qwerty" { + + include "de(neo_qwerty_base)" + + name[Group1]= "German (Neo, QWERTY)"; + + include "shift(both_capslock)" + include "level3(caps_switch)" + include "level3(bksl_switch)" + include "level5(lsgt_switch_lock)" + include "level5(ralt_switch_lock)" +}; + +partial alphanumeric_keys +xkb_symbols "lld" { + include "de(basic)" + name[Group1] = "German (Ladin)"; + + key { [ p, P, ediaeresis, Ediaeresis ] }; +}; diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/de_simple b/developer/src/kmc-convert/test/data/tests-xkb-kmn/de_simple index 61a0b63eb74..9462df4c08e 100644 --- a/developer/src/kmc-convert/test/data/tests-xkb-kmn/de_simple +++ b/developer/src/kmc-convert/test/data/tests-xkb-kmn/de_simple @@ -30,7 +30,7 @@ xkb_symbols "basic" { key { [ p, P, thorn, THORN ] }; key { [udiaeresis, Udiaeresis, NoSymbol, NoSymbol ] }; key { [ plus, asterisk, asciitilde, macron ] }; - + key { [ a, A, ae, AE ] }; key { [ s, S, ssharp, section ] }; key { [ d, D, eth, ETH ] }; diff --git a/developer/src/kmc-convert/test/kmc-convert-convert/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/kmc-convert-convert/keylayout-to-kmn-converter.tests.ts index ac2c8002c03..c74789e9fdd 100644 --- a/developer/src/kmc-convert/test/kmc-convert-convert/keylayout-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/kmc-convert-convert/keylayout-to-kmn-converter.tests.ts @@ -6,6 +6,7 @@ * Tests for KeylayoutToKmnConverter, KeylayoutFileReader, KmnFileWriter * */ +/* import 'mocha'; import { assert } from 'chai'; import * as NodeAssert from 'node:assert'; @@ -806,4 +807,4 @@ describe('KeylayoutToKmnConverter', function () { }); }); -}); +});*/ diff --git a/developer/src/kmc-convert/test/kmc-convert-convert/xkb-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/kmc-convert-convert/xkb-to-kmn-converter.tests.ts index 278254743a3..ac501cdc63d 100644 --- a/developer/src/kmc-convert/test/kmc-convert-convert/xkb-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/kmc-convert-convert/xkb-to-kmn-converter.tests.ts @@ -8,11 +8,11 @@ */ import 'mocha'; import { assert } from 'chai'; -import * as NodeAssert from 'node:assert'; +//import * as NodeAssert from 'node:assert'; import { compilerTestCallbacks, compilerTestOptions, makePathToFixture } from './../helpers/index.js'; -import { ActionStateOutput, KeylayoutFileData, XkbToKmnConverter, Rule } from '../../src/kmc-convert-convert/xkb-to-kmn-converter.js'; -import { XkbFileReader } from '../../src/kmc-convert-read/xkb-file-reader.js'; -import { ConverterMessages } from '../../src/converter-messages.js'; +import { /*ActionStateOutput, KeylayoutFileData,*/ XkbToKmnConverter/*, Rule */} from '../../src/kmc-convert-convert/xkb-to-kmn-converter.js'; +//import { XkbFileReader } from '../../src/kmc-convert-read/xkb-file-reader.js'; +//import { ConverterMessages } from '../../src/converter-messages.js'; describe('XkbToKmnConverter', function () { @@ -23,29 +23,8 @@ describe('XkbToKmnConverter', function () { describe('Xkb-kmn: RunSpecialTestFiles', function () { const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); [ - [makePathToFixture('../data/tests-xkb-kmn/Test_C0.keylayout')], - [makePathToFixture('../data/tests-xkb-kmn/Test_C1.keylayout')], - [makePathToFixture('../data/tests-xkb-kmn/Test_C2.keylayout')], - [makePathToFixture('../data/tests-xkb-kmn/Test_C2_several.keylayout')], - [makePathToFixture('../data/tests-xkb-kmn/Test_C3.keylayout')], - [makePathToFixture('../data/tests-xkb-kmn/Test_C3_several.keylayout')], - [makePathToFixture('../data/tests-xkb-kmn/Test_C0_C1_C2_C3.keylayout')], - [makePathToFixture('../data/tests-xkb-kmn/Test_maxKeyCode.keylayout')], - [makePathToFixture('../data/tests-xkb-kmn/Test_messages.keylayout')], - [makePathToFixture('../data/tests-xkb-kmn/Test_messages_controlCharacter.keylayout')], - [makePathToFixture('../data/tests-xkb-kmn/Test_messages_superior_C2.keylayout')], - [makePathToFixture('../data/tests-xkb-kmn/Test_messages_superior_C3.keylayout')], - [makePathToFixture('../data/tests-xkb-kmn/Test_duplicate_missing_keycode.keylayout')], - [makePathToFixture('../data/tests-xkb-kmn/Test_modifier.keylayout')], - [makePathToFixture('../data/tests-xkb-kmn/Test_modifierNoCaps.keylayout')], - [makePathToFixture('../data/tests-xkb-kmn/Test_differentAmountOfKeysInBehaviours.keylayout')], - [makePathToFixture('../data/tests-xkb-kmn/Test_duplicate_missing_keys.keylayout')], - [makePathToFixture('../data/tests-xkb-kmn/Test_duplicate_keys.keylayout')], - [makePathToFixture('../data/tests-xkb-kmn/Test_ambiguous_keys.keylayout')], - [makePathToFixture('../data/tests-xkb-kmn/Test_nr_elements.keylayout')], - [makePathToFixture('../data/tests-xkb-kmn/Test.keylayout')], - [makePathToFixture('../data/tests-xkb-kmn/Test_differentEncodings.keylayout')], - [makePathToFixture('../data/tests-xkb-kmn/Test_ExtraWarning.keylayout')], + [makePathToFixture('../data/tests-xkb-kmn/de_simple')], + [makePathToFixture('../data/tests-xkb-kmn/test_xkb_differentEncodings')], ].forEach(function (files) { it(files + " should give no errors ", async function () { sut.run(files[0]); @@ -53,7 +32,7 @@ describe('XkbToKmnConverter', function () { }); }); }); - +/* describe('Xkb-kmn: RunTestFiles resulting in errors ', function () { const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); [ @@ -151,8 +130,9 @@ describe('XkbToKmnConverter', function () { assert.equal(compilerTestCallbacks.messages.length, 0); }); }); - }); - + });*/ + ///////////////////////////////////////////////////////////// +/* describe('Xkb-kmn: convert() ', function () { const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sutR = new XkbFileReader(compilerTestCallbacks); @@ -802,5 +782,5 @@ describe('XkbToKmnConverter', function () { }); }); }); - +*/ }); diff --git a/developer/src/kmc-convert/test/kmc-convert-read/kmn-file-reader.tests.ts b/developer/src/kmc-convert/test/kmc-convert-read/kmn-file-reader.tests.ts index a8ad780f375..ad7ef9fc6b3 100644 --- a/developer/src/kmc-convert/test/kmc-convert-read/kmn-file-reader.tests.ts +++ b/developer/src/kmc-convert/test/kmc-convert-read/kmn-file-reader.tests.ts @@ -6,7 +6,7 @@ * Tests for KeylayoutToKmnConverter, KeylayoutFileReader, KmnFileWriter * */ - +/* import 'mocha'; import { assert } from 'chai'; import { compilerTestCallbacks, makePathToFixture } from './../helpers/index.js'; @@ -49,4 +49,4 @@ describe('KeylayoutFileReader', function () { }); }); -}); +});*/ diff --git a/developer/src/kmc-convert/test/kmc-convert-read/xkb-file-reader.tests.ts b/developer/src/kmc-convert/test/kmc-convert-read/xkb-file-reader.tests.ts index 6f418de2435..e09a85f797a 100644 --- a/developer/src/kmc-convert/test/kmc-convert-read/xkb-file-reader.tests.ts +++ b/developer/src/kmc-convert/test/kmc-convert-read/xkb-file-reader.tests.ts @@ -22,11 +22,11 @@ describe('XkbFileReader', function () { const sutR = new XkbFileReader(compilerTestCallbacks); it('read() should return filled array on correct input', async function () { - const inputFilename = makePathToFixture('../data/tests-xkb-kmn/Test.xkb'); + const inputFilename = makePathToFixture('../data/tests-xkb-kmn/de_simple'); const result = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); assert.isNotEmpty(result); }); - +/* it('read() should return empty array on empty input', async function () { const result = sutR.read(compilerTestCallbacks.loadFile("")); assert.isNull(result); @@ -46,7 +46,7 @@ describe('XkbFileReader', function () { it('read() should return empty array on typo in path', async function () { const result = sutR.read(compilerTestCallbacks.loadFile(makePathToFixture('../data|Test.xkb'))); assert.isNull(result); - }); + });*/ }); }); diff --git a/developer/src/kmc-convert/test/kmc-convert-write/kmn-file-writer.tests.ts b/developer/src/kmc-convert/test/kmc-convert-write/kmn-file-writer.tests.ts index d4abee2ab62..8749030915e 100644 --- a/developer/src/kmc-convert/test/kmc-convert-write/kmn-file-writer.tests.ts +++ b/developer/src/kmc-convert/test/kmc-convert-write/kmn-file-writer.tests.ts @@ -6,7 +6,7 @@ * Tests for KeylayoutToKmnConverter, KeylayoutFileReader, KmnFileWriter * */ - +/* import 'mocha'; import { assert } from 'chai'; import KEYMAN_VERSION from "@keymanapp/keyman-version"; @@ -81,14 +81,7 @@ describe('KmnFileWriter', function () { ["ẘẈ", "ẘẈ"], ["😎😆", '😎😆'], ["aሴ😆", 'aሴ😆'], - /* - ["U+0061", 'a'], - ["U+1234", 'ሴ'], - ["U+1E9A", "ẚ"], - ["U+1F60A", '😊'], - ["U+0001", '\u0001'], - ["U+1000000;", undefined], - */ + ["a", 'a'], ["ሴ", 'ሴ'], ["ẘ", "ẘ"], @@ -113,18 +106,7 @@ describe('KmnFileWriter', function () { ["", ''], [undefined, undefined], [null, undefined], - /* - ["U+", undefined], - ['U+', undefined], - ['U+U+', undefined], - ['U+D799', '힙'], - ['U+D800', undefined], - ['U+D83D', undefined], - ['U+DFFF', undefined], - ['U+10FFFF', '􏿿'], - ['U+E000', ''], - ['U+1000000', undefined], - */ + ['&', '&'], ['&;', '&;'], ['&&', '&&'], @@ -155,11 +137,7 @@ describe('KmnFileWriter', function () { ["😆", '😆'], ["", '\u0003'], ["󴉀", '󴉀'], - /*["U+0061", 'a'], - ["U+1234", 'ሴ'], - ["U+1F60E", '😎'], - ["U+0001", '\u0001'], - ["U+1000000;", undefined],*/ + ["@", undefined], ["a", 'a'], ["ሴ", 'ሴ'], @@ -422,7 +400,7 @@ describe('KmnFileWriter', function () { const sutW = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); [ [ - [ /* see ../data/Test_C0.keylayout */ + [ // see ../data/Test_C0.keylayout / new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_A', new TextEncoder().encode('a')), new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_A', new TextEncoder().encode('A')), new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_S', new TextEncoder().encode('s')), @@ -434,7 +412,7 @@ describe('KmnFileWriter', function () { "+ [NCAPS K_D] > 'd'\n"] ], [ - [ /* see ../data/Test_C1.keylayout */ + [ // see ../data/Test_C1.keylayout / new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_S', new TextEncoder().encode('s')), new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_S', new TextEncoder().encode('S')) ], @@ -442,14 +420,14 @@ describe('KmnFileWriter', function () { "+ [CAPS K_S] > 'S'\n"] ], [ - [ /* see ../data/Test_C2.keylayout */ + [ // see ../data/Test_C2.keylayout / new Rule("C2", '', '', 0, 0, 'NCAPS', 'K_U', 1, 1, 'CAPS', 'K_A', new TextEncoder().encode('Â')) ], ["+ [NCAPS K_U] > dk(A1)\n" + "dk(A1) + [CAPS K_A] > 'Â'\n\n"] ], [ - [ /* see ../data/Test_C3.keylayout */ + [ // see ../data/Test_C3.keylayout / new Rule("C3", 'NCAPS SHIFT', 'K_D', 2, 1, 'NCAPS', 'K_U', 1, 2, 'CAPS', 'K_A', new TextEncoder().encode('Â')) ], ["+ [NCAPS SHIFT K_D] > dk(A2)\n" + @@ -458,7 +436,7 @@ describe('KmnFileWriter', function () { ] ], [ - [ /* see ../data/Test_C0_C1_C2_C3.keylayout */ + [ // see ../data/Test_C0_C1_C2_C3.keylayout / new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_A', new TextEncoder().encode('A')), new Rule("C2", '', '', 0, 0, 'NCAPS RALT', 'K_EQUAL', 1, 1, 'CAPS', 'K_D', new TextEncoder().encode('Â')), new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_S', new TextEncoder().encode('S')), @@ -492,7 +470,7 @@ describe('KmnFileWriter', function () { "dk(B5) + [CAPS K_D] > 'Â'\n\n"] ], [ - [ /* see ../data/Test_C3_several.keylayout */ + [ // see ../data/Test_C3_several.keylayout / new Rule("C3", 'NCAPS RALT', 'K_8', 3, 1, 'CAPS', 'K_U', 1, 3, 'NCAPS', 'K_A', new TextEncoder().encode('â')), new Rule("C3", 'NCAPS RALT', 'K_8', 3, 0, 'CAPS', 'K_U', 1, 0, 'NCAPS RALT', 'K_A', new TextEncoder().encode('â')), new Rule("C3", 'NCAPS RALT', 'K_8', 3, 0, 'NCAPS RALT', 'K_U', 2, 2, 'NCAPS', 'K_A', new TextEncoder().encode('â')), @@ -522,3 +500,4 @@ describe('KmnFileWriter', function () { }); }); +*/ \ No newline at end of file From 8ca83a1035ac8228f699446e5ca4757063874cc6 Mon Sep 17 00:00:00 2001 From: Sabine Date: Fri, 8 May 2026 19:22:29 +0200 Subject: [PATCH 247/251] feat(developer): first functional version --- .../xkb-to-kmn-converter.ts | 1312 +++++++---------- .../src/kmc-convert-read/xkb-file-reader.ts | 15 +- .../src/kmc-convert-write/kmn-file-writer.ts | 31 +- 3 files changed, 603 insertions(+), 755 deletions(-) diff --git a/developer/src/kmc-convert/src/kmc-convert-convert/xkb-to-kmn-converter.ts b/developer/src/kmc-convert/src/kmc-convert-convert/xkb-to-kmn-converter.ts index 015d4027c5b..40742d22431 100644 --- a/developer/src/kmc-convert/src/kmc-convert-convert/xkb-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/kmc-convert-convert/xkb-to-kmn-converter.ts @@ -7,7 +7,24 @@ * */ -import { CompilerCallbacks, CompilerOptions, KeymanCompilerResult, Keylayout } from "@keymanapp/developer-utils"; + + +/* + ToDo kmc-convert (list): + - check for correct function comments + - function names + - any + - return types + - squiggles + - remove comments + - remove unused functions + - add warning/errormessages + + + +*/ + +import { CompilerCallbacks, CompilerOptions, KeymanCompilerResult } from "@keymanapp/developer-utils"; import { KmnFileWriter } from './../kmc-convert-write/kmn-file-writer.js'; import { XkbFileReader } from './../kmc-convert-read/xkb-file-reader.js'; import { ConverterMessages } from '../converter-messages.js'; @@ -40,30 +57,6 @@ export interface ProcessedData { rules: Rule[]; }; -export interface KeylayoutFileData { - /** - * Interface for storing data read from a .keylayout file and used for processing rules. - * These are used for obtaining one entity form the other (e.g. from action id to output, from keycode to modifier, etc.) - */ - actionId?: string; - keyCode?: string; - key?: string; - behavior: string; - modifier?: string; - outchar?: string; -}; - -export interface ActionStateOutput { - /** - * Interface for storing data read from a .keylayout file and used for processing rules. - * These are used for obtaining the triplet [action id, state, output] - * e.g. ['a9','1','â'] from for action id a9 - */ - id: string; - state: string; - output: string; -}; - /** * @brief class for all storing a rule containing data for key, deadkey, previous deadkey, output) */ @@ -107,37 +100,31 @@ export class XkbToKmnConverter { * @param outputFilename the resulting keyman .kmn-file * @return null on success */ - async run(inputFilename: string, outputFilename?: string): Promise { - + async run(inputFilename: string, outputFilename?: string): Promise { if (!inputFilename) { this.callbacks.reportMessage(ConverterMessages.Error_FileNotFound({ inputFilename })); return null; } - const KeylayoutReader = new XkbFileReader(this.callbacks/*, this.options*/); + const XkbReader = new XkbFileReader(this.callbacks/*, this.options*/); const binaryData = this.callbacks.loadFile(inputFilename); - const jsonO: Keylayout.KeylayoutXMLSourceFile = KeylayoutReader.read(binaryData); + const xkb_data = XkbReader.read(binaryData); - if (!jsonO) { + if (!xkb_data) { this.callbacks.reportMessage(ConverterMessages.Error_UnableToReadFile({ inputFilename: inputFilename })); return null; } - try { - if (!KeylayoutReader.validate(jsonO, inputFilename)) { - return null; - } - } catch (e) { - this.callbacks.reportMessage(ConverterMessages.Error_InvalidFile({ errorText: e.toString() })); - return null; - } - const processedData = await this.convert(jsonO, inputFilename, outputFilename); + const processedData = await this.convert(xkb_data, inputFilename, outputFilename); const kmnFileWriter = new KmnFileWriter(this.callbacks, this.options); + // ToDo-kmc-convert remove writeToFile + kmnFileWriter.writeToFile(processedData as ProcessedData); + // write to object/ConverterToKmnResult - const outputKmn = kmnFileWriter.write(processedData); + const outputKmn = kmnFileWriter.write(processedData as ProcessedData); const result: ConverterToKmnResult = { artifacts: { kmn: { data: outputKmn, filename: processedData.kmnFilename } @@ -151,12 +138,63 @@ export class XkbToKmnConverter { * @param jsonObj containing filename, behaviorand rules of a json object * @return an ProcessedData containing all data ready to print out */ - private convert(jsonObj: Keylayout.KeylayoutXMLSourceFile, inputfilename: string, outputFilename?: string): ProcessedData { - // modifiers for each behavior - const modifierBehavior: string[][] = []; + private createArrayOfModifier(xkb_data?: string): string[][] { + // ToDo-kmc-convert write createArrayOfModifier() + /* - // an array of data for a kmn rule - const rules: Rule[] = []; + theory xkb: what is hidden? + + can either be written for 1 key: within key {} ) + key { + type[Group1]="PC_ALT_LEVEL2", + symbols[Group1]= [ Henkan, Mode_switch ] + }; + + or for a group: within {} + hidden partial alphanumeric_keys + xkb_symbols "oldhun_lig" { + + key.type[Group1]="FOUR_LEVEL_ALPHABETIC"; + + key {[ U200D, U200F, U200C, 0 ]}; + //Zero-width-joiner,Right to left mark, Zero-width-non-joiner + //Zero-width-joiner and Zero-width-non-joiner are reqired for ligatures + key {[ U10CFA, apostrophe, U2E42, 1 ]}; + //Old Hungarian one, reversed 9 double low quotemark + key {[ U10CFB, quotedbl, U201F, 2 ]}; + }; + + find these lines in xkb file and extract number of, names and type of shiftstates + + key {type[Group1]="FOUR_LEVEL_PLUS_LOCK", symbols[Group1]= + [ssharp, question, backslash, questiondown, 0x1001E9E ]}; + // ToDo-kmc-convert fill array according to group type: + key {type[Group1]="FOUR_LEVEL_PLUS_LOCK", symbols[Group1]= [ssharp, question, backslash, questiondown, 0x1001E9E ]}; + -> [ "", "SHIFT", "RALT", "SHIFT RALT","CAPS SHIFT RALT" ] + (is it really "CAPS SHIFT RALT" ) + see + ONE_LEVEL + TWO_LEVEL + ALPHABETIC + THREE_LEVEL + FOUR_LEVEL + FOUR_LEVEL_ALPHABETIC + */ + + // also remenmber: checkIfCapsIsUsed + + const modi1D: string[] = ["", "SHIFT", "RALT", "SHIFT RALT"]; + const modi2D: string[][] = []; + + modi2D.push(modi1D); + return modi2D; + } + + private convert(xkb_data: string, inputfilename: string, outputFilename?: string): ProcessedData | null { + + if (!xkb_data) { + return null; + } // dataObject for all relevant data const dataObject: ProcessedData = { @@ -166,77 +204,94 @@ export class XkbToKmnConverter { rules: [] }; - if (jsonObj === null) { - return null; - } - // create an array of modifier combinations and store in dataObject - for (let j = 0; j < jsonObj.keyboard.modifierMap[0].keyMapSelect.length; j++) { - const singleModifierSet: string[] = []; - for (let k = 0; k < jsonObj.keyboard.modifierMap[0].keyMapSelect[j].modifier.length; k++) { - singleModifierSet.push(jsonObj.keyboard.modifierMap[0].keyMapSelect[j].modifier[k]['keys']); - } - modifierBehavior.push(singleModifierSet); - } - // fill dataObject with filenames, behaviors and (initialized) rules dataObject.keylayoutFilename = inputfilename; if (!outputFilename) - dataObject.kmnFilename = inputfilename.replace(/\.keylayout$/, '.kmn'); + dataObject.kmnFilename = inputfilename + '.kmn'; else dataObject.kmnFilename = outputFilename; - dataObject.modifiers = modifierBehavior; // ukelele uses behaviors e.g. 18 modifiersCombinations in 8 KeyMapSelect(behaviors) - dataObject.rules = rules; // fill rules into 'rules' of dataObject - return this.createRuleData(dataObject, jsonObj); + const out = this.createRuleData(dataObject, xkb_data); + return out; } + /** + * @brief member function to find the appopriate paragraph between "xkb_symbol " and the next xkb_symbol + * @param xkbData: an string containing the contents of the xkb file + * @return the paragraph of the xkb ffr the specified data + */ + public findParagraph(xkbData: string): string { + // ToDo-kmc-convert edit this function + // in the Configuration file we find the appopriate paragraph between "xkb_symbol " and the next xkb_symbol + return xkbData; + } + + /** + * @brief member function to extract all lines starting with with '' from input data + * @param xkbData: an string containing the contents of the xkb file + * @return an array of lines containing key - output pairs. + */ + public createCompleteLines(xkbData: string): string[] { + + // in the Configuration file we find the appopriate paragraph between "xkb_symbol " and the next xkb_symbol + // then copy all rows starting with "key <" to a 1D-Vector + + // ToDo-kmc-convert find appropriate parapraph + const paragraph = this.findParagraph(xkbData); + if (!paragraph) + console.log('ToDo-kmc-convert add Err-msg findParagraph'); + + // ToDo-kmc-convert remove + // key { [ 1, exclam, onesuperior, exclamdown ] }; // extract data from 1 line: + // 'AE01> { [ 1, exclam, onesuperior, exclamdown ] }; ' // use only lines that start with ' {[' and remove 'key' + // ',1,exclam,onesuperior,exclamdown' // remove whitespace etc from line + const lineArray = []; + const lines = xkbData.split("key <"); + for (let i = 0; i < lines.length; i++) { + if ((lines[i].indexOf('{') >= 6) && (lines[i].indexOf('[') >= 7)) { + lineArray.push('<' + lines[i].replaceAll(/[\s{[,;}\]]+/g, ',').slice(0, -1)); + } + } + return lineArray; + } + + /** * @brief member function to read the rules contained in a json object and add array of Rules[] to an ProcessedData * @param dataUkelele: an object containing the name of the in/output file, an array of behaviors and an (empty) array of Rules - * @param jsonObj: json Object containing all data read from a keylayout file + * @param jsonObj: json Object containing all da + * ta read from a keylayout file * @return an object containing the name of the input file, an array of behaviors and a populated array of Rules[] */ - public createRuleData(dataUkelele: ProcessedData, jsonObj: Keylayout.KeylayoutXMLSourceFile): ProcessedData { - - const rules: Rule[] = []; - let dkCounterC3: number = 0; - let dkCounterC2: number = 0; - let actionId: string; + public createRuleData(dataObject: ProcessedData, xkb_data: string): ProcessedData { - // check if we use CAPS in a modifier throughout the .keylayout file. In this case we need to add NCAPS - const isCapsused = (this.checkIfCapsIsUsed(dataUkelele.modifiers)); - - for (let j = 0; j <= XkbToKmnConverter.MAX_KEY_IDENTIFIER; j++) { + // create an array of modifier combinations and store in dataObject + // ToDo-kmc-convert edit function (hard coded at present) + dataObject.modifiers = this.createArrayOfModifier(xkb_data); - // loop behaviors (in ukelele it is possible to define multiple modifier combinations that behave in the same way) - for (let i = 0; i < jsonObj.keyboard.keyMapSet[0].keyMap.length; i++) { - // if index of keys and behaviors exist - const isItAvailable = ((j < jsonObj.keyboard.keyMapSet[0].keyMap[i].key.length) && (i < jsonObj.keyboard.keyMapSet[0].keyMap.length)); - if (!isItAvailable) { - continue; - } + //....................... extract complete lines to array ....................... + //....................... e.g. ',1,exclam,onesuperior,exclamdown', ....... + //............................................................................... - let ruleObj: Rule; + const lines = this.createCompleteLines(xkb_data); + if (!lines) + console.log("ToDo-kmc-convert add ErrorMsg"); - if (j < jsonObj.keyboard.keyMapSet[0].keyMap[i].key.length) { - // ............................................................................................................................... - // case C0: output ............................................................................................................... - // C0 see: https://docs.google.com/document/d/12J3NGO6RxIthCpZDTR8FYSRjiMgXJDLwPY2z9xqKzJ0/edit?tab=t.0#heading=h.g7jwx3lx0ydd ... - // a key is mapped to a character directly ( code -> output) ..................................................................... - // ...............e. g. ............................................................................... - // ............................................................................................................................... + //....................... create a Rule and save to ruleObj ....................... + //................................................................................. + //................................................................................. + const rules: Rule[] = []; - if ((jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['output'] !== undefined) - && (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['output'] !== "")) { + for (let i = 0; i < lines.length; i++) { - // loop modifiers - for (let l = 0; l < dataUkelele.modifiers[i].length; l++) { + // split / seperate keyname and outputs + const elements = lines[i].split(","); - if (this.mapUkeleleKeycodeToVK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['code']))) { + for (let j = 1; j < elements.length; j++) { - ruleObj = new Rule( + const ruleObj = new Rule( /* ruleType */ "C0", /* modifierPrevDeadkey*/ "", @@ -248,255 +303,429 @@ export class XkbToKmnConverter { /* deadkey */ "", /* dk for C2*/ 0, /* unique B */ 0, + /* modifierKey*/ dataObject.modifiers[0][j - 1], + /* key */ this.get_KMVirtKC_from_keyname(elements[0]), + // ToDo-kmc-convert convert outputnames to output e.g. 'exclam' -> '!' + /* output */ new TextEncoder().encode(this.get_Output_FromOutputname(elements[j])) + ); + rules.push(ruleObj); + } + } + dataObject.rules = rules; + return this.reviewRuleInputData(dataObject); + } - /* modifierKey*/ this.createKmnModifier(dataUkelele.modifiers[i][l], isCapsused), - /* key */ this.mapUkeleleKeycodeToVK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['code'])), - /* output */ new TextEncoder().encode(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['output']), - ); - rules.push(ruleObj); - } - } + /** + * @brief convert the key name obtained from symbol file to the matching keyname e.g. name of key --> 'K_A' + *@param key_name as stated in the symbol file + * @return the equivalent keyman virtual keycode + */ + public get_KMVirtKC_from_keyname(key_name: string): string { + let out = ''; + + if (key_name == "") + out = 'K_BKQUOTE'; + else if (key_name == "") + out = 'K_1'; + else if (key_name == "") + out = 'K_2'; + else if (key_name == "") + out = 'K_3'; + else if (key_name == "") + out = 'K_4'; + else if (key_name == "") + out = 'K_5'; + else if (key_name == "") + out = 'K_6'; + else if (key_name == "") + out = 'K_7'; + else if (key_name == "") + out = 'K_8'; + else if (key_name == "") + out = 'K_9'; + else if (key_name == "") + out = 'K_0'; + else if (key_name == "") + out = 'K_HYPHEN'; + else if (key_name == "") + out = 'K_EQUAL'; + else if (key_name == "") + out = 'K_Q'; + else if (key_name == "") + out = 'K_W'; + else if (key_name == "") + out = 'K_E'; + else if (key_name == "") + out = 'K_R'; + else if (key_name == "") + out = 'K_T'; + else if (key_name == "") + out = 'K_Y'; + else if (key_name == "") + out = 'K_U'; + else if (key_name == "") + out = 'K_I'; + else if (key_name == "") + out = 'K_O'; + else if (key_name == "") + out = 'K_P'; + else if (key_name == "") + out = 'K_LBRKT'; + else if (key_name == "") + out = 'K_RBRKT'; + + else if (key_name == "") + out = 'K_A'; + else if (key_name == "") + out = 'K_S'; + else if (key_name == "") + out = 'K_D'; + else if (key_name == "") + out = 'K_F'; + else if (key_name == "") + out = 'K_G'; + else if (key_name == "") + out = 'K_H'; + else if (key_name == "") + out = 'K_J'; + else if (key_name == "") + out = 'K_K'; + else if (key_name == "") + out = 'K_L'; + else if (key_name == "") + out = 'K_COLON'; + else if (key_name == "") + out = 'K_QUOTE'; + + else if (key_name == "") + out = 'K_Z'; + else if (key_name == "") + out = 'K_X'; + else if (key_name == "") + out = 'K_C'; + else if (key_name == "") + out = 'K_V'; + else if (key_name == "") + out = 'K_B'; + else if (key_name == "") + out = 'K_N'; + else if (key_name == "") + out = 'K_M'; + else if (key_name == "") + out = 'K_COMMA'; + else if (key_name == "") + out = 'K_PERIOD'; + else if (key_name == "") + out = 'K_SLASH'; + else if (key_name == "") + out = 'K_BKSLASH'; + else if (key_name == "") + out = 'K_RIGHTSHIFT'; + else if (key_name == "") + out = 'K_SPACE'; + + return String(out); + } - } - else if (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['action'] !== undefined) { - - actionId = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['action'] ?? ""; - // ............................................................................................................................... - // case C1: action + state none + output ......................................................................................... - // C1 see: https://docs.google.com/document/d/12J3NGO6RxIthCpZDTR8FYSRjiMgXJDLwPY2z9xqKzJ0/edit?tab=t.0#heading=h.g7jwx3lx0ydd ... - // a key is mapped to an action and then to an output ............................................................................ - // KeyMap:code -> KeyMap:action->action:actionState(none) -> actionOutput ...................................................... - // ...............e. g. ............................................................................ - // replace state x with all rules that result in 14 ( for action id a18 ...................................................................................................................... - if (jsonObj.keyboard.actions?.action?.[b1ActionIndex]?.when) { - for (const when of jsonObj.keyboard.actions.action[b1ActionIndex].when) { - if ((when['state'] === "none") // find "none" - && (when['next'] !== undefined)) { // find "next" - - // Data of Block Nr 5 ..................................................................................................................................................................... - // of this state(none)-next-pair get value of next (next="1") ............................................................................................................................. - /* eg: 1 */ const b5ValueNext: string = when['next']; - // ........................................................................................................................................................................................ - - - // Data of Block Nr 4 ..................................................................................................................................................................... - // with present actionId (a18) find all keycode-behavior-pairs that use this action (a18) => (keymapIndex 0/keycode 24 and keymapIndex 3/keycode 24) .................................... - // from these create an array of modifier combinations e.g. [['','caps?'], ['Caps']] ..................................................................................................... - /* eg: [['24', 0], ['24', 3]] */ const b4DeadkeyObj: KeylayoutFileData[] = this.getKeyModifierArrayFromActionID(jsonObj, actionId); - /* e.g. [['','caps?'], ['Caps']]*/ const b4DeadkeyModifierObj: string[][] = this.getModifierArrayFromKeyModifierArray(dataUkelele.modifiers, b4DeadkeyObj); - // ........................................................................................................................................................................................ - - - // Data of Block Nr 6 ..................................................................................................................................................................... - // create an array[action id,state,output] from all state-output-pairs that use state = b5ValueNext (e.g. use 1 in ) ...................................... - /* eg: [ 'a9','1','â'] */ const b6ActionIdObj: ActionStateOutput[] = this.getActionStateOutputArrayFromActionState(jsonObj, b5ValueNext); - // ........................................................................................................................................................................................ - - - // Data of Block Nr 1 .................................................................................................................................................................... - // create array[Keycode,Keyname,action id,actionIndex,output] and array[Keyname,action id,behavior,modifier,output] ...................................................................... - /* eg: ['0','K_A','a9','0','â'] */ const b1KeycodeObj: KeylayoutFileData[] = this.getKeyActionOutputArrayFromActionStateOutputArray(jsonObj, b6ActionIdObj); - /* eg: ['K_A','a9','0','NCAPS','â']*/ const b1ModifierKeyObj: KeylayoutFileData[] = this.getKeyBehaviorModOutputArrayFromKeyActionBehaviorOutputArray(jsonObj, b1KeycodeObj, isCapsused); - // ....................................................................................................................................................................................... - - for (let n1 = 0; n1 < b4DeadkeyModifierObj.length; n1++) { - for (let n2 = 0; n2 < b4DeadkeyModifierObj[n1].length; n2++) { - for (let n3 = 0; n3 < b4DeadkeyObj.length; n3++) { - for (let n4 = 0; n4 < b1ModifierKeyObj.length; n4++) { - - ruleObj = new Rule( - /* ruleType */ "C2", - - /* modifierPrevDeadkey*/ "", - /* prevDeadkey */ "", - /* idPrevDeadkey */ 0, - /* unique A */ 0, - - /* modifierDeadkey */ this.createKmnModifier(b4DeadkeyModifierObj[n1][n2], isCapsused), - /* deadkey */ this.mapUkeleleKeycodeToVK(Number(b4DeadkeyObj[n3].key)), - /* dk for C2*/ dkCounterC2++, - /* unique B */ 0, - - /* modifierKey*/ b1ModifierKeyObj[n4].modifier, - /* key */ b1ModifierKeyObj[n4].key, - /* output */ new TextEncoder().encode(b1ModifierKeyObj[n4].outchar), - ); - if ((b1ModifierKeyObj[n4].outchar !== undefined) - && (b1ModifierKeyObj[n4].outchar !== "undefined") - && (b1ModifierKeyObj[n4].outchar !== "")) { - rules.push(ruleObj); - } - } - } - } - } - } - } - } - - // ............................................................................................................................... - // case C3: action + state Nr + Next ............................................................................................. - // ...............e. g. ................................................................................ - // replace state x with all rules that result in 1 ( for action id a16 ............................................................................................................................. - for (let l = 0; l < jsonObj.keyboard.actions.action[b1ActionIndex].when.length; l++) { - if ((jsonObj.keyboard.actions.action[b1ActionIndex].when[l]['state'] !== "none") - && (jsonObj.keyboard.actions.action[b1ActionIndex].when[l]['next'] !== undefined)) { - - // Data of Block Nr 5 ........................................................................................................................................................................ - // of this state-next-pair get value of next (next="1") and state="3" ........................................................................................................................ - /* e.g. state = 3 */ const b5ValueState: string = jsonObj.keyboard.actions.action[b1ActionIndex].when[l]['state']; - /* e.g. next = 1 */ const b5ValueNext: string = jsonObj.keyboard.actions.action[b1ActionIndex].when[l]['next']; - // ........................................................................................................................................................................................... - - // Data of Block Nr 4 ........................................................................................................................................................................ - // with present actionId (a16) find all keycode-behavior-pairs that use this action (a16) => (keymapIndex 3/keycode 32) .................................................................... - // from these create an array of modifier combinations e.g. [ [ 'anyOption', 'Caps' ] ] ..................................................................................................... - /* e.g. [['32', 3]] */ const b4DeadkeyObj: KeylayoutFileData[] = this.getKeyModifierArrayFromActionID(jsonObj, actionId); - /* e.g. [ [ 'anyOption', 'Caps' ] ]*/ const b4DeadkeyModifierObj: string[][] = this.getModifierArrayFromKeyModifierArray(dataUkelele.modifiers, b4DeadkeyObj); - // ........................................................................................................................................................................................... - - // Data of Block Nr 3 ........................................................................................................................................................................ - // get an action id from a state-output-pair that use state = b5ValueState (e.g. use 3 in ) ................................................................. - /* e.g. actioniD = a17 */ const b3ActionId: string = this.getActionIdFromActionNext(jsonObj, b5ValueState); - // ........................................................................................................................................................................................... - - // Data of Block Nr 2 ....................................................................................................................................................................... - // with present actionId (a17) find all key names and behaviors that use this action (a17) => (keymapIndex 3/keycode 28) .................................................................... - // from these create an array of modifier combinations e.g. [ [ 'anyOption', 'Caps' ] ] ..................................................................................................... - /* eg: index=3 */ const b2PrevDeadkeyObj: KeylayoutFileData[] = this.getKeyModifierArrayFromActionID(jsonObj, b3ActionId); - /* e.g. [ [ 'anyOption', 'Caps' ] ] */ const b2PrevDeadkeyModifierObj: string[][] = this.getModifierArrayFromKeyModifierArray(dataUkelele.modifiers, b2PrevDeadkeyObj); - // ........................................................................................................................................................................................... - // Data of Block Nr 6 ........................................................................................................................................................................ - // create an array[action id,state,output] from all state-output-pairs that use state = b5ValueNext (e.g. use 1 in ) ......................................... - /* eg:[ [ 'a9','1','â'] ]*/ const b6ActionIdObj: ActionStateOutput[] = this.getActionStateOutputArrayFromActionState(jsonObj, b5ValueNext); /* eg:[ [ 'a9','1','â'] ]*/ - // ........................................................................................................................................................................................... - - // Data of Block Nr 1 ....................................................................................................................................................................... - // create array[Keycode,Keyname,action id,actionIndex,output] and array[Keyname,action id,behavior,modifier,output] ......................................................................... - /* eg: ['49','K_SPACE','a0','0','Â'] */ const b1KeycodeObj: KeylayoutFileData[] = this.getKeyActionOutputArrayFromActionStateOutputArray(jsonObj, b6ActionIdObj); - /* eg: ['K_SPACE','a0','0','NCAPS','Â'] */ const b1ModifierKeyObj: KeylayoutFileData[] = this.getKeyBehaviorModOutputArrayFromKeyActionBehaviorOutputArray(jsonObj, b1KeycodeObj, isCapsused); - // ........................................................................................................................................................................................... - - for (let n1 = 0; n1 < b2PrevDeadkeyModifierObj.length; n1++) { - for (let n2 = 0; n2 < b2PrevDeadkeyModifierObj[n1].length; n2++) { - for (let n3 = 0; n3 < b2PrevDeadkeyObj.length; n3++) { - for (let n4 = 0; n4 < b4DeadkeyModifierObj.length; n4++) { - for (let n5 = 0; n5 < b4DeadkeyModifierObj[n4].length; n5++) { - for (let n6 = 0; n6 < b4DeadkeyObj.length; n6++) { - for (let n7 = 0; n7 < b1ModifierKeyObj.length; n7++) { - - ruleObj = new Rule( - /* ruleType */ "C3", - /* modifierPrevDeadkey*/ this.createKmnModifier(b2PrevDeadkeyModifierObj[n1][n2], isCapsused), - /* prevDeadkey */ this.mapUkeleleKeycodeToVK(Number(b2PrevDeadkeyObj[n3].key)), - /* idPrevDeadkey */ dkCounterC3++, - /* unique A */ 0, - - /* modifierDeadkey */ this.createKmnModifier(b4DeadkeyModifierObj[n4][n5], isCapsused), - /* deadkey */ this.mapUkeleleKeycodeToVK(Number(b4DeadkeyObj[n6].key)), - /* dk for C2*/ 0, - /* unique B */ 0, - - /* modifierKey*/ b1ModifierKeyObj[n7].modifier, - /* key */ b1ModifierKeyObj[n7].key, - /* output */ new TextEncoder().encode(b1ModifierKeyObj[n7].outchar), - ); - if ((b1ModifierKeyObj[n7].outchar !== undefined) - && (b1ModifierKeyObj[n7].outchar !== "undefined") - && (b1ModifierKeyObj[n7].outchar !== "")) { - rules.push(ruleObj); - } - } - } - } - } - } - } - } - } - } - } - } else { - this.callbacks.reportMessage(ConverterMessages.Error_UnsupportedCharactersDetected({ - inputFilename: jsonObj.keyboard['name'] + ".keylayout", - keymapIndex: jsonObj.keyboard.keyMapSet[0].keyMap[i]['index'], - output: jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['output'], - key: jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['code'], - KeyName: this.mapUkeleleKeycodeToVK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['code'])) - })); - return null; - } - } - } + + /** + * @brief convert a keyval name to an output character + more on https://manpages.ubuntu.com/manpages/jammy/man3/keysyms.3tk.html + * @param outchar the name of the output + * @return the input character if input is a character,an empty string if "NoSymbol" is found, + * the output character if found in map, a Warning if not + */ + public get_Output_FromOutputname(outchar: string): string { + + if ((!outchar) || (outchar === "NoSymbol")) + return (''); + // it is already a character + if (outchar.length === 1) + return (outchar); + + if (outchar.slice(0, 2) === "0x") { + console.log(" ToDo-kmc-convert keysym name starting with 0x not found!"); + return '******* keysym name not found! - with 0x '; } - dataUkelele.rules = rules; - return this.reviewRuleInputData(dataUkelele); + + const m_uni = /^U([0-9a-f]{1,6})$/i.exec(outchar); + if (m_uni) { + console.log(" ToDo-kmc-convert keysym name starting with Uxxxx not found!"); + return '******* keysym name not found! - with Uxxxx '; + } + + // ToDo-kmc-convert find a function to lookup values + const key_values = new Map(); + key_values.set("ampersand", 38); + key_values.set("apostrophe", 39); + key_values.set("asciicircum", 136); + key_values.set("asciitilde", 126); + key_values.set("asterisk", 42); + key_values.set("at", 64); + key_values.set("backslash", 92); + key_values.set("BackSpace", 65288); + key_values.set("bar", 124); + key_values.set("braceleft", 123); + key_values.set("braceright", 125); + key_values.set("bracketleft", 91); + key_values.set("bracketright", 93); + key_values.set("colon", 58); + key_values.set("comma", 44); + key_values.set("diaeresis", 168); + key_values.set("dollar", 36); + key_values.set("equal", 61); + key_values.set("exclam", 33); + key_values.set("grave", 96); + key_values.set("greater", 62); + key_values.set("less", 60); + key_values.set("minus", 45); + key_values.set("numbersign", 35); + key_values.set("parenleft", 40); + key_values.set("parenright", 41); + key_values.set("percent", 37); + key_values.set("period", 46); + key_values.set("plus", 43); + key_values.set("question", 63); + key_values.set("quotedbl", 34); + key_values.set("semicolon", 59); + key_values.set("slash", 47); + key_values.set("space", 32); + key_values.set("ssharp", 223); + key_values.set("underscore", 95); + key_values.set("nobreakspace", 160); + key_values.set("exclamdown", 161); + key_values.set("cent", 162); + key_values.set("sterling", 163); + key_values.set("currency", 164); + key_values.set("yen", 165); + key_values.set("brokenbar", 166); + key_values.set("section", 167); + key_values.set("copyright", 169); + key_values.set("ordfeminine", 170); + key_values.set("guillemotleft", 171); + key_values.set("notsign", 172); + key_values.set("hyphen", 173); + key_values.set("registered", 174); + key_values.set("macron", 175); + key_values.set("degree", 176); + key_values.set("plusminus", 177); + key_values.set("twosuperior", 178); + key_values.set("threesuperior", 179); + key_values.set("acute", 180); + key_values.set("mu", 181); + key_values.set("paragraph", 182); + key_values.set("periodcentered", 183); + key_values.set("cedilla", 184); + key_values.set("onesuperior", 185); + key_values.set("masculine", 186); + key_values.set("guillemotright", 187); + key_values.set("onequarter", 188); + key_values.set("onehalf", 189); + key_values.set("threequarters", 190); + key_values.set("questiondown", 191); + key_values.set("Agrave", 192); + key_values.set("Aacute", 193); + key_values.set("Acircumflex", 194); + key_values.set("Atilde", 195); + key_values.set("Adiaeresis", 196); + key_values.set("Aring", 197); + key_values.set("AE", 198); + key_values.set("Ccedilla", 199); + key_values.set("Egrave", 200); + key_values.set("Eacute", 201); + key_values.set("Ecircumflex", 202); + key_values.set("Ediaeresis", 203); + key_values.set("Igrave", 204); + key_values.set("Iacute", 205); + key_values.set("Icircumflex", 206); + key_values.set("Idiaeresis", 207); + key_values.set("ETH", 208); + key_values.set("Ntilde", 209); + key_values.set("Ograve", 210); + key_values.set("Oacute", 211); + key_values.set("Ocircumflex", 212); + key_values.set("Otilde", 213); + key_values.set("Odiaeresis", 214); + key_values.set("multiply", 215); + key_values.set("Oslash", 216); + key_values.set("Ugrave", 217); + key_values.set("Uacute", 218); + key_values.set("Ucircumflex", 219); + key_values.set("Udiaeresis", 220); + key_values.set("Yacute", 221); + key_values.set("THORN", 222); + key_values.set("agrave", 224); + key_values.set("aacute", 225); + key_values.set("acircumflex", 226); + key_values.set("atilde", 227); + key_values.set("adiaeresis", 228); + key_values.set("aring", 229); + key_values.set("ae", 230); + key_values.set("ccedilla", 231); + key_values.set("egrave", 232); + key_values.set("eacute", 233); + key_values.set("ecircumflex", 234); + key_values.set("ediaeresis", 235); + key_values.set("igrave", 236); + key_values.set("iacute", 237); + key_values.set("icircumflex", 238); + key_values.set("idiaeresis", 239); + key_values.set("eth", 240); + key_values.set("ntilde", 241); + key_values.set("ograve", 242); + key_values.set("oacute", 243); + key_values.set("ocircumflex", 244); + key_values.set("otilde", 245); + key_values.set("odiaeresis", 246); + key_values.set("division", 247); + key_values.set("oslash", 248); + key_values.set("ugrave", 249); + key_values.set("uacute", 250); + key_values.set("ucircumflex", 251); + key_values.set("udiaeresis", 252); + key_values.set("yacute", 253); + key_values.set("thorn", 254); + key_values.set("ydiaeresis", 255); + key_values.set("Aogonek", 417); + key_values.set("breve", 418); + key_values.set("Lstroke", 419); + key_values.set("Lcaron", 421); + key_values.set("Sacute", 422); + key_values.set("Scaron", 425); + key_values.set("Scedilla", 426); + key_values.set("Tcaron", 427); + key_values.set("Zacute", 428); + key_values.set("Zcaron", 430); + key_values.set("Zabovedot", 431); + key_values.set("aogonek", 433); + key_values.set("ogonek", 434); + key_values.set("lstroke", 435); + key_values.set("lcaron", 437); + key_values.set("sacute", 438); + key_values.set("caron", 439); + key_values.set("scaron", 441); + key_values.set("scedilla", 442); + key_values.set("tcaron", 443); + key_values.set("zacute", 444); + key_values.set("doubleacute", 445); + key_values.set("zcaron", 446); + key_values.set("zabovedot", 447); + key_values.set("Racute", 448); + key_values.set("Abreve", 451); + key_values.set("Lacute", 453); + key_values.set("Cacute", 454); + key_values.set("Ccaron", 456); + key_values.set("Eogonek", 458); + key_values.set("Ecaron", 460); + key_values.set("Dcaron", 463); + key_values.set("Dstroke", 464); + key_values.set("Nacute", 465); + key_values.set("Ncaron", 466); + key_values.set("Odoubleacute", 469); + key_values.set("Rcaron", 472); + key_values.set("Uring", 473); + key_values.set("Udoubleacute", 475); + key_values.set("Tcedilla", 478); + key_values.set("racute", 480); + key_values.set("abreve", 483); + key_values.set("lacute", 485); + key_values.set("cacute", 486); + key_values.set("ccaron", 488); + key_values.set("eogonek", 490); + key_values.set("ecaron", 492); + key_values.set("dcaron", 495); + key_values.set("dstroke", 496); + key_values.set("nacute", 497); + key_values.set("ncaron", 498); + key_values.set("odoubleacute", 501); + key_values.set("rcaron", 504); + key_values.set("uring", 505); + key_values.set("udoubleacute", 507); + key_values.set("tcedilla", 510); + key_values.set("abovedot", 511); + key_values.set("Hstroke", 673); + key_values.set("Hcircumflex", 678); + key_values.set("Iabovedot", 681); + key_values.set("Gbreve", 683); + key_values.set("Jcircumflex", 684); + key_values.set("hstroke", 689); + key_values.set("hcircumflex", 694); + key_values.set("idotless", 697); + key_values.set("gbreve", 699); + key_values.set("jcircumflex", 700); + key_values.set("Cabovedot", 709); + key_values.set("Ccircumflex", 710); + key_values.set("Gabovedot", 725); + key_values.set("Gcircumflex", 728); + key_values.set("Ubreve", 733); + key_values.set("Scircumflex", 734); + key_values.set("cabovedot", 741); + key_values.set("ccircumflex", 742); + key_values.set("gabovedot", 757); + key_values.set("gcircumflex", 760); + key_values.set("ubreve", 765); + key_values.set("scircumflex", 766); + key_values.set("kra", 930); + key_values.set("Rcedilla", 931); + key_values.set("Itilde", 933); + key_values.set("Lcedilla", 934); + key_values.set("Emacron", 938); + key_values.set("Gcedilla", 939); + key_values.set("Tslash", 940); + key_values.set("rcedilla", 947); + key_values.set("itilde", 949); + key_values.set("lcedilla", 950); + key_values.set("emacron", 954); + key_values.set("gcedilla", 955); + key_values.set("tslash", 956); + key_values.set("ENG", 957); + key_values.set("eng", 959); + key_values.set("Amacron", 960); + key_values.set("Iogonek", 967); + key_values.set("Eabovedot", 972); + key_values.set("Imacron", 975); + key_values.set("Ncedilla", 977); + key_values.set("Omacron", 978); + key_values.set("Kcedilla", 979); + key_values.set("Uogonek", 985); + key_values.set("Utilde", 989); + key_values.set("Umacron", 990); + key_values.set("amacron", 992); + key_values.set("iogonek", 999); + key_values.set("eabovedot", 1004); + key_values.set("imacron", 1007); + key_values.set("ncedilla", 1009); + key_values.set("omacron", 1010); + key_values.set("kcedilla", 1011); + key_values.set("uogonek", 1017); + key_values.set("utilde", 1021); + key_values.set("umacron", 1022); + key_values.set("overline", 1150); + key_values.set("dead_abovedot", 729); + key_values.set("dead_abovering", 730); + key_values.set("dead_acute", 180); + key_values.set("dead_breve", 728); + key_values.set("dead_caron", 711); + key_values.set("dead_cedilla", 184); + key_values.set("dead_circumflex", 94); + key_values.set("dead_diaeresis", 168); + key_values.set("dead_doubleacute", 733); + key_values.set("dead_grave", 96); + key_values.set("dead_ogonek", 731); + key_values.set("dead_perispomeni", 126); + key_values.set("dead_tilde", 126); + key_values.set("acute accent", 0xB4); + + const result = key_values.get(outchar); + + if (!result) { + console.log(" ToDo-kmc-convert keysymname not found!"); + return '******* keysym name not found!'; + } + + const codePoint_u = parseInt(result, 10); + const outconv = String.fromCodePoint(codePoint_u); + return outconv; } /** @@ -603,89 +832,8 @@ export class XkbToKmnConverter { return dataUkelele; } - /** - * @brief member function to create a kmn modifier from a keylayout modifier - * @param keylayoutModifier :string - modifier used in a .keylayout file - * @param isCAPSused : boolean flag to indicate if CAPS is used in a keylayout file or not - * @return string - a modifier value suitable for use in a .kmn-file - */ - public createKmnModifier(keylayoutModifier: string, isCAPSused: boolean): string { - - const kmnModifier: string[] = []; - const modifierState = keylayoutModifier.split(" "); - - for (const modifier of modifierState) { - const modifierUppercase = modifier.toUpperCase(); - - if (isCAPSused && (keylayoutModifier).toUpperCase().indexOf("CAPS?") > 0) { - kmnModifier.push("NCAPS"); - } - if (isCAPSused && (keylayoutModifier).toUpperCase().indexOf("CAPS") === -1) { - kmnModifier.push("NCAPS"); - } - - // if we find a modifier containing a '?' e.g. SHIFT? it means the modifier is not necessary. - // If it is not necessary we don't write this modifier - if (modifierUppercase.includes('?') && modifierUppercase !== 'CAPS?') { - kmnModifier.push(""); - } - // if we find 'caps?' => caps is not necessary. - // If caps is not necessary and isCAPSused we need to write out NCAPS. - else if (isCAPSused && modifierUppercase === 'CAPS?') { - kmnModifier.push("NCAPS"); - } - else if (!isCAPSused && modifierUppercase === 'CAPS?') { - kmnModifier.push(""); - } - else if (modifierUppercase === 'CAPS' || modifierUppercase === 'CAPS?') { - kmnModifier.push("CAPS"); - } - else if (isCAPSused && (modifierUppercase === 'NCAPS')) { - kmnModifier.push("NCAPS"); - } - else if (modifierUppercase === 'ANYSHIFT' || modifierUppercase === 'SHIFT') { - kmnModifier.push("SHIFT"); - } - else if (modifierUppercase === "LEFTSHIFT" || modifierUppercase === "LSHIFT") { - kmnModifier.push("SHIFT"); - } - else if (modifierUppercase === "RIGHTSHIFT" || modifierUppercase === "RSHIFT") { - kmnModifier.push("SHIFT"); - } - else if (modifierUppercase === 'ANYCONTROL' || modifierUppercase === 'CONTROL') { - kmnModifier.push("CTRL"); - } - else if (modifierUppercase === "LEFTCONTROL" || modifierUppercase === "LCONTROL") { - kmnModifier.push("LCTRL"); - } - else if (modifierUppercase === "RIGHTCONTROL" || modifierUppercase === "RCONTROL") { - kmnModifier.push("RCTRL"); - } - else if (modifierUppercase === "LEFTOPTION" || modifierUppercase === "LOPTION") { - kmnModifier.push("LALT"); - } - else if (modifierUppercase === "RIGHTOPTION" || modifierUppercase === "ROPTION") { - kmnModifier.push("RALT"); - } - else if (modifierUppercase === 'ANYOPTION' || modifierUppercase === 'OPTION') { - kmnModifier.push("RALT"); - } - // to enable the use of other modifiers (leave upper/lowecase as in .keylayout) - // e.g. 'shift command' -> 'NCAPS SHIFT command'; 'wrongModifierName' -> 'wrongModifierName' - else { - if (!this.isAcceptableKeymanModifier(modifier)) - kmnModifier.push(modifier); - } - } - - // remove duplicate and empty entries and make sure NCAPS is at the beginning - const uniqueModifier: string[] = kmnModifier.filter(function (item, pos, self) { - return ((self.indexOf(item) === pos) && (item !== "")); - }); - - return uniqueModifier.flat().toString().replace(/,/g, " "); - } + // ToDo-kmc-convert needed? /** * @brief member function to check if CAPS is used throughout a keylayout file or not * @param keylayoutModifier the modifier string used in the .keylayout-file @@ -698,6 +846,7 @@ export class XkbToKmnConverter { return (" " + keylayoutModifier.flat().join(" ").toUpperCase() + " ").indexOf(" CAPS ") >= 0; } + // ToDo-kmc-convert needed? /** * @brief member function to check if a modifier can be used in Keyman * @param keylayoutModifier the modifier string used in the .keylayout-file @@ -715,327 +864,6 @@ export class XkbToKmnConverter { return true; } - /** - * @brief member function to map Ukelele keycodes to Windows Keycodes - * @param pos Ukelele (=mac) keycodes - * @return VK - */ - public mapUkeleleKeycodeToVK(pos: number): string { - const vk = [ - "K_A" /* A */, - "K_S" /* S */, - "K_D" /* D */, - "K_F" /* F */, - "K_H" /* H */, - "K_G" /* G */, - "K_Z" /* Z */, - "K_X" /* X */, - "K_C" /* C */, - "K_V" /* V */, - "K_BKQUOTE" /* ^ */, - "K_B" /* B */, - "K_Q" /* Q */, - "K_W" /* W */, - "K_E" /* E */, - "K_R" /* R */, - "K_Y" /* Y */, - "K_T" /* T */, - "K_1" /* 1 */, - "K_2" /* 2 */, - "K_3" /* 3 */, - "K_4" /* 4 */, - "K_6" /* 6 */, - "K_5" /* 5 */, - "K_EQUAL" /* ´ */, - "K_9" /* 9 */, - "K_7" /* 7 */, - "K_HYPHEN" /* ß */, - "K_8" /* 8 */, - "K_0" /* 0 */, - "K_RBRKT" /* ] */, - "K_O" /* O */, - "K_U" /* U */, - "K_LBRKT" /* [ */, - "K_I" /* I */, - "K_P" /* P */, - "K_ENTER", - "K_L" /* L */, - "K_J" /* J */, - "K_QUOTE" /* " */, - "K_K" /* K */, - "K_COLON" /* : */, - "K_BKSLASH" /* \ */, // 42 for ISO correct?? - "K_COMMA" /* , */, - "K_SLASH" /* / */, - "K_N" /* N */, - "K_M" /* M */, - "K_PERIOD" /* . */, - "K_oE2" /* \ */, // 48 for ANSI correct?? - "K_SPACE" /* \ */ - ]; - - if (!(pos >= 0 && pos <= 0x31) || (pos === null) || (pos === undefined)) { - return "" as string; - } else { - return vk[pos]; - } - } - - /** - * @brief member function to return an index for a given actionID - * @param data an object containing all data read from a .keylayout file - * @param search :string - value 'id' to be found - * @return a number specifying the index of an actionId - */ - public getActionIndexFromActionId(data: Keylayout.KeylayoutXMLSourceFile, search: string): number { - if (!data.keyboard?.actions?.action) { - return -1; - } - for (let i = 0; i < data.keyboard.actions.action.length; i++) { - if (data.keyboard.actions.action[i]['id'] === search) { - return i; - } - } - return -1; - } - - /** - * @brief member function to find the actionID of a certain state-next pair - * @param data an object containing all data read from a .keylayout file - * @param search :string value 'next' to be found - * @return a string containing the actionId of a certain state(none)-next pair - */ - public getActionIdFromActionNext(data: Keylayout.KeylayoutXMLSourceFile, search: string): string { - if (search !== "none" && data.keyboard?.actions?.action) { - for (const action of data.keyboard.actions.action) { - if (action.when) { - for (const when of action.when) { - if (when['next'] === search) { - return action['id'] as string; - } - } - } - } - } - return "" as string; - } - - /** - * @brief member function to create an array of (modifier) behaviors for a given keycode in [{keycode,modifier}] - * @param data an object containing all data read from a .keylayout file - * @param search : KeylayoutFileData[] - an array[{keycode,modifier}] to be found - * @return a string[] containing modifiers - */ - public getModifierArrayFromKeyModifierArray(data: ProcessedData["modifiers"], search: KeylayoutFileData[]): string[][] | [null] { - const returnString1D: string[][] = []; - for (let i = 0; i < search.length; i++) { - if (search[i].behavior === undefined || search[i].behavior === null) { - return [null]; - } - returnString1D.push(data[Number(search[i].behavior)]); - } - return returnString1D; - } - - /** - * @brief member function to find the output for a certain actionID for state 'none' - * @param data an object containing all data read from a .keylayout file - * @param search :string an actionId to be found - * @return a string containing the output character - */ - public getOutputFromActionIdNone(data: Keylayout.KeylayoutXMLSourceFile, search: string): string { - let OutputValue: string = ""; - - if (!data.keyboard?.actions?.action) { - return OutputValue; - } - - for (const action of data.keyboard.actions.action as Keylayout.KL_Action[]) { - if (action['id'] === search) { - for (const when of action.when as Keylayout.KL_When[]) { - if ((when['state'] === "none") && (when['output'] !== undefined)) { - OutputValue = when['output']; - } - } - } - } - return OutputValue; - } - - /** - * @brief member function to return array of [Keycode,Keyname,actionId,actionIDIndex, output] for a given actionID in of [ actionID,state,output] - * @param data an object containing all data read from a .keylayout file - * @param search :idStateOutputObject[] - array of [{ actionID,state,output }] - * @return a KeylayoutFileData[] containing [{Keycode,Keyname,actionId,actionID, output}] - */ - public getKeyActionOutputArrayFromActionStateOutputArray(data: Keylayout.KeylayoutXMLSourceFile, search: ActionStateOutput[]): KeylayoutFileData[] { - - if ((search === undefined) || (search === null)) - return []; - - const keyActionOutput = []; - - for (let k = 0; k < search.length; k++) { - for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { - for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { - if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['action'] === search[k].id && - Number(data.keyboard.keyMapSet[0].keyMap[i].key[j]['code']) <= XkbToKmnConverter.MAX_KEY_IDENTIFIER) { - const singleDataSet = { - keyCode: data.keyboard.keyMapSet[0].keyMap[i].key[j]['code'], - key: this.mapUkeleleKeycodeToVK(Number(data.keyboard.keyMapSet[0].keyMap[i].key[j]['code'])), - actionId: data.keyboard.keyMapSet[0].keyMap[i].key[j]['action'], - behavior: data.keyboard.keyMapSet[0].keyMap[i]['index'], - outchar: search[k].output - }; - keyActionOutput.push(singleDataSet); - } - } - } - } - return keyActionOutput; - } - - /** - * @brief member function to get an array of all actionId-output pairs for a certain state - * @param data an object containing all data read from a .keylayout file - * @param search : string a 'state' to be found - * @return an array: idStateOutputObject[] containing all [{actionId, state, output}] for a certain state - */ - public getActionStateOutputArrayFromActionState(data: Keylayout.KeylayoutXMLSourceFile, search: string): ActionStateOutput[] { - const actionStateOutput: ActionStateOutput[] = []; - if (search !== "none" && data.keyboard?.actions?.action) { - for (const action of data.keyboard.actions.action) { - if (action.when) { - for (const when of action.when) { - if ((when['state'] === search) && (when['output'] !== undefined)) { - const singleDataSet = { - id: action['id'], - state: when['state'], - output: when['output'] - }; - actionStateOutput.push(singleDataSet as ActionStateOutput); - } - } - - } - } - } - return actionStateOutput; - } - - /** - * @brief member function to create an 2D array of [KeyName,actionId,behavior,modifier,output] - * @param data an object containing all data read from a .keylayout file - * @param search : array of [{keycode,keyname,actionId,behavior,output}] to be found - * @param isCAPSused : boolean flag to indicate if CAPS is used in a keylayout file or not - * @return an array: KeylayoutFileData[] containing [{KeyName,actionId,behavior,modifier,output}] - */ - public getKeyBehaviorModOutputArrayFromKeyActionBehaviorOutputArray(data: Keylayout.KeylayoutXMLSourceFile, search: KeylayoutFileData[], isCAPSused: boolean): KeylayoutFileData[] { - const keyBehaviorModOutput = []; - if (!((search === undefined) || (search === null) || (search.length === 0))) { - for (let i = 0; i < search.length; i++) { - const behaviorIdx: number = Number(search[i].behavior); - for (let j = 0; j < data.keyboard.modifierMap[0].keyMapSelect[behaviorIdx].modifier.length; j++) { - const singleDataSet = { - actionId: search[i].actionId, - key: search[i].key, - behavior: search[i].behavior, - modifier: this.createKmnModifier(data.keyboard.modifierMap[0].keyMapSelect[behaviorIdx].modifier[j]['keys'], isCAPSused), - outchar: search[i].outchar, - }; - keyBehaviorModOutput.push(singleDataSet); - } - } - } - // remove duplicates - const uniquekeyBehaviorModOutput = keyBehaviorModOutput.reduce((unique, o) => { - if (!unique.some(obj => - obj.actionId === o.actionId && - obj.key === o.key && - obj.behavior === o.behavior && - obj.modifier === o.modifier && - obj.outchar === o.outchar - )) { - unique.push(o); - } - return unique; - }, [] as KeylayoutFileData[]); - return uniquekeyBehaviorModOutput; - } - - /** - * @brief member function to create an array of [actionID, output, behavior,keyname,modifier] for a given actionId - * @param data an object containing all data read from a .keylayout file - * @param modi an array of modifiers - * @param search : string - an actionId to be found - * @param outchar : string - the output character - * @param isCAPSused : boolean - flag to indicate if CAPS is used in a keylayout file or not - * @return an array: KeylayoutFileData[] containing [{actionID,output, behavior,keyname,modifier}] - */ - public getActionOutputBehaviorKeyModiFromActionIDStateOutput(data: Keylayout.KeylayoutXMLSourceFile, modi: string[][], search: string, outchar: string, isCapsused: boolean): KeylayoutFileData[] { - const actionOutputBehaviorKeyModi = []; - if ((!modi) || (search === "") || (search === undefined)) { - return []; - } - // loop behaviors (in ukelele it is possible to define multiple modifier combinations that behave in the same way) - for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { - for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { - if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['action'] === search) { - for (let k = 0; k < modi[Number(data.keyboard.keyMapSet[0].keyMap[i]['index'])].length; k++) { - const behaviorIdx: number = Number(data.keyboard.keyMapSet[0].keyMap[i]['index']); - const singleDataSet = { - outchar: outchar, - actionId: data.keyboard.keyMapSet[0].keyMap[i].key[j]['action'], - behavior: data.keyboard.keyMapSet[0].keyMap[i]['index'], - key: this.mapUkeleleKeycodeToVK(Number(data.keyboard.keyMapSet[0].keyMap[i].key[j]['code'])), - modifier: this.createKmnModifier(modi[behaviorIdx][k], isCapsused), - }; - actionOutputBehaviorKeyModi.push(singleDataSet); - } - } - } - } - - //............................................................................. - - // remove duplicates - const uniqueactionOutputBehaviorKey = actionOutputBehaviorKeyModi.reduce((unique, o) => { - if (!unique.some(obj => - obj.outchar === o.outchar && - obj.actionId === o.actionId && - obj.behavior === o.behavior && - obj.key === o.key && - obj.modifier === o.modifier - )) { - unique.push(o); - } - return unique; - }, [] as KeylayoutFileData[]); - - return uniqueactionOutputBehaviorKey; - } - - /** - * @brief member function to create an array of [{keycode,behavior}] for a given actionId - * @param data an object containing all data read from a .keylayout file - * @param search : string - an actionId to be found - * @return an array: KeylayoutFileData[] containing [{keycode,behavior}] - */ - public getKeyModifierArrayFromActionID(data: Keylayout.KeylayoutXMLSourceFile, search: string): KeylayoutFileData[] { - const mapIndexObject1D: KeylayoutFileData[] = []; - for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) { - for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) { - if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['action'] === search) { - const singleDataSet = { - key: data.keyboard.keyMapSet[0].keyMap[i].key[j]['code'], - behavior: String(i), - }; - mapIndexObject1D.push(singleDataSet); - } - } - } - return mapIndexObject1D; - } /** @internal */ public convertBound = { diff --git a/developer/src/kmc-convert/src/kmc-convert-read/xkb-file-reader.ts b/developer/src/kmc-convert/src/kmc-convert-read/xkb-file-reader.ts index cc55e9d6ca9..48392793e8e 100644 --- a/developer/src/kmc-convert/src/kmc-convert-read/xkb-file-reader.ts +++ b/developer/src/kmc-convert/src/kmc-convert-read/xkb-file-reader.ts @@ -7,7 +7,7 @@ * */ -import { CompilerCallbacks, DeveloperUtilsMessages, Keylayout, KeymanXMLReader } from "@keymanapp/developer-utils"; +import { CompilerCallbacks, DeveloperUtilsMessages, Keylayout } from "@keymanapp/developer-utils"; import { util, SchemaValidators } from '@keymanapp/common-types'; import { ConverterMessages } from '../converter-messages.js'; import boxXmlArray = util.boxXmlArray; @@ -149,18 +149,19 @@ export class XkbFileReader { * @param inputFilename the ukelele .keylayout-file to be parsed * @return in case of success: json object containing data of the .keylayout file; else null */ - public read(source: Uint8Array): Keylayout.KeylayoutXMLSourceFile { + public read(source: Uint8Array): string |null{ try { const data = new TextDecoder().decode(source); - const jsonObj = new KeymanXMLReader('keylayout').parse(data) as Keylayout.KeylayoutXMLSourceFile; + console.log('typeof(data)',typeof(data)) - if (!jsonObj?.keyboard) { - this.callbacks.reportMessage(ConverterMessages.Error_UnableToParse()); + // ToDo-kmc-convert double msg? + + if (!data) { + this.callbacks.reportMessage(ConverterMessages.Error_UnableToRead()); return null; } - this.boxArray(jsonObj.keyboard); // jsonObj now contains arrays; no single fields - return jsonObj; + return data; } catch (err) { this.callbacks.reportMessage(ConverterMessages.Error_UnableToRead()); diff --git a/developer/src/kmc-convert/src/kmc-convert-write/kmn-file-writer.ts b/developer/src/kmc-convert/src/kmc-convert-write/kmn-file-writer.ts index 2f3405c3853..e556e0f5e1b 100644 --- a/developer/src/kmc-convert/src/kmc-convert-write/kmn-file-writer.ts +++ b/developer/src/kmc-convert/src/kmc-convert-write/kmn-file-writer.ts @@ -21,12 +21,31 @@ export class KmnFileWriter { constructor(private callbacks: CompilerCallbacks, private options: CompilerOptions) { }; + // TODO-kmc-convert remove + public writeToFile(dataUkelele: ProcessedData): boolean | null { + + let data: string = "\n"; + + // add top part of kmn file: STORES + data += this.writeKmnFileHeader(dataUkelele); + + // add bottom part of kmn file: RULES + data += this.writeDataRules(dataUkelele); + + try { + this.callbacks.fs.writeFileSync(dataUkelele.kmnFilename, new TextEncoder().encode(data)); + return true; + } catch (err: any) { + this.callbacks.reportMessage(ConverterMessages.Error_UnableToWrite({ outputFilename: dataUkelele.kmnFilename, errorText: err })); + return false; + } + } /** * @brief member function to write data from object to a Uint8Array * @param dataUkelele the array holding all keyboard data * @return a Uint8Array holding data */ - public write(dataUkelele: ProcessedData): Uint8Array { + public write(dataUkelele: ProcessedData): Uint8Array|null { let data: string = "\n"; // top part of kmn file: STORES @@ -40,7 +59,7 @@ export class KmnFileWriter { try { return new TextEncoder().encode(data); - } catch (err) { + } catch (err:any) { this.callbacks.reportMessage(ConverterMessages.Error_UnableToWrite({ outputFilename: dataUkelele.kmnFilename, errorText: err })); return null; } @@ -152,7 +171,7 @@ export class KmnFileWriter { if ((outputCharacter !== undefined) || (outputCharacter !== "")) { const characterMessage = this.writeCharacterOrUnicode(outputCharacter, warnText[2]); versionOutputCharacter = characterMessage.character; - warnText[2] = characterMessage.message; + warnText[2] = characterMessage.message; } // add a warning in front of rules in case unavailable modifiers or ambiguous rules are used @@ -205,7 +224,7 @@ export class KmnFileWriter { if ((outputCharacter !== undefined) || (outputCharacter !== "")) { const characterMessage = this.writeCharacterOrUnicode(outputCharacter, warnText[2]); versionOutputCharacter = characterMessage.character; - warnText[2] = characterMessage.message; + warnText[2] = characterMessage.message; } // add a warning in front of rules in case unavailable modifiers or ambiguous rules are used @@ -279,7 +298,7 @@ export class KmnFileWriter { if ((outputCharacter !== undefined) || (outputCharacter !== "")) { const characterMessage = this.writeCharacterOrUnicode(outputCharacter, warnText[2]); versionOutputCharacter = characterMessage.character; - warnText[2] = characterMessage.message; + warnText[2] = characterMessage.message; } // add a warning in front of rules in case unavailable modifiers or ambiguous rules are used @@ -1030,7 +1049,7 @@ export class KmnFileWriter { const m_chr_inv = /^((&;?)+|(&#;?)+|(&#x;?)+;?)$|^$/i.exec(inputString); // valid '&#x...' - if (m_hex) { + if (m_hex) { const codePoint_h = parseInt(m_hex[1], 16); // Reject surrogates and invalid codepoints if ((codePoint_h >= 0xD800 && codePoint_h <= 0xDFFF) || codePoint_h > 0x10FFFF) { From fc9e6716390434d1a4a7c4c068c293cfd9f13fb7 Mon Sep 17 00:00:00 2001 From: Sabine Date: Thu, 14 May 2026 13:34:14 +0200 Subject: [PATCH 248/251] feat(developer): reading complex input files: key.type, comments, variant --- .../xkb-to-kmn-converter.ts | 490 ++++-- .../src/kmc-convert-read/xkb-file-reader.ts | 132 +- .../kmc-convert/test/data/tests-xkb-kmn/de | 5 +- .../test/data/tests-xkb-kmn/de-complex | 47 + .../tests-xkb-kmn/{de_simple => de-simple} | 3 +- .../test/data/tests-xkb-kmn/de-simple_basic | 229 +++ .../xkb-to-kmn-converter.tests.ts | 1458 +++++++++-------- .../kmc-convert-read/xkb-file-reader.tests.ts | 2 +- 8 files changed, 1436 insertions(+), 930 deletions(-) create mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/de-complex rename developer/src/kmc-convert/test/data/tests-xkb-kmn/{de_simple => de-simple} (98%) create mode 100644 developer/src/kmc-convert/test/data/tests-xkb-kmn/de-simple_basic diff --git a/developer/src/kmc-convert/src/kmc-convert-convert/xkb-to-kmn-converter.ts b/developer/src/kmc-convert/src/kmc-convert-convert/xkb-to-kmn-converter.ts index 40742d22431..d4f9576bd86 100644 --- a/developer/src/kmc-convert/src/kmc-convert-convert/xkb-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/kmc-convert-convert/xkb-to-kmn-converter.ts @@ -21,6 +21,42 @@ - add warning/errormessages +========================================================= +key {type[Group1]="FOUR_LEVEL_PLUS_LOCK", +symbols[Group1]= [ssharp, question, backslash, questiondown, 0x1001E9E ]}; +-----> "FOUR_LEVEL_PLUS_LOCK" + ====================================================== + use split(/type\[.*\]=(.*?),symbols/); +========================================================= + + +========================================================= +key {type[Group1]="FOUR_LEVEL_PLUS_LOCK", +symbols[Group1]= [ssharp, question, backslash, questiondown, 0x1001E9E ]}; +-----> "ssharp, question, backslash, questiondown, 0x1001E9E " + ====================================================== +use split(/symbols\[.*\]\s*=(.*?)\[/) +========================================================= + + +========================================================= +key.type[Group1] = "EIGHT_LEVEL"; +-----> "EIGHT_LEVEL" + ====================================================== +use split(/key.type\[.*\]=(.*?)/); +========================================================= + + +========================================================= + key { [ +-----> "" + ====================================================== +use split(/key.type\[.*\]=(.*?)/); + split(/key\s*()\s*\{\s*\[/); + split(/key()\{\[/); +========================================================= + + */ @@ -56,9 +92,19 @@ export interface ProcessedData { modifiers: string[][]; rules: Rule[]; }; +export interface Data_xkb { + /** + * Interface for all data read from a .keylayout file. Also contains all rules processed from input data. + * Data will be used for writing to a .kmn file (e.g. filename, modifier combinations, rules) + */ + xkb_keyname: string; + xkb_keytype: string; + xkb_modifiers: string[]; + xkb_output: string[]; +}; /** - * @brief class for all storing a rule containing data for key, deadkey, previous deadkey, output) + * @brief class for all storing a rule containing data for key, deadkey, previous deadkey, output) */ export class Rule { constructor( @@ -95,12 +141,21 @@ export class XkbToKmnConverter { }; /** - * @brief member function to run read/convert/write + * @brief ToDo check description + * @brief member function to run read/convert/write * @param inputFilename the ukelele .keylayout-file to be converted * @param outputFilename the resulting keyman .kmn-file * @return null on success */ - async run(inputFilename: string, outputFilename?: string): Promise { + async run(inputFilename_withVariant: string, outputFilename?: string): Promise { + + const variant_name = inputFilename_withVariant.substring(inputFilename_withVariant.indexOf('(') + 1, inputFilename_withVariant.indexOf(')')); + console.log('variant_name of run', variant_name); + + let inputFilename = inputFilename_withVariant; + if (variant_name) + inputFilename = inputFilename_withVariant.substring(0, inputFilename_withVariant.indexOf('(')); + if (!inputFilename) { this.callbacks.reportMessage(ConverterMessages.Error_FileNotFound({ inputFilename })); @@ -117,7 +172,7 @@ export class XkbToKmnConverter { return null; } - const processedData = await this.convert(xkb_data, inputFilename, outputFilename); + const processedData = await this.convert(xkb_data, inputFilename_withVariant, outputFilename); const kmnFileWriter = new KmnFileWriter(this.callbacks, this.options); // ToDo-kmc-convert remove writeToFile @@ -133,62 +188,6 @@ export class XkbToKmnConverter { return result; } - /** - * @brief member function to read filename and behaviorof a json object into a ProcessedData - * @param jsonObj containing filename, behaviorand rules of a json object - * @return an ProcessedData containing all data ready to print out - */ - private createArrayOfModifier(xkb_data?: string): string[][] { - // ToDo-kmc-convert write createArrayOfModifier() - /* - - theory xkb: what is hidden? - - can either be written for 1 key: within key {} ) - key { - type[Group1]="PC_ALT_LEVEL2", - symbols[Group1]= [ Henkan, Mode_switch ] - }; - - or for a group: within {} - hidden partial alphanumeric_keys - xkb_symbols "oldhun_lig" { - - key.type[Group1]="FOUR_LEVEL_ALPHABETIC"; - - key {[ U200D, U200F, U200C, 0 ]}; - //Zero-width-joiner,Right to left mark, Zero-width-non-joiner - //Zero-width-joiner and Zero-width-non-joiner are reqired for ligatures - key {[ U10CFA, apostrophe, U2E42, 1 ]}; - //Old Hungarian one, reversed 9 double low quotemark - key {[ U10CFB, quotedbl, U201F, 2 ]}; - }; - - find these lines in xkb file and extract number of, names and type of shiftstates - - key {type[Group1]="FOUR_LEVEL_PLUS_LOCK", symbols[Group1]= - [ssharp, question, backslash, questiondown, 0x1001E9E ]}; - // ToDo-kmc-convert fill array according to group type: - key {type[Group1]="FOUR_LEVEL_PLUS_LOCK", symbols[Group1]= [ssharp, question, backslash, questiondown, 0x1001E9E ]}; - -> [ "", "SHIFT", "RALT", "SHIFT RALT","CAPS SHIFT RALT" ] - (is it really "CAPS SHIFT RALT" ) - see - ONE_LEVEL - TWO_LEVEL - ALPHABETIC - THREE_LEVEL - FOUR_LEVEL - FOUR_LEVEL_ALPHABETIC - */ - - // also remenmber: checkIfCapsIsUsed - - const modi1D: string[] = ["", "SHIFT", "RALT", "SHIFT RALT"]; - const modi2D: string[][] = []; - - modi2D.push(modi1D); - return modi2D; - } private convert(xkb_data: string, inputfilename: string, outputFilename?: string): ProcessedData | null { @@ -198,67 +197,314 @@ export class XkbToKmnConverter { // dataObject for all relevant data const dataObject: ProcessedData = { - keylayoutFilename: "", - kmnFilename: "", + keylayoutFilename: '', + kmnFilename: '', modifiers: [], rules: [] }; - // fill dataObject with filenames, behaviors and (initialized) rules + //const paragraph_name = "basic"; + const start_brack = inputfilename.indexOf('('); + const end_brack = inputfilename.indexOf(')'); + const variant_name = inputfilename.substring(start_brack + 1, end_brack); + const inputfilenameUntilBracket = inputfilename.substring(0, start_brack); + + + + + + dataObject.keylayoutFilename = inputfilename; - if (!outputFilename) - dataObject.kmnFilename = inputfilename + '.kmn'; + if (start_brack >= 0) { + dataObject.keylayoutFilename = inputfilenameUntilBracket; + } + + // fill dataObject with filenames, behaviors and (initialized) rules + // dataObject.keylayoutFilename = inputfilename; + if (!outputFilename) { + if (variant_name) + dataObject.kmnFilename = dataObject.keylayoutFilename + "_" + variant_name + '.kmn'; + else + dataObject.kmnFilename = dataObject.keylayoutFilename + '.kmn'; + //dataObject.kmnFilename = inputfilename + '.kmn'; + } else dataObject.kmnFilename = outputFilename; + + console.log('varidataObject.dataObject.keylayoutFilename\n', dataObject.keylayoutFilename, "\n", dataObject.kmnFilename); // fill rules into 'rules' of dataObject const out = this.createRuleData(dataObject, xkb_data); return out; } /** - * @brief member function to find the appopriate paragraph between "xkb_symbol " and the next xkb_symbol + // ToDo-kmc-convert edit this function + // in the Configuration file we find the appopriate paragraph between "xkb_symbol " and the next xkb_symbol + // ++++ load xkb and return paragraph between xkb_symbols block x and xkb_symbols y + * @brief ToDo check description + * @brief member function to find the appopriate paragraph between "xkb_symbol " and the next xkb_symbol * @param xkbData: an string containing the contents of the xkb file * @return the paragraph of the xkb ffr the specified data */ - public findParagraph(xkbData: string): string { - // ToDo-kmc-convert edit this function - // in the Configuration file we find the appopriate paragraph between "xkb_symbol " and the next xkb_symbol - return xkbData; + public findParagraph(xkbData_in: string, dataObject: ProcessedData): string { + + // Todo-kmc-convert: recursive look through other definition files if they are included (e.g. include "de(basic)") + // Todo-kmc-convert: create paragraphname from inputfilename + // ToDo-kmc-convert remove this-it`s neccessary as we could not process the include (include "de(basic)") + const xkbData = xkbData_in.replace(/include \"/g, '\/\/include \"'); + //const paragraph_name = "deadtilde"; + //const paragraph_name = "basic"; + const start_vari = dataObject.kmnFilename.lastIndexOf('_'); + const end_vari = dataObject.kmnFilename.indexOf('.'); + let variant_name = ''; + if ((start_vari !== -1) && (end_vari !== -1)) + variant_name = dataObject.kmnFilename.substring(start_vari + 1, end_vari); + + + //dataObject.kmnFilename = dataObject.keylayoutFilename.substring(0, start_brack) + "_" + variant_name; + + let paragraph_name = ''; + // Todo find default keyword (default xkb_symbols "basic") and use this + if (variant_name) + paragraph_name = variant_name; + else { + /* const pos_start_def_keyword = xkbData_in.indexOf('default xkb_symbols \"'); + const keywordstring = xkbData_in.substring(pos_start_def_keyword); + const pos_quote = keywordstring.indexOf('\"'); + const shortstring = keywordstring.substring(pos_quote + 1); + const pos_end_def_keyword = shortstring.indexOf('\"'); + //paragraph_name = "basic"; + paragraph_name = shortstring.substring(0, pos_end_def_keyword);*/ + + //const word= "symbols" + paragraph_name = xkbData_in.split(/default xkb_symbols\s*\"(.*?)\"\s\{/)[1]; + + } + console.log('paragraph_name', paragraph_name); + // remove all comments, remove whitespace, split into block for each xkb_symbol definition + const noComments = xkbData.replace(/\/\*[\s\S]*?\*\/|(?<=[^:])\/\/.*|^\/\/.*/g, ''); + const xkbData_noWhitespace = noComments.replaceAll(/[\s,]+/g, ',').slice(0, -1); + const xkb_symbols_blocks = xkbData_noWhitespace.split("xkb_symbols"); + + // find paragraphname in xkb_symbols, clean data and return appropriate paragraph + for (let i = 0; i < xkb_symbols_blocks.length; i++) { + if (xkb_symbols_blocks[i].indexOf(paragraph_name) >= 0) { + // text after 'xkb_symbols "xxxx" {' until '};,};' + // ToDo-kmc-convert find better solution + const start_paragraph = xkb_symbols_blocks[i].indexOf('{'); + const end_paragraph = xkb_symbols_blocks[i].indexOf('};,};'); + const paragraph = xkb_symbols_blocks[i].substring(start_paragraph + 2, end_paragraph); + return paragraph.replaceAll(/[{[,}\]]+/g, ','); + } + } + return ''; } /** - * @brief member function to extract all lines starting with with '' from input data + * @brief ToDo check description + * @brief* @brief ToDo check description + * @brief member function to extract all lines starting with with '' from input data * @param xkbData: an string containing the contents of the xkb file * @return an array of lines containing key - output pairs. */ - public createCompleteLines(xkbData: string): string[] { + public createCompleteLines(xkbData: string, dataObject: ProcessedData): string[] { + + // in the Configuration file we find the appopriate paragraph between "xkb_symbol " and the next xkb_symbol + // then push all rows starting with "key" to a 1D-Vector + const paragraph = this.findParagraph(xkbData, dataObject); + if (!paragraph) + console.log('ToDo-kmc-convert add Err-msg findParagraph'); + + const lineArray = []; + + // each rule and type in a seperate line + // Todo_kmc-convert needed? + const lines = paragraph.split('key'); + + for (let i = 0; i < lines.length; i++) { + if (lines[i]) { + lineArray.push(lines[i].replaceAll(/[\s;]]+/g, ',').slice(1, -1)); + } + } + return lineArray; + } + + public getModifier(typename: string): string[] | null { + + // ToDo-kmc-convert read levels from file + // ToDo-kmc-convert use case + + if (typename === "ONE_LEVEL") { + return [""]; + } + + if (typename === "FOUR_LEVEL_PLUS_LOCK") { + return ["", "SHIFT", "RALT", "SHIFT RALT", "LOCK"]; + } + + if (typename === "EIGHT_LEVEL") { + return ["", "SHIFT", "ALT", "SHIFT ALT", "X", "X SHIFT", "X ALT", "X SHIFT ALT"]; + } + + if (typename === "DEFAULT_LEVEL") { + return ["", "SHIFT", "ALT", "SHIFT ALT"]; + } + return null; + } + public getOutputcher(line: string): string { + // kmc-konvert-better solution + + + + const pos_type = line.indexOf('type'); + if (pos_type >= 0) { + + const pos_type2 = line.indexOf('symbols'); + if (pos_type2 >= 0) { + const shorterline = line.substring(pos_type2); + const pos_equal2 = shorterline.indexOf('"'); + const out = shorterline.substring(pos_equal2); + return out; + + +/* + + const myTip = line.split(/type.*\s*=(.*?)\[/); + if (myTip[2] !== out) + console.log('paragraph_name1 NOT EQUAL ###################################', out, myTip); + else console.log('paragraph_name1 is EQUAL ................#', out, myTip); + return myTip[2];*/ + + + + + + + + + } + } + return line; + } + + public getKeytype(data_key: string, default_type: string): string { + + // kmc-konvert-better solution + const pos_type = data_key.indexOf('type'); + if (pos_type >= 0) { + const first_quote = data_key.indexOf('"'); + const longstring = data_key.substring(first_quote + 1); + const last_qoute = longstring.indexOf('"'); + const shortstring = longstring.substring(0, last_qoute); + return shortstring; + } + return default_type; + } + + + public filldata_paragraph(xkbData: string, dataObject: ProcessedData, data_paragraph_arr: Data_xkb[]): Data_xkb[] { // in the Configuration file we find the appopriate paragraph between "xkb_symbol " and the next xkb_symbol // then copy all rows starting with "key <" to a 1D-Vector - // ToDo-kmc-convert find appropriate parapraph - const paragraph = this.findParagraph(xkbData); + // find appropriate parapraph + const paragraph = this.findParagraph(xkbData, dataObject); if (!paragraph) console.log('ToDo-kmc-convert add Err-msg findParagraph'); - // ToDo-kmc-convert remove - // key { [ 1, exclam, onesuperior, exclamdown ] }; // extract data from 1 line: - // 'AE01> { [ 1, exclam, onesuperior, exclamdown ] }; ' // use only lines that start with ' {[' and remove 'key' - // ',1,exclam,onesuperior,exclamdown' // remove whitespace etc from line const lineArray = []; - const lines = xkbData.split("key <"); + + // each rule and type in a seperate line + const lines = paragraph.split('key'); + for (let i = 0; i < lines.length; i++) { - if ((lines[i].indexOf('{') >= 6) && (lines[i].indexOf('[') >= 7)) { - lineArray.push('<' + lines[i].replaceAll(/[\s{[,;}\]]+/g, ',').slice(0, -1)); + lineArray.push(lines[i].replaceAll(/[\s{[,;}\]]+/g, ',').slice(1, -1)); + } + + let default_key_type: string = 'DEFAULT_LEVEL'; + + for (let i = 0; i < lineArray.length; i++) { + + // get Data for key_type OK + const outputChar = []; + const key_type = this.getKeytype(lineArray[i], default_key_type); + default_key_type = key_type; + + // get Data for modifier OK + const modi_Data = this.getModifier(key_type); + + // get Data for keyname + // Todo-kmc-convert move to function + let keyname = ''; + const pos_key_start = lineArray[i].indexOf('= 0) { + const keyname1 = lineArray[i].substring(pos_key_start); + const pos_key_end = keyname1.indexOf('>'); + keyname = keyname1.substring(pos_key_start, pos_key_end + 1); + } + + // get Data for outputmove to functionbetter solution + let out: string = ''; + const pos_type = lineArray[i].indexOf('type'); + if (pos_type >= 0) { + + // use of key {type[Group1]=" + /* const pos_symbols = lineArray[i].indexOf('symbols'); + if (pos_symbols >= 0) { + const shortstring = lineArray[i].substring(pos_symbols); + const pos_first_equal = shortstring.indexOf('='); + out = shortstring.substring(pos_first_equal + 2); + }*/ + const pos_symbols = lineArray[i].indexOf('symbols'); + if (pos_symbols >= 0) { + out = lineArray[i].split(/symbols.*(.*?)=,/)[2]; + } + else { + // use of key.type + const pos_first_equal = lineArray[i].indexOf('='); + out = lineArray[i].substring(pos_first_equal + 2); + } + } + else { + // normal + if (lineArray[i].indexOf('= 0) { + const completestring = lineArray[i]; + const onlyOut = completestring.split('>,'); + out = onlyOut[1]; + } + } + const elements = out.split(','); + + // get Data for outputChar + for (let j = 0; j < elements.length; j++) { + const outputcharOK = this.getOutputcher(elements[j]); + outputChar.push(outputcharOK); + } + + + + + const singleData_paragraph: Data_xkb = { + xkb_keyname: keyname as string, + xkb_keytype: default_key_type, + xkb_modifiers: modi_Data as string[], + xkb_output: outputChar, + }; + + if (keyname) { + data_paragraph_arr.push(singleData_paragraph); } } - return lineArray; + return data_paragraph_arr; } /** - * @brief member function to read the rules contained in a json object and add array of Rules[] to an ProcessedData + * @brief ToDo check description + * @brief* @brief ToDo check description + * @brief member function to read the rules contained in a json object and add array of Rules[] to an ProcessedData * @param dataUkelele: an object containing the name of the in/output file, an array of behaviors and an (empty) array of Rules * @param jsonObj: json Object containing all da * ta read from a keylayout file @@ -268,28 +514,33 @@ export class XkbToKmnConverter { // create an array of modifier combinations and store in dataObject // ToDo-kmc-convert edit function (hard coded at present) - dataObject.modifiers = this.createArrayOfModifier(xkb_data); + //....................... extract complete lines to array ....................... //....................... e.g. ',1,exclam,onesuperior,exclamdown', ....... //............................................................................... - const lines = this.createCompleteLines(xkb_data); + const data_paragraph_arr: Data_xkb[] = []; + + const lines = this.createCompleteLines(xkb_data, dataObject); + // Todo-kmc-convert check data_paragraph_arr vs dataObject + this.filldata_paragraph(xkb_data, dataObject, data_paragraph_arr); + + // fill darta_data_paragraph if (!lines) console.log("ToDo-kmc-convert add ErrorMsg"); + // Todo-kmc-convert check nr(modi)= nr(output) + //....................... create a Rule and save to ruleObj ....................... //................................................................................. //................................................................................. const rules: Rule[] = []; - for (let i = 0; i < lines.length; i++) { - - // split / seperate keyname and outputs - const elements = lines[i].split(","); + for (let i = 0; i < data_paragraph_arr.length; i++) { - for (let j = 1; j < elements.length; j++) { + for (let j = 0; j < data_paragraph_arr[i].xkb_modifiers.length; j++) { const ruleObj = new Rule( /* ruleType */ "C0", @@ -303,10 +554,9 @@ export class XkbToKmnConverter { /* deadkey */ "", /* dk for C2*/ 0, /* unique B */ 0, - /* modifierKey*/ dataObject.modifiers[0][j - 1], - /* key */ this.get_KMVirtKC_from_keyname(elements[0]), - // ToDo-kmc-convert convert outputnames to output e.g. 'exclam' -> '!' - /* output */ new TextEncoder().encode(this.get_Output_FromOutputname(elements[j])) + /* modifierKey*/ data_paragraph_arr[i].xkb_modifiers[j], + /* key */ this.get_KMVirtKC_from_keyname(data_paragraph_arr[i].xkb_keyname), + /* output */ new TextEncoder().encode(this.get_Output_FromOutputname(data_paragraph_arr[i].xkb_output[j])) ); rules.push(ruleObj); } @@ -316,8 +566,9 @@ export class XkbToKmnConverter { } /** - * @brief convert the key name obtained from symbol file to the matching keyname e.g. name of key --> 'K_A' - *@param key_name as stated in the symbol file + * @brief ToDo check description + * @brief convert the key name obtained from symbol file to the matching keyname e.g. name of key --> 'K_A' + * @param key_name as stated in the symbol file * @return the equivalent keyman virtual keycode */ public get_KMVirtKC_from_keyname(key_name: string): string { @@ -429,7 +680,8 @@ export class XkbToKmnConverter { /** - * @brief convert a keyval name to an output character + * @brief ToDo check description + * @brief convert a keyval name to an output character more on https://manpages.ubuntu.com/manpages/jammy/man3/keysyms.3tk.html * @param outchar the name of the output * @return the input character if input is a character,an empty string if "NoSymbol" is found, @@ -445,13 +697,13 @@ export class XkbToKmnConverter { if (outchar.slice(0, 2) === "0x") { console.log(" ToDo-kmc-convert keysym name starting with 0x not found!"); - return '******* keysym name not found! - with 0x '; + return ('******* keysym name not found! - with 0x :' + outchar); } const m_uni = /^U([0-9a-f]{1,6})$/i.exec(outchar); if (m_uni) { console.log(" ToDo-kmc-convert keysym name starting with Uxxxx not found!"); - return '******* keysym name not found! - with Uxxxx '; + return ('******* keysym name not found! - with Uxxxx :' + outchar); } // ToDo-kmc-convert find a function to lookup values @@ -720,16 +972,17 @@ export class XkbToKmnConverter { if (!result) { console.log(" ToDo-kmc-convert keysymname not found!"); - return '******* keysym name not found!'; + return ('******* keysym name not found!' + outchar); } - + // Todo-kmc-convert better names const codePoint_u = parseInt(result, 10); const outconv = String.fromCodePoint(codePoint_u); return outconv; } /** - * @brief member function to review data in array of rules of dataUkelele: remove duplicate rules and mark first occurance of a rule in rules + * @brief ToDo check description + * @brief member function to review data in array of rules of dataUkelele: remove duplicate rules and mark first occurance of a rule in rules * @param dataUkelele: an object containing the name of the in/output file, an array of behaviors and an array of Rules * @return an object containing the name of the input file, an array of behaviors and the revised array of Rule[] */ @@ -832,39 +1085,6 @@ export class XkbToKmnConverter { return dataUkelele; } - - // ToDo-kmc-convert needed? - /** - * @brief member function to check if CAPS is used throughout a keylayout file or not - * @param keylayoutModifier the modifier string used in the .keylayout-file - * @return "caps" or undefined if "caps" is not found - */ - public checkIfCapsIsUsed(keylayoutModifier: string[][]): boolean { - if (!keylayoutModifier) - return false; - // make sure we always have a whitespace before and after each modifier( to distinguish from caps? ) - return (" " + keylayoutModifier.flat().join(" ").toUpperCase() + " ").indexOf(" CAPS ") >= 0; - } - - // ToDo-kmc-convert needed? - /** - * @brief member function to check if a modifier can be used in Keyman - * @param keylayoutModifier the modifier string used in the .keylayout-file - * @return true if the modifier can be used in keyman; false if not - */ - public isAcceptableKeymanModifier(keylayoutModifier: string): boolean { - if (keylayoutModifier === null) - return false; - const modifierSingle = keylayoutModifier.toUpperCase().split(" "); - for (const mod of modifierSingle) { - if (!mod.match(/^(NCAPS|CAPS|SHIFT|ALT|RALT|LALT|CTRL|LCTRL|RCTRL|)$/)) { - return false; - } - } - return true; - } - - /** @internal */ public convertBound = { convert: this.convert.bind(this), diff --git a/developer/src/kmc-convert/src/kmc-convert-read/xkb-file-reader.ts b/developer/src/kmc-convert/src/kmc-convert-read/xkb-file-reader.ts index 48392793e8e..33d5531bfb3 100644 --- a/developer/src/kmc-convert/src/kmc-convert-read/xkb-file-reader.ts +++ b/developer/src/kmc-convert/src/kmc-convert-read/xkb-file-reader.ts @@ -7,142 +7,13 @@ * */ -import { CompilerCallbacks, DeveloperUtilsMessages, Keylayout } from "@keymanapp/developer-utils"; -import { util, SchemaValidators } from '@keymanapp/common-types'; +import { CompilerCallbacks/*, DeveloperUtilsMessages, Keylayout*/ } from "@keymanapp/developer-utils"; import { ConverterMessages } from '../converter-messages.js'; -import boxXmlArray = util.boxXmlArray; -import { KL_KeyMapSelect, KL_KeyMap } from "../../../common/web/utils/src/types/keylayout/keylayout-xml.js"; - export class XkbFileReader { constructor(private callbacks: CompilerCallbacks /*,private options: CompilerOptions*/) { }; - - /** - * @brief helper function to find a specific keyMap index in a keyMapSet - * @param jsonObj the read keylayout data to be checked - * @param keyMapSelect the keyMapSelect element to find in keyMapSet - * @return true if the keyMapSet element is found, false if not - */ - public findMapIndexinKeymap(jsonObj: Keylayout.KeylayoutXMLSourceFile, keyMapSelect: KL_KeyMapSelect): boolean { - for (const keyMapSet of jsonObj.keyboard.keyMapSet) { - for (const keyMap of keyMapSet.keyMap) { - if (keyMap['index'] === keyMapSelect.mapIndex) { - return true; - } - } - } - return false; - } - - /** - * @brief helper function to find a specific keyMapSelect index in a modifierMap - * @param jsonObj the read keylayout data to be checked - * @param keyMap the keyMap element to find in modifierMap - * @return true if the keyMap element is found, false if not - */ - public findIndexinKeymapSelect(jsonObj: Keylayout.KeylayoutXMLSourceFile, keyMap: KL_KeyMap): boolean { - for (const modifierMap of jsonObj.keyboard.modifierMap) { - for (const keyMapSelect of modifierMap.keyMapSelect) { - if (keyMapSelect['mapIndex'] === keyMap.index) { - return true; - } - } - } - return false; - } - - /** - * @brief member function checking if all keyMapSelect elements have a corresponding keyMap - * element in the .keylayout file (if not, the .keylayout file is invalid and will not be converted) - * see TN2056 (https://developer.apple.com/library/archive/technotes/tn2056/_index.html#//apple_ref/doc/uid/DTS10003085-CH1-SUBSECTION7) - * @param jsonObj the read keylayout data to be checked - * @return true if all keyMapSelect elements have a corresponding keyMap element, false if not - */ - public checkForCorrespondingElements(jsonObj: Keylayout.KeylayoutXMLSourceFile): boolean { - let available = true; - - // check if all keyMapSelect elements have a corresponding keyMap element in the .keylayout file - for (const modifierMap of jsonObj.keyboard.modifierMap) { - for (const keyMapSelect of modifierMap.keyMapSelect) { - available = available && this.findMapIndexinKeymap(jsonObj, keyMapSelect); - } - } - // check if all keyMap elements have a corresponding keyMapSelect element in the .keylayout file - for (const keyMapSet of jsonObj.keyboard.keyMapSet) { - for (const keyMap of keyMapSet.keyMap) { - available = available && this.findIndexinKeymapSelect(jsonObj, keyMap); - } - } - return available; - } - - - /** - * @returns true if valid, false if invalid - */ - public validate(source: Keylayout.KeylayoutXMLSourceFile, inputFilename: string): boolean { - if (!SchemaValidators.default.keylayout(source)) { - for (const err of (SchemaValidators.default.keylayout).errors) { - this.callbacks.reportMessage(DeveloperUtilsMessages.Error_InvalidXml({ - e: err.instancePath - })); - } - return false; - } - - // check if all keyMapSelect elements have a corresponding keyMap element in the .keylayout file - if (!this.checkForCorrespondingElements(source)) { - this.callbacks.reportMessage(ConverterMessages.Error_InvalidFile({ errorText: inputFilename })); - return false; - } - return true; - } - - /** - * @brief member function to box single-entry objects into arrays - * @param source the object to be changed - * @return object that contain only boxed arrays - */ - public boxArray(source: any) { - - boxXmlArray(source, 'modifierMap'); - - boxXmlArray(source, 'keyMapSet'); - - if (source.layouts) { - boxXmlArray(source.layouts, 'layout'); - } - - if (source.modifierMap) { - for (const modifierMap of source.modifierMap) { - boxXmlArray(modifierMap, 'keyMapSelect'); - if (modifierMap.keyMapSelect) { - for (const keyMapSelect of modifierMap.keyMapSelect) { - boxXmlArray(keyMapSelect, 'modifier'); - } - } - } - } - - for (const keyMapSet of source.keyMapSet) { - boxXmlArray(keyMapSet, 'keyMap'); - for (const keyMap of keyMapSet.keyMap) { - boxXmlArray(keyMap, 'key'); - } - } - - if (source.actions) { - boxXmlArray(source.actions, 'action'); - for (const action of source.actions.action) { - boxXmlArray(action, 'when'); - } - } - - boxXmlArray(source?.terminators, 'when'); - } - /** * @brief member function to parse data from a .keylayout-file and store in a json object * we need to be able to ignore an output character of "", process an output character of " " (space) and allow surrounding whitespace in #text (which will be removed later) @@ -153,7 +24,6 @@ export class XkbFileReader { try { const data = new TextDecoder().decode(source); - console.log('typeof(data)',typeof(data)) // ToDo-kmc-convert double msg? diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/de b/developer/src/kmc-convert/test/data/tests-xkb-kmn/de index 496514f8bda..0c69ecc0764 100644 --- a/developer/src/kmc-convert/test/data/tests-xkb-kmn/de +++ b/developer/src/kmc-convert/test/data/tests-xkb-kmn/de @@ -1,5 +1,4 @@ -default -xkb_symbols "basic" { +default xkb_symbols "basic" { include "latin(type4)" @@ -36,7 +35,7 @@ xkb_symbols "basic" { key { [ less, greater, bar, dead_belowmacron ] }; include "kpdl(comma)" -ẞß + include "level3(ralt_switch)" }; diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/de-complex b/developer/src/kmc-convert/test/data/tests-xkb-kmn/de-complex new file mode 100644 index 00000000000..32ebbf4813c --- /dev/null +++ b/developer/src/kmc-convert/test/data/tests-xkb-kmn/de-complex @@ -0,0 +1,47 @@ +// Common Latin alphabet layout +// 0x1001E9E on key key , key , key added for testing purposes by SAB +// can now process +// comments ( // and /* */) +// different key.type +// defined xkb_symbols block +// read variant from variable +default xkb_symbols "basic" { + + key { [ /*some comment in the middle*/ 1, exclam, onesuperior, exclamdown ] }; + key { [ 2, quotedbl, twosuperior, oneeighth ] }; // some comment at the end + key { [ 3, section, threesuperior, sterling ] }; + key { [ r, /*a comment in the middle*/ R, paragraph, registered ] }; // plus some comment at the end + + key {type[Group1]="FOUR_LEVEL_PLUS_LOCK", symbols[Group1]= + [ssharp, question, backslash, questiondown, B ]}; + + + key.type[Group1] = "EIGHT_LEVEL"; + // t,T,ŧ ,Ŧ ,ṭ,ṫ,ţ,ᵗ + key { [ t, T, tslash,Tslash ,U1E6D ,U1E6B ,U0163 ,U1D57] }; + + key.type[Group1] = "ONE_LEVEL"; + key { [Z] }; + key { [U] }; + key { [I] }; + // key { [ z, Z, leftarrow, yen ] }; + // key { [ u, U, downarrow, uparrow ] }; + // key { [ i, I, rightarrow, idotless ] }; + + key.type[Group1] = "DEFAULT_LEVEL"; + key { [ o, O, oslash, Ooblique ] }; + key { [ p, P, thorn, THORN ] }; + +}; + + +partial alphanumeric_keys +xkb_symbols "deadtilde" { + // previous standard German layout with tilde as dead key + + include "de(basic)" + name[Group1]="German (dead tilde)"; + + key { [ plus, asterisk, dead_tilde, dead_macron ] }; +}; + diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/de_simple b/developer/src/kmc-convert/test/data/tests-xkb-kmn/de-simple similarity index 98% rename from developer/src/kmc-convert/test/data/tests-xkb-kmn/de_simple rename to developer/src/kmc-convert/test/data/tests-xkb-kmn/de-simple index 9462df4c08e..0fdb26b6eca 100644 --- a/developer/src/kmc-convert/test/data/tests-xkb-kmn/de_simple +++ b/developer/src/kmc-convert/test/data/tests-xkb-kmn/de-simple @@ -1,8 +1,7 @@ // Common Latin alphabet layout // 0x1001E9E on key key , key , key added for testing purposes by SAB -default partial -xkb_symbols "basic" { +default xkb_symbols "basic" { key { [ 1, exclam, onesuperior, exclamdown ] }; key { [ 2, quotedbl, twosuperior, oneeighth ] }; diff --git a/developer/src/kmc-convert/test/data/tests-xkb-kmn/de-simple_basic b/developer/src/kmc-convert/test/data/tests-xkb-kmn/de-simple_basic new file mode 100644 index 00000000000..2595abc8f5c --- /dev/null +++ b/developer/src/kmc-convert/test/data/tests-xkb-kmn/de-simple_basic @@ -0,0 +1,229 @@ + +c .................................................................................................................. +c .................................................................................................................. +c Keyman keyboard generated by kmn-convert version: 19.0.197 +c from Ukelele file: C:\Projects\keyman\keyman\developer\src\kmc-convert\test\data\tests-xkb-kmn\de_simple(basic) +c .................................................................................................................. +c .................................................................................................................. + +store(&TARGETS) 'desktop' + +begin Unicode > use(main) + +group(main) using keys + + ++ [K_1] > '1' ++ [SHIFT K_1] > '!' ++ [ALT K_1] > '¹' ++ [SHIFT ALT K_1] > '¡' + ++ [K_2] > '2' ++ [SHIFT K_2] > '"' ++ [ALT K_2] > '²' ++ [SHIFT ALT K_2] > '******* keysym name not found!oneeighth' + ++ [K_3] > '3' ++ [SHIFT K_3] > '§' ++ [ALT K_3] > '³' ++ [SHIFT ALT K_3] > '£' + ++ [K_4] > '4' ++ [SHIFT K_4] > '$' ++ [ALT K_4] > '¼' ++ [SHIFT ALT K_4] > '¤' + ++ [K_5] > '5' ++ [SHIFT K_5] > '%' ++ [ALT K_5] > '½' ++ [SHIFT ALT K_5] > '******* keysym name not found!threeeighths' + ++ [K_6] > '6' ++ [SHIFT K_6] > 'ˆ' ++ [ALT K_6] > '¾' ++ [SHIFT ALT K_6] > '******* keysym name not found!fiveeighths' + ++ [K_7] > '7' ++ [SHIFT K_7] > '&' ++ [ALT K_7] > '{' ++ [SHIFT ALT K_7] > '******* keysym name not found!seveneighths' + ++ [K_8] > '8' ++ [SHIFT K_8] > '*' ++ [ALT K_8] > '[' ++ [SHIFT ALT K_8] > '******* keysym name not found!trademark' + ++ [K_9] > '9' ++ [SHIFT K_9] > '(' ++ [ALT K_9] > ']' ++ [SHIFT ALT K_9] > '±' + ++ [K_0] > '0' ++ [SHIFT K_0] > ')' ++ [ALT K_0] > '}' ++ [SHIFT ALT K_0] > '°' + ++ [K_HYPHEN] > 'ß' ++ [SHIFT K_HYPHEN] > '?' ++ [ALT K_HYPHEN] > '\' ++ [SHIFT ALT K_HYPHEN] > '******* keysym name not found! - with 0x :0x1001E9E' + ++ [SHIFT ALT K_EQUAL] > '******* keysym name not found! - with 0x :0x1001E9E' + ++ [K_Q] > 'q' ++ [SHIFT K_Q] > 'Q' ++ [ALT K_Q] > '@' ++ [SHIFT ALT K_Q] > '******* keysym name not found!Greek_OMEGA' + ++ [K_W] > 'w' ++ [SHIFT K_W] > 'W' ++ [ALT K_W] > 'Ƴ' ++ [SHIFT ALT K_W] > 'ƣ' + ++ [K_E] > 'e' ++ [SHIFT K_E] > 'E' ++ [ALT K_E] > '******* keysym name not found!EuroSign' ++ [SHIFT ALT K_E] > '******* keysym name not found!EuroSign' + ++ [K_R] > 'r' ++ [SHIFT K_R] > 'R' ++ [ALT K_R] > '¶' ++ [SHIFT ALT K_R] > '®' + ++ [K_T] > 't' ++ [SHIFT K_T] > 'T' ++ [ALT K_T] > 'μ' ++ [SHIFT ALT K_T] > 'ά' + ++ [K_Y] > 'z' ++ [SHIFT K_Y] > 'Z' ++ [ALT K_Y] > '******* keysym name not found!leftarrow' ++ [SHIFT ALT K_Y] > '¥' + ++ [K_U] > 'u' ++ [SHIFT K_U] > 'U' ++ [ALT K_U] > '******* keysym name not found!downarrow' ++ [SHIFT ALT K_U] > '******* keysym name not found!uparrow' + ++ [K_I] > 'i' ++ [SHIFT K_I] > 'I' ++ [ALT K_I] > '******* keysym name not found!rightarrow' ++ [SHIFT ALT K_I] > 'ʹ' + ++ [K_O] > 'o' ++ [SHIFT K_O] > 'O' ++ [ALT K_O] > 'ø' ++ [SHIFT ALT K_O] > '******* keysym name not found!Ooblique' + ++ [K_P] > 'p' ++ [SHIFT K_P] > 'P' ++ [ALT K_P] > 'þ' ++ [SHIFT ALT K_P] > 'Þ' + ++ [K_LBRKT] > 'ü' ++ [SHIFT K_LBRKT] > 'Ü' + ++ [K_RBRKT] > '+' ++ [SHIFT K_RBRKT] > '*' ++ [ALT K_RBRKT] > '~' ++ [SHIFT ALT K_RBRKT] > '¯' + ++ [K_A] > 'a' ++ [SHIFT K_A] > 'A' ++ [ALT K_A] > 'æ' ++ [SHIFT ALT K_A] > 'Æ' + ++ [K_S] > 's' ++ [SHIFT K_S] > 'S' ++ [ALT K_S] > 'ß' ++ [SHIFT ALT K_S] > '§' + ++ [K_D] > 'd' ++ [SHIFT K_D] > 'D' ++ [ALT K_D] > 'ð' ++ [SHIFT ALT K_D] > 'Ð' + ++ [K_F] > 'f' ++ [SHIFT K_F] > 'F' ++ [ALT K_F] > 'ǰ' ++ [SHIFT ALT K_F] > 'ª' + ++ [K_G] > 'g' ++ [SHIFT K_G] > 'G' ++ [ALT K_G] > 'ο' ++ [SHIFT ALT K_G] > 'ν' + ++ [K_H] > 'h' ++ [SHIFT K_H] > 'H' ++ [ALT K_H] > 'ʱ' ++ [SHIFT ALT K_H] > 'ʡ' + ++ [K_J] > 'j' ++ [SHIFT K_J] > 'J' + ++ [K_K] > 'k' ++ [SHIFT K_K] > 'K' ++ [ALT K_K] > '΢' ++ [SHIFT ALT K_K] > '&' + ++ [K_L] > 'l' ++ [SHIFT K_L] > 'L' ++ [ALT K_L] > 'Ƴ' ++ [SHIFT ALT K_L] > 'ƣ' + ++ [K_COLON] > 'ö' ++ [SHIFT K_COLON] > 'Ö' ++ [SHIFT ALT K_COLON] > '******* keysym name not found! - with 0x :0x1001E9E' + ++ [K_QUOTE] > 'ä' ++ [SHIFT K_QUOTE] > 'Ä' + ++ [K_Z] > 'y' ++ [SHIFT K_Z] > 'Y' ++ [ALT K_Z] > '»' ++ [SHIFT ALT K_Z] > '******* keysym name not found! - with Uxxxx :U203A' + ++ [K_X] > 'x' ++ [SHIFT K_X] > 'X' ++ [ALT K_X] > '«' ++ [SHIFT ALT K_X] > '******* keysym name not found! - with Uxxxx :U2039' + ++ [K_C] > 'c' ++ [SHIFT K_C] > 'C' ++ [ALT K_C] > '¢' ++ [SHIFT ALT K_C] > '©' + ++ [K_V] > 'v' ++ [SHIFT K_V] > 'V' ++ [ALT K_V] > '******* keysym name not found!doublelowquotemark' ++ [SHIFT ALT K_V] > '******* keysym name not found!singlelowquotemark' + ++ [K_B] > 'b' ++ [SHIFT K_B] > 'B' ++ [ALT K_B] > '******* keysym name not found!leftdoublequotemark' ++ [SHIFT ALT K_B] > '******* keysym name not found!leftsinglequotemark' + ++ [K_N] > 'n' ++ [SHIFT K_N] > 'N' ++ [ALT K_N] > '******* keysym name not found!rightdoublequotemark' ++ [SHIFT ALT K_N] > '******* keysym name not found!rightsinglequotemark' + ++ [K_M] > 'm' ++ [SHIFT K_M] > 'M' ++ [ALT K_M] > 'µ' ++ [SHIFT ALT K_M] > 'º' + ++ [K_COMMA] > ',' ++ [SHIFT K_COMMA] > ';' ++ [ALT K_COMMA] > '·' ++ [SHIFT ALT K_COMMA] > '×' + ++ [K_PERIOD] > '.' ++ [SHIFT K_PERIOD] > ':' ++ [ALT K_PERIOD] > '******* keysym name not found! - with Uxxxx :U2026' ++ [SHIFT ALT K_PERIOD] > '÷' + ++ [K_SLASH] > '-' ++ [SHIFT K_SLASH] > '_' ++ [ALT K_SLASH] > '******* keysym name not found!endash' ++ [SHIFT ALT K_SLASH] > '******* keysym name not found!emdash' diff --git a/developer/src/kmc-convert/test/kmc-convert-convert/xkb-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/kmc-convert-convert/xkb-to-kmn-converter.tests.ts index ac501cdc63d..69bdcb422d7 100644 --- a/developer/src/kmc-convert/test/kmc-convert-convert/xkb-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/kmc-convert-convert/xkb-to-kmn-converter.tests.ts @@ -10,7 +10,7 @@ import 'mocha'; import { assert } from 'chai'; //import * as NodeAssert from 'node:assert'; import { compilerTestCallbacks, compilerTestOptions, makePathToFixture } from './../helpers/index.js'; -import { /*ActionStateOutput, KeylayoutFileData,*/ XkbToKmnConverter/*, Rule */} from '../../src/kmc-convert-convert/xkb-to-kmn-converter.js'; +import { /*ActionStateOutput, KeylayoutFileData,*/ XkbToKmnConverter } from '../../src/kmc-convert-convert/xkb-to-kmn-converter.js'; //import { XkbFileReader } from '../../src/kmc-convert-read/xkb-file-reader.js'; //import { ConverterMessages } from '../../src/converter-messages.js'; @@ -23,8 +23,10 @@ describe('XkbToKmnConverter', function () { describe('Xkb-kmn: RunSpecialTestFiles', function () { const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); [ - [makePathToFixture('../data/tests-xkb-kmn/de_simple')], - [makePathToFixture('../data/tests-xkb-kmn/test_xkb_differentEncodings')], + [makePathToFixture('../data/tests-xkb-kmn/de-simple')], + [makePathToFixture('../data/tests-xkb-kmn/de-simple(basic)')], + [makePathToFixture('../data/tests-xkb-kmn/de-complex')], + [makePathToFixture('../data/tests-xkb-kmn/de-complex(deadtilde)')], ].forEach(function (files) { it(files + " should give no errors ", async function () { sut.run(files[0]); @@ -32,755 +34,895 @@ describe('XkbToKmnConverter', function () { }); }); }); + /* - describe('Xkb-kmn: RunTestFiles resulting in errors ', function () { + describe('findParagraph ', function () { const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); [ - [makePathToFixture('../data/tests-xkb-kmn/Test_DifferentAmountOfMapSelectInKeyMapERROR.keylayout')], - [makePathToFixture('../data/tests-xkb-kmn/Test_MissingkeyERROR.keylayout')], - [makePathToFixture('../data/tests-xkb-kmn/Test_MissingkeyMapERROR.keylayout')], - [makePathToFixture('../data/tests-xkb-kmn/Test_MissingLayoutsERROR.keylayout')], - [makePathToFixture('../data/tests-xkb-kmn/Test_MissingmodifierMapERROR.keylayout')], - [makePathToFixture('../data/tests-xkb-kmn/Test_MissingkeyMapSetERROR.keylayout')], - [makePathToFixture('../data/tests-xkb-kmn/Test_MissingActionsERROR.keylayout')], - [makePathToFixture('../data/tests-xkb-kmn/Test_MissingTerminatorsERROR.keylayout')], - [makePathToFixture('../data/tests-xkb-kmn/Test_MissingAllERROR.keylayout')], - ].forEach(function (files) { - it(files + " should give an error ", async function () { - sut.run(files[0]); - assert.isTrue(compilerTestCallbacks.messages.length > 0); + ['', ''], + ].forEach(function (values) { + it(("findParagraph(" + values[0] + ")").padEnd(26, " ") + "should return " + "'" + values[1] + "'", async function () { + const result = sut.findParagraph(values[0] as string); + assert.equal(result, values[1]); }); }); }); - describe('Xkb-kmn: RunSpecialTestFiles - create Error: unsupported characters', function () { + + describe('createCompleteLines ', function () { const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); [ - [makePathToFixture('../data/tests-xkb-kmn/Test_characters.keylayout')], - ].forEach(function (files) { - it(files + " should give Error: unsupported characters ", async function () { - sut.run(files[0]); - assert.isTrue(compilerTestCallbacks.messages.length === 1); + ['', ''], + ].forEach(function (values) { + it(("findPacreateCompleteLinesragraph(" + values[0] + ")").padEnd(26, " ") + "should return " + "'" + values[1] + "'", async function () { + const result = sut.createCompleteLines(values[0] as string); + assert.equal(result, values[1]); }); }); - }); + });*/ + - describe('Xkb-kmn: RunSpecialTestFiles - create Error: undefined action', function () { + describe('get_KMVirtKC_from_keyname ', function () { const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); [ - [makePathToFixture('../data/tests-xkb-kmn/Test_undefinedAction.keylayout')], - ].forEach(function (files) { - it(files + " should give Error: undefined action detected", async function () { - sut.run(files[0]); - assert.isTrue(compilerTestCallbacks.messages.length === 1); - assert.equal(compilerTestCallbacks.messages[0].code, 5292040); + ['', 'K_A'], + ['', 'K_X'], + ['', 'K_BKQUOTE'], + ['AC01>', ''], + ['', ''], + ['', ''], + ['', ''], + ['', ''], + ['', ''], + [17, ''], + [null, ''], + [undefined, ''], + ].forEach(function (values) { + it(("get_KMVirtKC_from_keyname(" + values[0] + ")").padEnd(26, " ") + "should return " + "'" + values[1] + "'", async function () { + const result = sut.get_KMVirtKC_from_keyname(values[0] as string); + assert.equal(result, values[1]); }); }); }); - describe('Xkb-kmn: run() ', function () { + describe('get_Output_FromOutputname ', function () { const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); - - it('run() should throw on null input file name and null output file name', async function () { - // note, could use 'chai as promised' library to make this more fluent: - const result = sut.run(null, null); - assert.isNotNull(result); - assert.equal(compilerTestCallbacks.messages.length, 1); - assert.deepEqual(compilerTestCallbacks.messages[0], ConverterMessages.Error_FileNotFound({ inputFilename: null })); + [ + ['a', 'a'], + ['7', '7'], + ['ampersand', '&'], + ['NoSymbol', ''], + [null, ''], + [undefined, ''], + // ['😎', '😎'], + ['ሴ', 'ሴ'], + ['blabla', '******* keysym name not found!blabla'], + ['17', '******* keysym name not found!17'], + ['a', '******* keysym name not found!a'], + ['0x1234', '******* keysym name not found! - with 0x :0x1234'], + ['U2345', '******* keysym name not found! - with Uxxxx :U2345'], + ['ampersand', '&'], + ['ampersand', '&'], + ['ampersand', '&'], + ['ampersand', '&'], + ].forEach(function (values) { + it(("get_Output_FromOutputname(" + values[0] + ")").padEnd(26, " ") + "should return " + "'" + values[1] + "'", async function () { + const result = sut.get_Output_FromOutputname(values[0] as string); + assert.equal(result, values[1]); + }); }); + }); + /* + describe('isAcceptableKeymanModifier ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + [ + ['NCAPS', true], + ['NxCAPS', false], + ['SHIFT', true], + ['ALT', true], + ['RALT', true], + ['LALT', true], + ['CTRL', true], + ['LCTRL', true], + ['RCTRL', true], + ['LCTRL CAPS', true], + ['LCTRL X', false], + ['', true], + [null, false], + ].forEach(function (values) { + it(("isAcceptableKeymanModifier(" + values[0] + ")").padEnd(38, " ") + ' should return ' + values[1], async function () { + const result = sut.isAcceptableKeymanModifier(values[0] as string); + assert.equal(result, values[1]); + }); + }); + });*/ + /* + describe('checkIfCapsIsUsed ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + [ + [[['caps', 'xxx'], ['yyy']], true], + [[['Caps', 'xxx'], ['yyy']], true], + [[['CaPs', 'xxx'], ['yyy']], true], + [[['Caps?', 'xxx'], ['yyy']], false], + [[['zzz', 'xxx'], ['Caps?']], false], + [[['caps?', 'xxx'], ['yyy']], false], + [[['zzz', 'xxx'], ['yyy']], false], + [[['shift', 'xxx'], ['caps']], true], + [[['shift', 'caps'], ['yyy']], true], + [[['caps', 'xxx'], ['caps']], true], + [[['', 'someWordWithCaps'], ['']], false], + [null, false], + [[], false], + [[['', ''], ['']], false], + [[[' ', ' '], [' ']], false], + ].forEach(function (values) { + it(("checkIfCapsIsUsed(" + values[0] + ")").padEnd(40, " ") + "should return " + "'" + values[1] + "'", async function () { + const result = sut.checkIfCapsIsUsed(values[0] as string[][]); + assert.isTrue(result === values[1]); + }); + }); + });*/ + - it('run() should throw on null input file name and empty output file name', async function () { - const result = sut.run(null, ''); - assert.isNotNull(result); - assert.equal(compilerTestCallbacks.messages.length, 1); - assert.deepEqual(compilerTestCallbacks.messages[0], ConverterMessages.Error_FileNotFound({ inputFilename: null })); - }); - it('run() should throw on null input file name and unknown output file name', async function () { - const result = sut.run(null, 'X'); - assert.isNotNull(result); - assert.equal(compilerTestCallbacks.messages.length, 1); - assert.deepEqual(compilerTestCallbacks.messages[0], ConverterMessages.Error_FileNotFound({ inputFilename: null })); + + + + + + + + + /* + describe('Xkb-kmn: RunTestFiles resulting in errors ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + [ + [makePathToFixture('../data/tests-xkb-kmn/Test_DifferentAmountOfMapSelectInKeyMapERROR.keylayout')], + [makePathToFixture('../data/tests-xkb-kmn/Test_MissingkeyERROR.keylayout')], + [makePathToFixture('../data/tests-xkb-kmn/Test_MissingkeyMapERROR.keylayout')], + [makePathToFixture('../data/tests-xkb-kmn/Test_MissingLayoutsERROR.keylayout')], + [makePathToFixture('../data/tests-xkb-kmn/Test_MissingmodifierMapERROR.keylayout')], + [makePathToFixture('../data/tests-xkb-kmn/Test_MissingkeyMapSetERROR.keylayout')], + [makePathToFixture('../data/tests-xkb-kmn/Test_MissingActionsERROR.keylayout')], + [makePathToFixture('../data/tests-xkb-kmn/Test_MissingTerminatorsERROR.keylayout')], + [makePathToFixture('../data/tests-xkb-kmn/Test_MissingAllERROR.keylayout')], + ].forEach(function (files) { + it(files + " should give an error ", async function () { + sut.run(files[0]); + assert.isTrue(compilerTestCallbacks.messages.length > 0); + }); + }); }); - it('run() should throw on unavailable input file name and null output file name', async function () { - const inputFilename = makePathToFixture('../data/tests-xkb-kmn/Unavailable.keylayout'); - const result = sut.run(inputFilename, null); - assert.isNotNull(result); - assert.equal(compilerTestCallbacks.messages.length, 2); - assert.deepEqual(compilerTestCallbacks.messages[0], ConverterMessages.Error_UnableToRead()); - assert.equal(compilerTestCallbacks.messages[1].code, 5292037); + describe('Xkb-kmn: RunSpecialTestFiles - create Error: unsupported characters', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + [ + [makePathToFixture('../data/tests-xkb-kmn/Test_characters.keylayout')], + ].forEach(function (files) { + it(files + " should give Error: unsupported characters ", async function () { + sut.run(files[0]); + assert.isTrue(compilerTestCallbacks.messages.length === 1); + }); + }); }); - }); - describe('Xkb-kmn: Run kmc-convert with or without outputfile name', async function () { - this.timeout(5000); // allow longer time for this test - const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const infile = '../data/tests-xkb-kmn/Test.keylayout'; - [ - [makePathToFixture('../data/tests-xkb-kmn/Test.kmn')], - [makePathToFixture('')], - [], - [null], - [makePathToFixture('../data/tests-xkb-kmn/test_OtherOutputName.kmn')], - [makePathToFixture('../data/tests-xkb-kmn/OutputXName.bb')], - ].forEach(function (files) { - it(infile + " should run ", async function () { - await NodeAssert.doesNotReject(async () => sut.run(makePathToFixture(infile), files[0])); - assert.equal(compilerTestCallbacks.messages.length, 0); + describe('Xkb-kmn: RunSpecialTestFiles - create Error: undefined action', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + [ + [makePathToFixture('../data/tests-xkb-kmn/Test_undefinedAction.keylayout')], + ].forEach(function (files) { + it(files + " should give Error: undefined action detected", async function () { + sut.run(files[0]); + assert.isTrue(compilerTestCallbacks.messages.length === 1); + assert.equal(compilerTestCallbacks.messages[0].code, 5292040); + }); }); }); - });*/ - ///////////////////////////////////////////////////////////// -/* - describe('Xkb-kmn: convert() ', function () { - const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const sutR = new XkbFileReader(compilerTestCallbacks); - // ProcessedData from usable file - const inputFilename = makePathToFixture('../data/tests-xkb-kmn/Test.keylayout'); - const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); - const converted = sut.convertBound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); + describe('Xkb-kmn: run() ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); - // ProcessedData from unavailable file - const inputFilenameUnavailable = makePathToFixture('../data/tests-xkb-kmn/X.keylayout'); - const readUnavailable = sutR.read(compilerTestCallbacks.loadFile(inputFilenameUnavailable)); - const convertedUnavailable = sut.convertBound.convert(readUnavailable, inputFilenameUnavailable.replace(/\.keylayout$/, '.kmn')); + it('run() should throw on null input file name and null output file name', async function () { + // note, could use 'chai as promised' library to make this more fluent: + const result = sut.run(null, null); + assert.isNotNull(result); + assert.equal(compilerTestCallbacks.messages.length, 1); + assert.deepEqual(compilerTestCallbacks.messages[0], ConverterMessages.Error_FileNotFound({ inputFilename: null })); + }); - // ProcessedData from empty file - const inputFilenameEmpty = makePathToFixture(''); - const readEmpty = sutR.read(compilerTestCallbacks.loadFile(inputFilenameEmpty)); - const convertedEmpty = sut.convertBound.convert(readEmpty, inputFilenameEmpty); + it('run() should throw on null input file name and empty output file name', async function () { + const result = sut.run(null, ''); + assert.isNotNull(result); + assert.equal(compilerTestCallbacks.messages.length, 1); + assert.deepEqual(compilerTestCallbacks.messages[0], ConverterMessages.Error_FileNotFound({ inputFilename: null })); + }); - it('should return converted array on correct input', async function () { - assert.isTrue(converted.rules.length !== 0); - }); + it('run() should throw on null input file name and unknown output file name', async function () { + const result = sut.run(null, 'X'); + assert.isNotNull(result); + assert.equal(compilerTestCallbacks.messages.length, 1); + assert.deepEqual(compilerTestCallbacks.messages[0], ConverterMessages.Error_FileNotFound({ inputFilename: null })); + }); - it('should return empty on empty name as input', async function () { - assert.isNull(convertedUnavailable); + it('run() should throw on unavailable input file name and null output file name', async function () { + const inputFilename = makePathToFixture('../data/tests-xkb-kmn/Unavailable.keylayout'); + const result = sut.run(inputFilename, null); + assert.isNotNull(result); + assert.equal(compilerTestCallbacks.messages.length, 2); + assert.deepEqual(compilerTestCallbacks.messages[0], ConverterMessages.Error_UnableToRead()); + assert.equal(compilerTestCallbacks.messages[1].code, 5292037); + }); }); - it('should return empty on empty input', async function () { - assert.isNull(convertedEmpty); - }); + describe('Xkb-kmn: Run kmc-convert with or without outputfile name', async function () { + this.timeout(5000); // allow longer time for this test + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const infile = '../data/tests-xkb-kmn/Test.keylayout'; + [ + [makePathToFixture('../data/tests-xkb-kmn/Test.kmn')], + [makePathToFixture('')], + [], + [null], + [makePathToFixture('../data/tests-xkb-kmn/test_OtherOutputName.kmn')], + [makePathToFixture('../data/tests-xkb-kmn/OutputXName.bb')], + ].forEach(function (files) { + it(infile + " should run ", async function () { + await NodeAssert.doesNotReject(async () => sut.run(makePathToFixture(infile), files[0])); + assert.equal(compilerTestCallbacks.messages.length, 0); + }); + }); + });*/ + ///////////////////////////////////////////////////////////// + /* + describe('Xkb-kmn: convert() ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sutR = new XkbFileReader(compilerTestCallbacks); + + // ProcessedData from usable file + const inputFilename = makePathToFixture('../data/tests-xkb-kmn/Test.keylayout'); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + const converted = sut.convertBound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); + + // ProcessedData from unavailable file + const inputFilenameUnavailable = makePathToFixture('../data/tests-xkb-kmn/X.keylayout'); + const readUnavailable = sutR.read(compilerTestCallbacks.loadFile(inputFilenameUnavailable)); + const convertedUnavailable = sut.convertBound.convert(readUnavailable, inputFilenameUnavailable.replace(/\.keylayout$/, '.kmn')); + + // ProcessedData from empty file + const inputFilenameEmpty = makePathToFixture(''); + const readEmpty = sutR.read(compilerTestCallbacks.loadFile(inputFilenameEmpty)); + const convertedEmpty = sut.convertBound.convert(readEmpty, inputFilenameEmpty); + + it('should return converted array on correct input', async function () { + assert.isTrue(converted.rules.length !== 0); + }); - it('should return empty array of rules on null input', async function () { - const convertedRule = sut.convertBound.convert(null, 'ABC.kmn'); - assert.isNull(convertedRule); - }); - }); + it('should return empty on empty name as input', async function () { + assert.isNull(convertedUnavailable); + }); - describe('Xkb-kmn: createKmnModifier ', function () { - const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); - [ - [' ', true, 'NCAPS'], - [' ', false, ''], - - ['NCAPS', true, 'NCAPS'], - ['NCAPS', false, ''], - ['caps', true, 'CAPS'], - ['CAPS', true, 'CAPS'], - ['CAPS?', true, 'NCAPS'], - ['CAPS', false, 'CAPS'], - ['CAPS?', false, ''], - ['CAPS? NCAPS', true, 'NCAPS'], - ['CAPS NCAPS', true, 'CAPS NCAPS'], - ['caps ncaps', true, 'CAPS NCAPS'], - ['NCAPS shift', true, 'NCAPS SHIFT'], - ['shift', true, 'NCAPS SHIFT'], - ['leftshift', true, 'NCAPS SHIFT'], - ['rightShift', true, 'NCAPS SHIFT'], - ['shift', false, 'SHIFT'], - ['leftshift', false, 'SHIFT'], - ['rightShift', false, 'SHIFT'], - ['shift rightShift?', true, 'NCAPS SHIFT'], - ['rightShift?', true, 'NCAPS'], - ['shift Shift?', true, 'NCAPS SHIFT'], - ['shift rightShift? caps? rightOption? rightControl', true, 'NCAPS SHIFT RCTRL'], - ['leftshift rightShift? caps? rightOption? rightControl', true, 'NCAPS SHIFT RCTRL'], - ['anycontrol', true, 'NCAPS CTRL'], - ['shift?', true, 'NCAPS'], - ['?', true, 'NCAPS'], - ['?', false, ''], - ['', true, 'NCAPS'], - [' ', false, ''], - ['wrongModifierName', false, 'wrongModifierName'], - ['shift', false, 'SHIFT'], - ['shift command', true, 'NCAPS SHIFT command'], - ['rshift', true, 'NCAPS SHIFT'], - ['rshift', false, 'SHIFT'], - ['rightshift', true, 'NCAPS SHIFT'], - ['riGhtsHift', true, 'NCAPS SHIFT'], - ['LEFTCONTROL', true, 'NCAPS LCTRL'], - ['RCONTROL', true, 'NCAPS RCTRL'], - ['leftoption', true, 'NCAPS LALT'], - ['loption', true, 'NCAPS LALT'], - ['rightoption', true, 'NCAPS RALT'], - ['roption', true, 'NCAPS RALT'], - ].forEach(function (values) { - it(('should convert "' + values[0] + '"').padEnd(36, " ") + 'to "' + values[2] + '"', async function () { - const result = sut.createKmnModifier(values[0] as string, values[1] as boolean); - assert.equal(result, values[2]); + it('should return empty on empty input', async function () { + assert.isNull(convertedEmpty); }); - }); - }); - describe('Xkb-kmn: isAcceptableKeymanModifier ', function () { - const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); - [ - ['NCAPS', true], - ['NxCAPS', false], - ['SHIFT', true], - ['ALT', true], - ['RALT', true], - ['LALT', true], - ['CTRL', true], - ['LCTRL', true], - ['RCTRL', true], - ['LCTRL CAPS', true], - ['LCTRL X', false], - ['', true], - [null, false], - ].forEach(function (values) { - it(("isAcceptableKeymanModifier(" + values[0] + ")").padEnd(38, " ") + ' should return ' + values[1], async function () { - const result = sut.isAcceptableKeymanModifier(values[0] as string); - assert.equal(result, values[1]); + it('should return empty array of rules on null input', async function () { + const convertedRule = sut.convertBound.convert(null, 'ABC.kmn'); + assert.isNull(convertedRule); }); }); - }); - describe('Xkb-kmn: mapUkeleleKeycodeToVK ', function () { - const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); - [ - [0x00, 'K_A'], - [0x31, 'K_SPACE'], - [0x18, 'K_EQUAL'], - [0x10, 'K_Y'], - [0x18, 'K_EQUAL'], - [0x21, 'K_LBRKT'], - [0x999, ''], - [-1, ''], - [null, ''], - [undefined, ''], - [, ''], - ].forEach(function (values) { - it(("mapUkeleleKeycodeToVK(" + values[0] + ")").padEnd(26, " ") + "should return " + "'" + values[1] + "'", async function () { - const result = sut.mapUkeleleKeycodeToVK(values[0] as number); - assert.equal(result, values[1]); + describe('Xkb-kmn: createKmnModifier ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + [ + [' ', true, 'NCAPS'], + [' ', false, ''], + + ['NCAPS', true, 'NCAPS'], + ['NCAPS', false, ''], + ['caps', true, 'CAPS'], + ['CAPS', true, 'CAPS'], + ['CAPS?', true, 'NCAPS'], + ['CAPS', false, 'CAPS'], + ['CAPS?', false, ''], + ['CAPS? NCAPS', true, 'NCAPS'], + ['CAPS NCAPS', true, 'CAPS NCAPS'], + ['caps ncaps', true, 'CAPS NCAPS'], + ['NCAPS shift', true, 'NCAPS SHIFT'], + ['shift', true, 'NCAPS SHIFT'], + ['leftshift', true, 'NCAPS SHIFT'], + ['rightShift', true, 'NCAPS SHIFT'], + ['shift', false, 'SHIFT'], + ['leftshift', false, 'SHIFT'], + ['rightShift', false, 'SHIFT'], + ['shift rightShift?', true, 'NCAPS SHIFT'], + ['rightShift?', true, 'NCAPS'], + ['shift Shift?', true, 'NCAPS SHIFT'], + ['shift rightShift? caps? rightOption? rightControl', true, 'NCAPS SHIFT RCTRL'], + ['leftshift rightShift? caps? rightOption? rightControl', true, 'NCAPS SHIFT RCTRL'], + ['anycontrol', true, 'NCAPS CTRL'], + ['shift?', true, 'NCAPS'], + ['?', true, 'NCAPS'], + ['?', false, ''], + ['', true, 'NCAPS'], + [' ', false, ''], + ['wrongModifierName', false, 'wrongModifierName'], + ['shift', false, 'SHIFT'], + ['shift command', true, 'NCAPS SHIFT command'], + ['rshift', true, 'NCAPS SHIFT'], + ['rshift', false, 'SHIFT'], + ['rightshift', true, 'NCAPS SHIFT'], + ['riGhtsHift', true, 'NCAPS SHIFT'], + ['LEFTCONTROL', true, 'NCAPS LCTRL'], + ['RCONTROL', true, 'NCAPS RCTRL'], + ['leftoption', true, 'NCAPS LALT'], + ['loption', true, 'NCAPS LALT'], + ['rightoption', true, 'NCAPS RALT'], + ['roption', true, 'NCAPS RALT'], + ].forEach(function (values) { + it(('should convert "' + values[0] + '"').padEnd(36, " ") + 'to "' + values[2] + '"', async function () { + const result = sut.createKmnModifier(values[0] as string, values[1] as boolean); + assert.equal(result, values[2]); + }); }); }); - }); - describe('Xkb-kmn: checkIfCapsIsUsed ', function () { - const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); - [ - [[['caps', 'xxx'], ['yyy']], true], - [[['Caps', 'xxx'], ['yyy']], true], - [[['CaPs', 'xxx'], ['yyy']], true], - [[['Caps?', 'xxx'], ['yyy']], false], - [[['zzz', 'xxx'], ['Caps?']], false], - [[['caps?', 'xxx'], ['yyy']], false], - [[['zzz', 'xxx'], ['yyy']], false], - [[['shift', 'xxx'], ['caps']], true], - [[['shift', 'caps'], ['yyy']], true], - [[['caps', 'xxx'], ['caps']], true], - [[['', 'someWordWithCaps'], ['']], false], - [null, false], - [[], false], - [[['', ''], ['']], false], - [[[' ', ' '], [' ']], false], - ].forEach(function (values) { - it(("checkIfCapsIsUsed(" + values[0] + ")").padEnd(40, " ") + "should return " + "'" + values[1] + "'", async function () { - const result = sut.checkIfCapsIsUsed(values[0] as string[][]); - assert.isTrue(result === values[1]); + describe('Xkb-kmn: isAcceptableKeymanModifier ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + [ + ['NCAPS', true], + ['NxCAPS', false], + ['SHIFT', true], + ['ALT', true], + ['RALT', true], + ['LALT', true], + ['CTRL', true], + ['LCTRL', true], + ['RCTRL', true], + ['LCTRL CAPS', true], + ['LCTRL X', false], + ['', true], + [null, false], + ].forEach(function (values) { + it(("isAcceptableKeymanModifier(" + values[0] + ")").padEnd(38, " ") + ' should return ' + values[1], async function () { + const result = sut.isAcceptableKeymanModifier(values[0] as string); + assert.equal(result, values[1]); + }); }); }); - }); - - describe('Xkb-kmn: getModifierArrayFromKeyModifierArray ', function () { - const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const sutR = new XkbFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/tests-xkb-kmn/Test.keylayout'); - const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); - const converted = sut.convertBound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); - [ - [[{ key: '0', behavior: 0 }], [['', 'shift? caps? ']]], - [[{ key: '0', behavior: 2 }], [['shift? leftShift caps? ', 'anyShift caps?', 'shift leftShift caps ', 'shift? rightShift caps? ']]], - [[{ key: '0', behavior: 999 }], [null]], - [[{ key: '999', behavior: null }], [null]], - [[{ key: '0', behavior: -999 }], [null]], - [[{ key: '0', behavior: null }], [null]], - [[], []], - ].forEach(function (values) { - it((values[1] !== null) ? - ("getModifierArrayFromKeyModifierArray('" + JSON.stringify(values[0]) + "')").padEnd(68, " ") + " should return '" + JSON.stringify(values[1]) + "'" : - ("getModifierArrayFromKeyModifierArray('" + JSON.stringify(values[0]) + "')").padEnd(68, " ") + " should return '" + "null" + "'", async function () { - const result = sut.getModifierArrayFromKeyModifierArray(converted.modifiers, values[0] as unknown as KeylayoutFileData[]); - assert.deepStrictEqual(JSON.stringify(result), JSON.stringify(values[1])); + describe('Xkb-kmn: mapUkeleleKeycodeToVK ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + [ + [0x00, 'K_A'], + [0x31, 'K_SPACE'], + [0x18, 'K_EQUAL'], + [0x10, 'K_Y'], + [0x18, 'K_EQUAL'], + [0x21, 'K_LBRKT'], + [0x999, ''], + [-1, ''], + [null, ''], + [undefined, ''], + [, ''], + ].forEach(function (values) { + it(("mapUkeleleKeycodeToVK(" + values[0] + ")").padEnd(26, " ") + "should return " + "'" + values[1] + "'", async function () { + const result = sut.mapUkeleleKeycodeToVK(values[0] as number); + assert.equal(result, values[1]); }); + }); }); - }); - describe('Xkb-kmn: getKeyModifierArrayFromActionID ', function () { - const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const sutR = new XkbFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/tests-xkb-kmn/Test.keylayout'); - const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); - [ - ['A_16', [{ "key": "32", "behavior": "5" }]], - ['A_19', [{ "key": "45", "behavior": "5" }]], - ['A_18', [{ "key": "24", "behavior": "0" }, { "key": "24", "behavior": "5" }]], - ['unknown', []], - [undefined, []], - [null, []], - [' ', []], - ['', []], - ].forEach(function (values) { - let outstring = '[ '; - for (let i = 0; i < values[1].length; i++) { - outstring = outstring + "[ " + JSON.stringify(values[1][i]) + "], "; - } - it(("getKeyModifierArrayFromActionID('" + values[0] + "')").padEnd(57, " ") + ' should return ' + outstring.substring(0, outstring.lastIndexOf(']') + 2) + " ]", async function () { - const result = sut.getKeyModifierArrayFromActionID(read, String(values[0])); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + describe('Xkb-kmn: checkIfCapsIsUsed ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + [ + [[['caps', 'xxx'], ['yyy']], true], + [[['Caps', 'xxx'], ['yyy']], true], + [[['CaPs', 'xxx'], ['yyy']], true], + [[['Caps?', 'xxx'], ['yyy']], false], + [[['zzz', 'xxx'], ['Caps?']], false], + [[['caps?', 'xxx'], ['yyy']], false], + [[['zzz', 'xxx'], ['yyy']], false], + [[['shift', 'xxx'], ['caps']], true], + [[['shift', 'caps'], ['yyy']], true], + [[['caps', 'xxx'], ['caps']], true], + [[['', 'someWordWithCaps'], ['']], false], + [null, false], + [[], false], + [[['', ''], ['']], false], + [[[' ', ' '], [' ']], false], + ].forEach(function (values) { + it(("checkIfCapsIsUsed(" + values[0] + ")").padEnd(40, " ") + "should return " + "'" + values[1] + "'", async function () { + const result = sut.checkIfCapsIsUsed(values[0] as string[][]); + assert.isTrue(result === values[1]); + }); }); }); - }); - describe('Xkb-kmn: getActionIdFromActionNext ', function () { - const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const sutR = new XkbFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/tests-xkb-kmn/Test.keylayout'); - const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); - [ - ['none', ''], - ['0', ''], - ['A_18', ''], - ['1', 'A_16'], - ['2', 'A_8'], - ['3', 'A_17'], - ['', ''], - [' ', ''], - ['99', ''], - [null, ''], - [undefined, ''], - ['unknown', ''], - ].forEach(function (values) { - it(("getActionIdFromActionNext('" + values[0] + "')").padEnd(49, " ") + ' should return ' + "'" + values[1] + "'", async function () { - const result = sut.getActionIdFromActionNext(read, String(values[0])); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + describe('Xkb-kmn: getModifierArrayFromKeyModifierArray ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sutR = new XkbFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/tests-xkb-kmn/Test.keylayout'); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + const converted = sut.convertBound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); + [ + [[{ key: '0', behavior: 0 }], [['', 'shift? caps? ']]], + [[{ key: '0', behavior: 2 }], [['shift? leftShift caps? ', 'anyShift caps?', 'shift leftShift caps ', 'shift? rightShift caps? ']]], + [[{ key: '0', behavior: 999 }], [null]], + [[{ key: '999', behavior: null }], [null]], + [[{ key: '0', behavior: -999 }], [null]], + [[{ key: '0', behavior: null }], [null]], + [[], []], + + ].forEach(function (values) { + it((values[1] !== null) ? + ("getModifierArrayFromKeyModifierArray('" + JSON.stringify(values[0]) + "')").padEnd(68, " ") + " should return '" + JSON.stringify(values[1]) + "'" : + ("getModifierArrayFromKeyModifierArray('" + JSON.stringify(values[0]) + "')").padEnd(68, " ") + " should return '" + "null" + "'", async function () { + const result = sut.getModifierArrayFromKeyModifierArray(converted.modifiers, values[0] as unknown as KeylayoutFileData[]); + assert.deepStrictEqual(JSON.stringify(result), JSON.stringify(values[1])); + }); }); }); - }); - describe('Xkb-kmn: getActionIndexFromActionId ', function () { - const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const sutR = new XkbFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/tests-xkb-kmn/Test.keylayout'); - const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); - [ - ['none', -1], - ['A_16', 8], - ['A_18', 10], - ['A_19', 11], - ['0', -1], - ['', -1], - [' ', -1], - [null, -1], - [undefined, -1], - ['unknown', -1], - ].forEach(function (values) { - it(("getActionIndexFromActionId('" + values[0] + "')").padEnd(50, " ") + ' should return ' + values[1], async function () { - const result = sut.getActionIndexFromActionId(read, String(values[0])); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + describe('Xkb-kmn: getKeyModifierArrayFromActionID ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sutR = new XkbFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/tests-xkb-kmn/Test.keylayout'); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + [ + ['A_16', [{ "key": "32", "behavior": "5" }]], + ['A_19', [{ "key": "45", "behavior": "5" }]], + ['A_18', [{ "key": "24", "behavior": "0" }, { "key": "24", "behavior": "5" }]], + ['unknown', []], + [undefined, []], + [null, []], + [' ', []], + ['', []], + ].forEach(function (values) { + let outstring = '[ '; + for (let i = 0; i < values[1].length; i++) { + outstring = outstring + "[ " + JSON.stringify(values[1][i]) + "], "; + } + it(("getKeyModifierArrayFromActionID('" + values[0] + "')").padEnd(57, " ") + ' should return ' + outstring.substring(0, outstring.lastIndexOf(']') + 2) + " ]", async function () { + const result = sut.getKeyModifierArrayFromActionID(read, String(values[0])); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); }); }); - }); - describe('Xkb-kmn: getOutputFromActionIdNone ', function () { - const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const sutR = new XkbFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/tests-xkb-kmn/Test.keylayout'); - const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); - [ - ['A_14', 'u'], - ['', ''], - [' ', ''], - ['A_18', ''], - ['unknown', ''], - ].forEach(function (values) { - it( - ("getOutputFromActionIdNone('" + values[0] + "')").padEnd(56, " ") + ' should return ' + "'" + values[1] + "'", async function () { - const result = sut.getOutputFromActionIdNone(read, String(values[0])); + describe('Xkb-kmn: getActionIdFromActionNext ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sutR = new XkbFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/tests-xkb-kmn/Test.keylayout'); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + [ + ['none', ''], + ['0', ''], + ['A_18', ''], + ['1', 'A_16'], + ['2', 'A_8'], + ['3', 'A_17'], + ['', ''], + [' ', ''], + ['99', ''], + [null, ''], + [undefined, ''], + ['unknown', ''], + ].forEach(function (values) { + it(("getActionIdFromActionNext('" + values[0] + "')").padEnd(49, " ") + ' should return ' + "'" + values[1] + "'", async function () { + const result = sut.getActionIdFromActionNext(read, String(values[0])); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); + }); }); - [[null, ''], - [undefined, ''], - [99, ''], - ].forEach(function (values) { - it(("getOutputFromActionIdNone('" + values[0] + "')").padEnd(56, " ") + ' should return ' + values[1], async function () { - const result = sut.getOutputFromActionIdNone(read, String(values[0])); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + describe('Xkb-kmn: getActionIndexFromActionId ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sutR = new XkbFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/tests-xkb-kmn/Test.keylayout'); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + [ + ['none', -1], + ['A_16', 8], + ['A_18', 10], + ['A_19', 11], + ['0', -1], + ['', -1], + [' ', -1], + [null, -1], + [undefined, -1], + ['unknown', -1], + ].forEach(function (values) { + it(("getActionIndexFromActionId('" + values[0] + "')").padEnd(50, " ") + ' should return ' + values[1], async function () { + const result = sut.getActionIndexFromActionId(read, String(values[0])); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); }); }); - }); - describe('Xkb-kmn: getKeybehaviorModOutputArrayFromKeyActionbehaviorOutputArray ', function () { - const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const sutR = new XkbFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/tests-xkb-kmn/Test.keylayout'); - const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); - - const b1KeycodeArr: KeylayoutFileData[] = [ - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '0', outchar: 'ˆ' }, - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '1', outchar: 'ˆ' }, - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '2', outchar: 'ˆ' }, - { keyCode: '6', key: 'K_Z', actionId: 'A_0', behavior: '4', outchar: 'ˆ' }, - { keyCode: '25', key: 'K_9', actionId: 'A_0', behavior: '4', outchar: 'ˆ' }, - { keyCode: '43', key: 'K_COMMA', actionId: 'A_0', behavior: '4', outchar: 'ˆ' }, - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '3', outchar: 'ˆ' }, - { keyCode: '0', key: 'K_A', actionId: 'A_1', behavior: '2', outchar: 'Â' }, - { keyCode: '0', key: 'K_A', actionId: 'A_1', behavior: '1', outchar: 'Â' }, - { keyCode: '14', key: 'K_E', actionId: 'A_10', behavior: '0', outchar: 'ê' }, - { keyCode: '34', key: 'K_I', actionId: 'A_11', behavior: '0', outchar: 'î' }, - { keyCode: '31', key: 'K_O', actionId: 'A_13', behavior: '0', outchar: 'ô' }, - { keyCode: '32', key: 'K_U', actionId: 'A_14', behavior: '0', outchar: 'û' }, - { keyCode: '14', key: 'K_E', actionId: 'A_2', behavior: '2', outchar: 'Ê' }, - { keyCode: '14', key: 'K_E', actionId: 'A_2', behavior: '1', outchar: 'Ê' }, - { keyCode: '34', key: 'K_I', actionId: 'A_3', behavior: '2', outchar: 'Î' }, - { keyCode: '34', key: 'K_I', actionId: 'A_3', behavior: '1', outchar: 'Î' }, - { keyCode: '31', key: 'K_O', actionId: 'A_5', behavior: '2', outchar: 'Ô' }, - { keyCode: '31', key: 'K_O', actionId: 'A_5', behavior: '1', outchar: 'Ô' }, - { keyCode: '32', key: 'K_U', actionId: 'A_6', behavior: '2', outchar: 'Û' }, - { keyCode: '32', key: 'K_U', actionId: 'A_6', behavior: '1', outchar: 'Û' }, - { keyCode: '0', key: 'K_A', actionId: 'A_9', behavior: '0', outchar: 'â' } - - ]; - const b1ModifierKeyArr: KeylayoutFileData[] = [ - { actionId: 'A_0', key: 'K_SPACE', behavior: '0', modifier: 'NCAPS', outchar: 'ˆ' }, - { actionId: 'A_0', key: 'K_SPACE', behavior: '1', modifier: 'CAPS', outchar: 'ˆ' }, - { actionId: 'A_0', key: 'K_SPACE', behavior: '2', modifier: 'NCAPS SHIFT', outchar: 'ˆ' }, - { actionId: 'A_0', key: 'K_SPACE', behavior: '2', modifier: 'SHIFT CAPS', outchar: 'ˆ' }, - { actionId: 'A_0', key: 'K_Z', behavior: '4', modifier: 'NCAPS SHIFT RALT', outchar: 'ˆ' }, - { actionId: 'A_0', key: 'K_9', behavior: '4', modifier: 'NCAPS SHIFT RALT', outchar: 'ˆ' }, - { actionId: 'A_0', key: 'K_COMMA', behavior: '4', modifier: 'NCAPS SHIFT RALT', outchar: 'ˆ' }, - { actionId: 'A_0', key: 'K_SPACE', behavior: '3', modifier: 'NCAPS RALT CTRL', outchar: 'ˆ' }, - { actionId: 'A_0', key: 'K_SPACE', behavior: '3', modifier: 'NCAPS CTRL', outchar: 'ˆ' }, - { actionId: 'A_1', key: 'K_A', behavior: '2', modifier: 'NCAPS SHIFT', outchar: 'Â' }, - { actionId: 'A_1', key: 'K_A', behavior: '2', modifier: 'SHIFT CAPS', outchar: 'Â' }, - { actionId: 'A_1', key: 'K_A', behavior: '1', modifier: 'CAPS', outchar: 'Â' }, - { actionId: 'A_10', key: 'K_E', behavior: '0', modifier: 'NCAPS', outchar: 'ê' }, - { actionId: 'A_11', key: 'K_I', behavior: '0', modifier: 'NCAPS', outchar: 'î' }, - { actionId: 'A_13', key: 'K_O', behavior: '0', modifier: 'NCAPS', outchar: 'ô' }, - { actionId: 'A_14', key: 'K_U', behavior: '0', modifier: 'NCAPS', outchar: 'û' }, - { actionId: 'A_2', key: 'K_E', behavior: '2', modifier: 'NCAPS SHIFT', outchar: 'Ê' }, - { actionId: 'A_2', key: 'K_E', behavior: '2', modifier: 'SHIFT CAPS', outchar: 'Ê' }, - { actionId: 'A_2', key: 'K_E', behavior: '1', modifier: 'CAPS', outchar: 'Ê' }, - { actionId: 'A_3', key: 'K_I', behavior: '2', modifier: 'NCAPS SHIFT', outchar: 'Î' }, - { actionId: 'A_3', key: 'K_I', behavior: '2', modifier: 'SHIFT CAPS', outchar: 'Î' }, - { actionId: 'A_3', key: 'K_I', behavior: '1', modifier: 'CAPS', outchar: 'Î' }, - { actionId: 'A_5', key: 'K_O', behavior: '2', modifier: 'NCAPS SHIFT', outchar: 'Ô' }, - { actionId: 'A_5', key: 'K_O', behavior: '2', modifier: 'SHIFT CAPS', outchar: 'Ô' }, - { actionId: 'A_5', key: 'K_O', behavior: '1', modifier: 'CAPS', outchar: 'Ô' }, - { actionId: 'A_6', key: 'K_U', behavior: '2', modifier: 'NCAPS SHIFT', outchar: 'Û' }, - { actionId: 'A_6', key: 'K_U', behavior: '2', modifier: 'SHIFT CAPS', outchar: 'Û' }, - { actionId: 'A_6', key: 'K_U', behavior: '1', modifier: 'CAPS', outchar: 'Û' }, - { actionId: 'A_9', key: 'K_A', behavior: '0', modifier: 'NCAPS', outchar: 'â' } - ]; - - [[b1KeycodeArr, b1ModifierKeyArr], - [[{ keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '0', modifier: '0', outchar: 'ˆ' }], [{ actionId: 'A_0', key: 'K_SPACE', behavior: '0', modifier: 'NCAPS', outchar: 'ˆ' }]], - [[{ keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '0', modifier: '', outchar: 'ˆ' }], [{ actionId: 'A_0', key: 'K_SPACE', behavior: '0', modifier: 'NCAPS', outchar: 'ˆ' }]], - [[{ keyCode: '49', key: 'K_SPACE', actionId: '', behavior: '0', modifier: '0', outchar: 'ˆ' }], [{ actionId: '', key: 'K_SPACE', behavior: '0', modifier: 'NCAPS', outchar: 'ˆ' }]], - [[{ keyCode: '49', key: '', actionId: 'A_0', behavior: '0', modifier: '0', outchar: 'ˆ' }], [{ actionId: 'A_0', key: '', behavior: '0', modifier: 'NCAPS', outchar: 'ˆ' }]], - [[{ keyCode: '', key: 'K_SPACE', actionId: 'A_0', behavior: '0', modifier: '0', outchar: 'ˆ' }], [{ actionId: 'A_0', key: 'K_SPACE', behavior: '0', modifier: 'NCAPS', outchar: 'ˆ' }]], - [[{ keyCode: '', key: '', actionId: '', behavior: '0', modifier: '', outchar: '' }], [{ actionId: '', key: '', behavior: '0', modifier: 'NCAPS', outchar: '' }]], - ].forEach(function (values) { - const isCapsUsed = true; - const stringIn = "getKeybehaviorModOutputArrayFromKeyActionbehaviorOutputArray(['" + "', '" + "', '" + values[0][0].keyCode + "', '" + values[0][0].key + "', '" + values[0][0].actionId + "', '" + values[0][0].modifier + "', '" + values[0][0].outchar + "'])"; - const stringOut = "['" + "', '" + "', '" + values[1][0].key + "', '" + values[1][0].actionId + "', '" + "', '" + values[1][0].modifier + "', '" + values[1][0].outchar + "']"; + describe('Xkb-kmn: getOutputFromActionIdNone ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sutR = new XkbFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/tests-xkb-kmn/Test.keylayout'); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + [ + ['A_14', 'u'], + ['', ''], + [' ', ''], + ['A_18', ''], + ['unknown', ''], + ].forEach(function (values) { + it( + ("getOutputFromActionIdNone('" + values[0] + "')").padEnd(56, " ") + ' should return ' + "'" + values[1] + "'", async function () { + const result = sut.getOutputFromActionIdNone(read, String(values[0])); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); - it((JSON.stringify(values[1]).length > 60) ? 'an array of objects should return an array of objects' : - stringIn.padEnd(74, " ") + ' should return ' + stringOut, async function () { - const result = sut.getKeyBehaviorModOutputArrayFromKeyActionBehaviorOutputArray(read, values[0], isCapsUsed); + [[null, ''], + [undefined, ''], + [99, ''], + ].forEach(function (values) { + it(("getOutputFromActionIdNone('" + values[0] + "')").padEnd(56, " ") + ' should return ' + values[1], async function () { + const result = sut.getOutputFromActionIdNone(read, String(values[0])); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); + }); }); - [[{ keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '0', modifier: '0', outchar: 'ˆ' }, { actionId: 'A_0', key: 'K_SPACE', behavior: '0', modifier: '', outchar: 'ˆ' }], - [{ keyCode: '', key: 'K_SPACE', actionId: 'A_0', behavior: '0', modifier: '0', outchar: 'ˆ' }, { actionId: 'A_0', key: 'K_SPACE', behavior: '0', modifier: '', outchar: 'ˆ' }], - [{ keyCode: '', key: '', actionId: '', behavior: '0', modifier: '', outchar: '' }, { actionId: '', key: '', behavior: '0', modifier: '', outchar: '' }], - ].forEach(function (values) { - const isCapsUsed = false; - const stringIn = "getKeybehaviorModOutputArrayFromKeyActionbehaviorOutputArray([ '" + values[0].keyCode + "', '" + values[0].key + "', '" + values[0].actionId + "', '" + values[0].modifier + "', '" + values[0].outchar + "'])"; - const stringOut = "['" + values[1].actionId + "', '" + "', '" + values[1].modifier + "', '" + values[1].key + "', '" + values[1].outchar + "']"; - - it(stringIn.padEnd(74, " ") + ' should return ' + stringOut, async function () { - const result = sut.getKeyBehaviorModOutputArrayFromKeyActionBehaviorOutputArray(read, [values[0]], isCapsUsed); - assert.equal(JSON.stringify(result), JSON.stringify([values[1]])); + describe('Xkb-kmn: getKeybehaviorModOutputArrayFromKeyActionbehaviorOutputArray ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sutR = new XkbFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/tests-xkb-kmn/Test.keylayout'); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + + const b1KeycodeArr: KeylayoutFileData[] = [ + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '0', outchar: 'ˆ' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '1', outchar: 'ˆ' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '2', outchar: 'ˆ' }, + { keyCode: '6', key: 'K_Z', actionId: 'A_0', behavior: '4', outchar: 'ˆ' }, + { keyCode: '25', key: 'K_9', actionId: 'A_0', behavior: '4', outchar: 'ˆ' }, + { keyCode: '43', key: 'K_COMMA', actionId: 'A_0', behavior: '4', outchar: 'ˆ' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '3', outchar: 'ˆ' }, + { keyCode: '0', key: 'K_A', actionId: 'A_1', behavior: '2', outchar: 'Â' }, + { keyCode: '0', key: 'K_A', actionId: 'A_1', behavior: '1', outchar: 'Â' }, + { keyCode: '14', key: 'K_E', actionId: 'A_10', behavior: '0', outchar: 'ê' }, + { keyCode: '34', key: 'K_I', actionId: 'A_11', behavior: '0', outchar: 'î' }, + { keyCode: '31', key: 'K_O', actionId: 'A_13', behavior: '0', outchar: 'ô' }, + { keyCode: '32', key: 'K_U', actionId: 'A_14', behavior: '0', outchar: 'û' }, + { keyCode: '14', key: 'K_E', actionId: 'A_2', behavior: '2', outchar: 'Ê' }, + { keyCode: '14', key: 'K_E', actionId: 'A_2', behavior: '1', outchar: 'Ê' }, + { keyCode: '34', key: 'K_I', actionId: 'A_3', behavior: '2', outchar: 'Î' }, + { keyCode: '34', key: 'K_I', actionId: 'A_3', behavior: '1', outchar: 'Î' }, + { keyCode: '31', key: 'K_O', actionId: 'A_5', behavior: '2', outchar: 'Ô' }, + { keyCode: '31', key: 'K_O', actionId: 'A_5', behavior: '1', outchar: 'Ô' }, + { keyCode: '32', key: 'K_U', actionId: 'A_6', behavior: '2', outchar: 'Û' }, + { keyCode: '32', key: 'K_U', actionId: 'A_6', behavior: '1', outchar: 'Û' }, + { keyCode: '0', key: 'K_A', actionId: 'A_9', behavior: '0', outchar: 'â' } + + ]; + const b1ModifierKeyArr: KeylayoutFileData[] = [ + { actionId: 'A_0', key: 'K_SPACE', behavior: '0', modifier: 'NCAPS', outchar: 'ˆ' }, + { actionId: 'A_0', key: 'K_SPACE', behavior: '1', modifier: 'CAPS', outchar: 'ˆ' }, + { actionId: 'A_0', key: 'K_SPACE', behavior: '2', modifier: 'NCAPS SHIFT', outchar: 'ˆ' }, + { actionId: 'A_0', key: 'K_SPACE', behavior: '2', modifier: 'SHIFT CAPS', outchar: 'ˆ' }, + { actionId: 'A_0', key: 'K_Z', behavior: '4', modifier: 'NCAPS SHIFT RALT', outchar: 'ˆ' }, + { actionId: 'A_0', key: 'K_9', behavior: '4', modifier: 'NCAPS SHIFT RALT', outchar: 'ˆ' }, + { actionId: 'A_0', key: 'K_COMMA', behavior: '4', modifier: 'NCAPS SHIFT RALT', outchar: 'ˆ' }, + { actionId: 'A_0', key: 'K_SPACE', behavior: '3', modifier: 'NCAPS RALT CTRL', outchar: 'ˆ' }, + { actionId: 'A_0', key: 'K_SPACE', behavior: '3', modifier: 'NCAPS CTRL', outchar: 'ˆ' }, + { actionId: 'A_1', key: 'K_A', behavior: '2', modifier: 'NCAPS SHIFT', outchar: 'Â' }, + { actionId: 'A_1', key: 'K_A', behavior: '2', modifier: 'SHIFT CAPS', outchar: 'Â' }, + { actionId: 'A_1', key: 'K_A', behavior: '1', modifier: 'CAPS', outchar: 'Â' }, + { actionId: 'A_10', key: 'K_E', behavior: '0', modifier: 'NCAPS', outchar: 'ê' }, + { actionId: 'A_11', key: 'K_I', behavior: '0', modifier: 'NCAPS', outchar: 'î' }, + { actionId: 'A_13', key: 'K_O', behavior: '0', modifier: 'NCAPS', outchar: 'ô' }, + { actionId: 'A_14', key: 'K_U', behavior: '0', modifier: 'NCAPS', outchar: 'û' }, + { actionId: 'A_2', key: 'K_E', behavior: '2', modifier: 'NCAPS SHIFT', outchar: 'Ê' }, + { actionId: 'A_2', key: 'K_E', behavior: '2', modifier: 'SHIFT CAPS', outchar: 'Ê' }, + { actionId: 'A_2', key: 'K_E', behavior: '1', modifier: 'CAPS', outchar: 'Ê' }, + { actionId: 'A_3', key: 'K_I', behavior: '2', modifier: 'NCAPS SHIFT', outchar: 'Î' }, + { actionId: 'A_3', key: 'K_I', behavior: '2', modifier: 'SHIFT CAPS', outchar: 'Î' }, + { actionId: 'A_3', key: 'K_I', behavior: '1', modifier: 'CAPS', outchar: 'Î' }, + { actionId: 'A_5', key: 'K_O', behavior: '2', modifier: 'NCAPS SHIFT', outchar: 'Ô' }, + { actionId: 'A_5', key: 'K_O', behavior: '2', modifier: 'SHIFT CAPS', outchar: 'Ô' }, + { actionId: 'A_5', key: 'K_O', behavior: '1', modifier: 'CAPS', outchar: 'Ô' }, + { actionId: 'A_6', key: 'K_U', behavior: '2', modifier: 'NCAPS SHIFT', outchar: 'Û' }, + { actionId: 'A_6', key: 'K_U', behavior: '2', modifier: 'SHIFT CAPS', outchar: 'Û' }, + { actionId: 'A_6', key: 'K_U', behavior: '1', modifier: 'CAPS', outchar: 'Û' }, + { actionId: 'A_9', key: 'K_A', behavior: '0', modifier: 'NCAPS', outchar: 'â' } + ]; + + [[b1KeycodeArr, b1ModifierKeyArr], + [[{ keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '0', modifier: '0', outchar: 'ˆ' }], [{ actionId: 'A_0', key: 'K_SPACE', behavior: '0', modifier: 'NCAPS', outchar: 'ˆ' }]], + [[{ keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '0', modifier: '', outchar: 'ˆ' }], [{ actionId: 'A_0', key: 'K_SPACE', behavior: '0', modifier: 'NCAPS', outchar: 'ˆ' }]], + [[{ keyCode: '49', key: 'K_SPACE', actionId: '', behavior: '0', modifier: '0', outchar: 'ˆ' }], [{ actionId: '', key: 'K_SPACE', behavior: '0', modifier: 'NCAPS', outchar: 'ˆ' }]], + [[{ keyCode: '49', key: '', actionId: 'A_0', behavior: '0', modifier: '0', outchar: 'ˆ' }], [{ actionId: 'A_0', key: '', behavior: '0', modifier: 'NCAPS', outchar: 'ˆ' }]], + [[{ keyCode: '', key: 'K_SPACE', actionId: 'A_0', behavior: '0', modifier: '0', outchar: 'ˆ' }], [{ actionId: 'A_0', key: 'K_SPACE', behavior: '0', modifier: 'NCAPS', outchar: 'ˆ' }]], + [[{ keyCode: '', key: '', actionId: '', behavior: '0', modifier: '', outchar: '' }], [{ actionId: '', key: '', behavior: '0', modifier: 'NCAPS', outchar: '' }]], + ].forEach(function (values) { + const isCapsUsed = true; + const stringIn = "getKeybehaviorModOutputArrayFromKeyActionbehaviorOutputArray(['" + "', '" + "', '" + values[0][0].keyCode + "', '" + values[0][0].key + "', '" + values[0][0].actionId + "', '" + values[0][0].modifier + "', '" + values[0][0].outchar + "'])"; + const stringOut = "['" + "', '" + "', '" + values[1][0].key + "', '" + values[1][0].actionId + "', '" + "', '" + values[1][0].modifier + "', '" + values[1][0].outchar + "']"; + + it((JSON.stringify(values[1]).length > 60) ? 'an array of objects should return an array of objects' : + stringIn.padEnd(74, " ") + ' should return ' + stringOut, async function () { + const result = sut.getKeyBehaviorModOutputArrayFromKeyActionBehaviorOutputArray(read, values[0], isCapsUsed); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); }); - }); - [[[], []], - [undefined, []], - [null, []], - ].forEach(function (values) { - const isCaps = true; - it(("getKeybehaviorModOutputArrayFromKeyActionbehaviorOutputArray([" + values[0] + "])").padEnd(74, " ") + ' should return ' + "[" + values[1] + "]", async function () { - const result = sut.getKeyBehaviorModOutputArrayFromKeyActionBehaviorOutputArray(read, values[0], isCaps); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + [[{ keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '0', modifier: '0', outchar: 'ˆ' }, { actionId: 'A_0', key: 'K_SPACE', behavior: '0', modifier: '', outchar: 'ˆ' }], + [{ keyCode: '', key: 'K_SPACE', actionId: 'A_0', behavior: '0', modifier: '0', outchar: 'ˆ' }, { actionId: 'A_0', key: 'K_SPACE', behavior: '0', modifier: '', outchar: 'ˆ' }], + [{ keyCode: '', key: '', actionId: '', behavior: '0', modifier: '', outchar: '' }, { actionId: '', key: '', behavior: '0', modifier: '', outchar: '' }], + ].forEach(function (values) { + const isCapsUsed = false; + const stringIn = "getKeybehaviorModOutputArrayFromKeyActionbehaviorOutputArray([ '" + values[0].keyCode + "', '" + values[0].key + "', '" + values[0].actionId + "', '" + values[0].modifier + "', '" + values[0].outchar + "'])"; + const stringOut = "['" + values[1].actionId + "', '" + "', '" + values[1].modifier + "', '" + values[1].key + "', '" + values[1].outchar + "']"; + + it(stringIn.padEnd(74, " ") + ' should return ' + stringOut, async function () { + const result = sut.getKeyBehaviorModOutputArrayFromKeyActionBehaviorOutputArray(read, [values[0]], isCapsUsed); + assert.equal(JSON.stringify(result), JSON.stringify([values[1]])); + }); }); - }); - }); - describe('Xkb-kmn: getActionStateOutputArrayFromActionState ', function () { - const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const sutR = new XkbFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/tests-xkb-kmn/Test.keylayout'); - const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); - [['1', [ - { "id": "A_0", "state": "1", "output": "ˆ" }, - { "id": "A_1", "state": "1", "output": "Â" }, - { "id": "A_10", "state": "1", "output": "ê" }, - { "id": "A_11", "state": "1", "output": "î" }, - { "id": "A_13", "state": "1", "output": "ô" }, - { "id": "A_14", "state": "1", "output": "û" }, - { "id": "A_2", "state": "1", "output": "Ê" }, - { "id": "A_3", "state": "1", "output": "Î" }, - { "id": "A_5", "state": "1", "output": "Ô" }, - { "id": "A_6", "state": "1", "output": "Û" }, - { "id": "A_9", "state": "1", "output": "â" } - ],], - ['2', [ - { "id": "A_0", "state": "2", "output": "`" }, - { "id": "A_1", "state": "2", "output": "À" }, - { "id": "A_10", "state": "2", "output": "è" }, - { "id": "A_11", "state": "2", "output": "ì" }, - { "id": "A_13", "state": "2", "output": "ò" }, - { "id": "A_14", "state": "2", "output": "ù" }, - { "id": "A_2", "state": "2", "output": "È" }, - { "id": "A_3", "state": "2", "output": "Ì" }, - { "id": "A_5", "state": "2", "output": "Ò" }, - { "id": "A_6", "state": "2", "output": "Ù" }, - { "id": "A_9", "state": "2", "output": "à" } - ],], - ['789', [],], - ['', [],], - [' ', [],], - [123, [],], - [null, [],], - [undefined, [],], - ].forEach(function (values) { - it((JSON.stringify(values[1]).length > 30) ? - ("getActionStateOutputArrayFromActionState('" + values[0] + "')").padEnd(60, " ") + ' should return an array of objects' : - ("getActionStateOutputArrayFromActionState('" + values[0] + "')").padEnd(60, " ") + ' should return ' + "'" + JSON.stringify(values[1]) + "'", async function () { - const result = sut.getActionStateOutputArrayFromActionState(read, String(values[0])); + [[[], []], + [undefined, []], + [null, []], + ].forEach(function (values) { + const isCaps = true; + it(("getKeybehaviorModOutputArrayFromKeyActionbehaviorOutputArray([" + values[0] + "])").padEnd(74, " ") + ' should return ' + "[" + values[1] + "]", async function () { + const result = sut.getKeyBehaviorModOutputArrayFromKeyActionBehaviorOutputArray(read, values[0], isCaps); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); + }); }); - }); - describe('Xkb-kmn: getActionOutputbehaviorKeyModiFromActionIDStateOutput ', function () { - const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const sutR = new XkbFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/tests-xkb-kmn/Test.keylayout'); - const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); - const converted = sut.convertBound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); - [ - ['A_1', 'A', true, - [{ "outchar": "A", "actionId": "A_1", "behavior": "1", "key": "K_A", "modifier": "CAPS" }, - { "outchar": "A", "actionId": "A_1", "behavior": "2", "key": "K_A", "modifier": "NCAPS SHIFT" }, - { "outchar": "A", "actionId": "A_1", "behavior": "2", "key": "K_A", "modifier": "SHIFT CAPS" }] - ], - ['A_1', 'A', false, - [{ "outchar": "A", "actionId": "A_1", "behavior": "1", "key": "K_A", "modifier": "CAPS" }, - { "outchar": "A", "actionId": "A_1", "behavior": "2", "key": "K_A", "modifier": "SHIFT" }, - { "outchar": "A", "actionId": "A_1", "behavior": "2", "key": "K_A", "modifier": "SHIFT CAPS" }] - ], - ['A_9', 'a', true, [{ "outchar": "a", "actionId": "A_9", "behavior": "0", "key": "K_A", "modifier": "NCAPS" }]], - ['A_9', 'a', false, [{ "outchar": "a", "actionId": "A_9", "behavior": "0", "key": "K_A", "modifier": "" }]], - ['A_9', 'a', , [{ "outchar": "a", "actionId": "A_9", "behavior": "0", "key": "K_A", "modifier": "" }]], - ['A_9', '', true, [{ "outchar": "", "actionId": "A_9", "behavior": "0", "key": "K_A", "modifier": "NCAPS" }]], - ['A_9', '', false, [{ "outchar": "", "actionId": "A_9", "behavior": "0", "key": "K_A", "modifier": "" }]], - ['', 'a', true, []], - ['', 'a', false, []], - ['', '', , []], - ].forEach(function (values) { - it((JSON.stringify(values[3]).length > 35) ? - ("getActionOutputbehaviorKeyModiFromActionIDStateOutput('" + values[0] + "', '" + values[1] + "', " + values[2] + ")").padEnd(67, " ") + ' should return an array of objects' : - ("getActionOutputbehaviorKeyModiFromActionIDStateOutput('" + values[0] + "', '" + values[1] + "', " + values[2] + ")").padEnd(67, " ") + ' should return ' + "'" + JSON.stringify(values[3]) + "'", async function () { - const result = sut.getActionOutputBehaviorKeyModiFromActionIDStateOutput(read, converted.modifiers, String(values[0]), String(values[1]), Boolean(values[2])); - assert.equal(JSON.stringify(result), JSON.stringify(values[3])); - }); + describe('Xkb-kmn: getActionStateOutputArrayFromActionState ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sutR = new XkbFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/tests-xkb-kmn/Test.keylayout'); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + [['1', [ + { "id": "A_0", "state": "1", "output": "ˆ" }, + { "id": "A_1", "state": "1", "output": "Â" }, + { "id": "A_10", "state": "1", "output": "ê" }, + { "id": "A_11", "state": "1", "output": "î" }, + { "id": "A_13", "state": "1", "output": "ô" }, + { "id": "A_14", "state": "1", "output": "û" }, + { "id": "A_2", "state": "1", "output": "Ê" }, + { "id": "A_3", "state": "1", "output": "Î" }, + { "id": "A_5", "state": "1", "output": "Ô" }, + { "id": "A_6", "state": "1", "output": "Û" }, + { "id": "A_9", "state": "1", "output": "â" } + ],], + ['2', [ + { "id": "A_0", "state": "2", "output": "`" }, + { "id": "A_1", "state": "2", "output": "À" }, + { "id": "A_10", "state": "2", "output": "è" }, + { "id": "A_11", "state": "2", "output": "ì" }, + { "id": "A_13", "state": "2", "output": "ò" }, + { "id": "A_14", "state": "2", "output": "ù" }, + { "id": "A_2", "state": "2", "output": "È" }, + { "id": "A_3", "state": "2", "output": "Ì" }, + { "id": "A_5", "state": "2", "output": "Ò" }, + { "id": "A_6", "state": "2", "output": "Ù" }, + { "id": "A_9", "state": "2", "output": "à" } + ],], + ['789', [],], + ['', [],], + [' ', [],], + [123, [],], + [null, [],], + [undefined, [],], + ].forEach(function (values) { + it((JSON.stringify(values[1]).length > 30) ? + ("getActionStateOutputArrayFromActionState('" + values[0] + "')").padEnd(60, " ") + ' should return an array of objects' : + ("getActionStateOutputArrayFromActionState('" + values[0] + "')").padEnd(60, " ") + ' should return ' + "'" + JSON.stringify(values[1]) + "'", async function () { + const result = sut.getActionStateOutputArrayFromActionState(read, String(values[0])); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); }); - }); - describe('Xkb-kmn: getKeyActionOutputArrayFromActionStateOutputArray ', function () { - const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const sutR = new XkbFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/tests-xkb-kmn/Test.keylayout'); - const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); - - const b6ActionIdArr: ActionStateOutput[] = [ - { "id": "A_0", "state": "1", "output": "ˆ" }, - { "id": "A_1", "state": "1", "output": "Â" }, - { "id": "A_10", "state": "1", "output": "ê" }, - { "id": "A_11", "state": "1", "output": "î" }, - { "id": "A_13", "state": "1", "output": "ô" }, - { "id": "A_14", "state": "1", "output": "û" }, - { "id": "A_2", "state": "1", "output": "Ê" }, - { "id": "A_3", "state": "1", "output": "Î" }, - { "id": "A_5", "state": "1", "output": "Ô" }, - { "id": "A_6", "state": "1", "output": "Û" }, - { "id": "A_9", "state": "1", "output": "â" } - ]; - - const b1KeycodeArr: KeylayoutFileData[] = [ - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '0', outchar: 'ˆ' }, - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '1', outchar: 'ˆ' }, - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '2', outchar: 'ˆ' }, - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '3', outchar: 'ˆ' }, - { keyCode: '6', key: 'K_Z', actionId: 'A_0', behavior: '4', outchar: 'ˆ' }, - { keyCode: '25', key: 'K_9', actionId: 'A_0', behavior: '4', outchar: 'ˆ' }, - { keyCode: '43', key: 'K_COMMA', actionId: 'A_0', behavior: '4', outchar: 'ˆ' }, - { keyCode: '0', key: 'K_A', actionId: 'A_1', behavior: '1', outchar: 'Â' }, - { keyCode: '0', key: 'K_A', actionId: 'A_1', behavior: '2', outchar: 'Â' }, - { keyCode: '14', key: 'K_E', actionId: 'A_10', behavior: '0', outchar: 'ê' }, - { keyCode: '34', key: 'K_I', actionId: 'A_11', behavior: '0', outchar: 'î' }, - { keyCode: '31', key: 'K_O', actionId: 'A_13', behavior: '0', outchar: 'ô' }, - { keyCode: '32', key: 'K_U', actionId: 'A_14', behavior: '0', outchar: 'û' }, - { keyCode: '14', key: 'K_E', actionId: 'A_2', behavior: '1', outchar: 'Ê' }, - { keyCode: '14', key: 'K_E', actionId: 'A_2', behavior: '2', outchar: 'Ê' }, - { keyCode: '34', key: 'K_I', actionId: 'A_3', behavior: '1', outchar: 'Î' }, - { keyCode: '34', key: 'K_I', actionId: 'A_3', behavior: '2', outchar: 'Î' }, - { keyCode: '31', key: 'K_O', actionId: 'A_5', behavior: '1', outchar: 'Ô' }, - { keyCode: '31', key: 'K_O', actionId: 'A_5', behavior: '2', outchar: 'Ô' }, - { keyCode: '32', key: 'K_U', actionId: 'A_6', behavior: '1', outchar: 'Û' }, - { keyCode: '32', key: 'K_U', actionId: 'A_6', behavior: '2', outchar: 'Û' }, - { keyCode: '0', key: 'K_A', actionId: 'A_9', behavior: '0', outchar: 'â' } - ]; - - [[b6ActionIdArr, b1KeycodeArr], - ].forEach(function (values) { - it(("getKeyActionOutputArrayFromActionStateOutputArray([['" + JSON.stringify(values[0]) + "'],..])").padEnd(73, " ") + '1 should return an array of objects', async function () { - const result = sut.getKeyActionOutputArrayFromActionStateOutputArray(read, values[0] as ActionStateOutput[]); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + describe('Xkb-kmn: getActionOutputbehaviorKeyModiFromActionIDStateOutput ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sutR = new XkbFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/tests-xkb-kmn/Test.keylayout'); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + const converted = sut.convertBound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); + [ + ['A_1', 'A', true, + [{ "outchar": "A", "actionId": "A_1", "behavior": "1", "key": "K_A", "modifier": "CAPS" }, + { "outchar": "A", "actionId": "A_1", "behavior": "2", "key": "K_A", "modifier": "NCAPS SHIFT" }, + { "outchar": "A", "actionId": "A_1", "behavior": "2", "key": "K_A", "modifier": "SHIFT CAPS" }] + ], + ['A_1', 'A', false, + [{ "outchar": "A", "actionId": "A_1", "behavior": "1", "key": "K_A", "modifier": "CAPS" }, + { "outchar": "A", "actionId": "A_1", "behavior": "2", "key": "K_A", "modifier": "SHIFT" }, + { "outchar": "A", "actionId": "A_1", "behavior": "2", "key": "K_A", "modifier": "SHIFT CAPS" }] + ], + ['A_9', 'a', true, [{ "outchar": "a", "actionId": "A_9", "behavior": "0", "key": "K_A", "modifier": "NCAPS" }]], + ['A_9', 'a', false, [{ "outchar": "a", "actionId": "A_9", "behavior": "0", "key": "K_A", "modifier": "" }]], + ['A_9', 'a', , [{ "outchar": "a", "actionId": "A_9", "behavior": "0", "key": "K_A", "modifier": "" }]], + ['A_9', '', true, [{ "outchar": "", "actionId": "A_9", "behavior": "0", "key": "K_A", "modifier": "NCAPS" }]], + ['A_9', '', false, [{ "outchar": "", "actionId": "A_9", "behavior": "0", "key": "K_A", "modifier": "" }]], + ['', 'a', true, []], + ['', 'a', false, []], + ['', '', , []], + ].forEach(function (values) { + it((JSON.stringify(values[3]).length > 35) ? + ("getActionOutputbehaviorKeyModiFromActionIDStateOutput('" + values[0] + "', '" + values[1] + "', " + values[2] + ")").padEnd(67, " ") + ' should return an array of objects' : + ("getActionOutputbehaviorKeyModiFromActionIDStateOutput('" + values[0] + "', '" + values[1] + "', " + values[2] + ")").padEnd(67, " ") + ' should return ' + "'" + JSON.stringify(values[3]) + "'", async function () { + const result = sut.getActionOutputBehaviorKeyModiFromActionIDStateOutput(read, converted.modifiers, String(values[0]), String(values[1]), Boolean(values[2])); + assert.equal(JSON.stringify(result), JSON.stringify(values[3])); + }); }); }); - const oneEntryResult = [ - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '0', outchar: 'ˆ' }, - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '1', outchar: 'ˆ' }, - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '2', outchar: 'ˆ' }, - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '3', outchar: 'ˆ' }, - { keyCode: '6', key: 'K_Z', actionId: 'A_0', behavior: '4', outchar: 'ˆ' }, - { keyCode: '25', key: 'K_9', actionId: 'A_0', behavior: '4', outchar: 'ˆ' }, - { keyCode: '43', key: 'K_COMMA', actionId: 'A_0', behavior: '4', outchar: 'ˆ' } - ]; - - const oneEntryResultNoOutput = [ - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '0', outchar: '' }, - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '1', outchar: '' }, - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '2', outchar: '' }, - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '3', outchar: '' }, - { keyCode: '6', key: 'K_Z', actionId: 'A_0', behavior: '4', outchar: '' }, - { keyCode: '25', key: 'K_9', actionId: 'A_0', behavior: '4', outchar: '' }, - { keyCode: '43', key: 'K_COMMA', actionId: 'A_0', behavior: '4', outchar: '' }, - ]; - - [[[{ "id": "A_0", "state": "1", "output": "ˆ" }], oneEntryResult], - [[{ "id": "A_0", "state": "1", "output": "" }], oneEntryResultNoOutput], - [[{ "id": "A_0", "state": "", "output": "ˆ" }], oneEntryResult], - ].forEach(function (values) { - it(("getKeyActionOutputArrayFromActionStateOutputArray(['" + JSON.stringify(values[0]) + "'])").padEnd(73, " ") + ' should return an array of objects', async function () { - const result = sut.getKeyActionOutputArrayFromActionStateOutputArray(read, values[0] as ActionStateOutput[]); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + describe('Xkb-kmn: getKeyActionOutputArrayFromActionStateOutputArray ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sutR = new XkbFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/tests-xkb-kmn/Test.keylayout'); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + + const b6ActionIdArr: ActionStateOutput[] = [ + { "id": "A_0", "state": "1", "output": "ˆ" }, + { "id": "A_1", "state": "1", "output": "Â" }, + { "id": "A_10", "state": "1", "output": "ê" }, + { "id": "A_11", "state": "1", "output": "î" }, + { "id": "A_13", "state": "1", "output": "ô" }, + { "id": "A_14", "state": "1", "output": "û" }, + { "id": "A_2", "state": "1", "output": "Ê" }, + { "id": "A_3", "state": "1", "output": "Î" }, + { "id": "A_5", "state": "1", "output": "Ô" }, + { "id": "A_6", "state": "1", "output": "Û" }, + { "id": "A_9", "state": "1", "output": "â" } + ]; + + const b1KeycodeArr: KeylayoutFileData[] = [ + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '0', outchar: 'ˆ' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '1', outchar: 'ˆ' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '2', outchar: 'ˆ' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '3', outchar: 'ˆ' }, + { keyCode: '6', key: 'K_Z', actionId: 'A_0', behavior: '4', outchar: 'ˆ' }, + { keyCode: '25', key: 'K_9', actionId: 'A_0', behavior: '4', outchar: 'ˆ' }, + { keyCode: '43', key: 'K_COMMA', actionId: 'A_0', behavior: '4', outchar: 'ˆ' }, + { keyCode: '0', key: 'K_A', actionId: 'A_1', behavior: '1', outchar: 'Â' }, + { keyCode: '0', key: 'K_A', actionId: 'A_1', behavior: '2', outchar: 'Â' }, + { keyCode: '14', key: 'K_E', actionId: 'A_10', behavior: '0', outchar: 'ê' }, + { keyCode: '34', key: 'K_I', actionId: 'A_11', behavior: '0', outchar: 'î' }, + { keyCode: '31', key: 'K_O', actionId: 'A_13', behavior: '0', outchar: 'ô' }, + { keyCode: '32', key: 'K_U', actionId: 'A_14', behavior: '0', outchar: 'û' }, + { keyCode: '14', key: 'K_E', actionId: 'A_2', behavior: '1', outchar: 'Ê' }, + { keyCode: '14', key: 'K_E', actionId: 'A_2', behavior: '2', outchar: 'Ê' }, + { keyCode: '34', key: 'K_I', actionId: 'A_3', behavior: '1', outchar: 'Î' }, + { keyCode: '34', key: 'K_I', actionId: 'A_3', behavior: '2', outchar: 'Î' }, + { keyCode: '31', key: 'K_O', actionId: 'A_5', behavior: '1', outchar: 'Ô' }, + { keyCode: '31', key: 'K_O', actionId: 'A_5', behavior: '2', outchar: 'Ô' }, + { keyCode: '32', key: 'K_U', actionId: 'A_6', behavior: '1', outchar: 'Û' }, + { keyCode: '32', key: 'K_U', actionId: 'A_6', behavior: '2', outchar: 'Û' }, + { keyCode: '0', key: 'K_A', actionId: 'A_9', behavior: '0', outchar: 'â' } + ]; + + [[b6ActionIdArr, b1KeycodeArr], + ].forEach(function (values) { + it(("getKeyActionOutputArrayFromActionStateOutputArray([['" + JSON.stringify(values[0]) + "'],..])").padEnd(73, " ") + '1 should return an array of objects', async function () { + const result = sut.getKeyActionOutputArrayFromActionStateOutputArray(read, values[0] as ActionStateOutput[]); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); }); - }); - [[[{ "id": "", "state": "1", "output": "ˆ" }], []], - [[{ "id": "", "state": "", "output": "" }], []], - [[{ "id": " ", "state": " ", "output": "" }], []], + const oneEntryResult = [ + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '0', outchar: 'ˆ' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '1', outchar: 'ˆ' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '2', outchar: 'ˆ' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '3', outchar: 'ˆ' }, + { keyCode: '6', key: 'K_Z', actionId: 'A_0', behavior: '4', outchar: 'ˆ' }, + { keyCode: '25', key: 'K_9', actionId: 'A_0', behavior: '4', outchar: 'ˆ' }, + { keyCode: '43', key: 'K_COMMA', actionId: 'A_0', behavior: '4', outchar: 'ˆ' } + ]; + + const oneEntryResultNoOutput = [ + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '0', outchar: '' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '1', outchar: '' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '2', outchar: '' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '3', outchar: '' }, + { keyCode: '6', key: 'K_Z', actionId: 'A_0', behavior: '4', outchar: '' }, + { keyCode: '25', key: 'K_9', actionId: 'A_0', behavior: '4', outchar: '' }, + { keyCode: '43', key: 'K_COMMA', actionId: 'A_0', behavior: '4', outchar: '' }, + ]; + + [[[{ "id": "A_0", "state": "1", "output": "ˆ" }], oneEntryResult], + [[{ "id": "A_0", "state": "1", "output": "" }], oneEntryResultNoOutput], + [[{ "id": "A_0", "state": "", "output": "ˆ" }], oneEntryResult], + ].forEach(function (values) { + it(("getKeyActionOutputArrayFromActionStateOutputArray(['" + JSON.stringify(values[0]) + "'])").padEnd(73, " ") + ' should return an array of objects', async function () { + const result = sut.getKeyActionOutputArrayFromActionStateOutputArray(read, values[0] as ActionStateOutput[]); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); - ].forEach(function (values) { - it(("getKeyActionOutputArrayFromActionStateOutputArray(" + JSON.stringify(values[0]) + ")").padEnd(73, " ") + ' should return ' + "'[" + JSON.stringify(values[1]) + "]'", async function () { - const result = sut.getKeyActionOutputArrayFromActionStateOutputArray(read, values[0] as ActionStateOutput[]); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + [[[{ "id": "", "state": "1", "output": "ˆ" }], []], + [[{ "id": "", "state": "", "output": "" }], []], + [[{ "id": " ", "state": " ", "output": "" }], []], + + ].forEach(function (values) { + it(("getKeyActionOutputArrayFromActionStateOutputArray(" + JSON.stringify(values[0]) + ")").padEnd(73, " ") + ' should return ' + "'[" + JSON.stringify(values[1]) + "]'", async function () { + const result = sut.getKeyActionOutputArrayFromActionStateOutputArray(read, values[0] as ActionStateOutput[]); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); }); - }); - [[, []], - [undefined, []], - [null, []], - ].forEach(function (values) { - it(("getKeyActionOutputArrayFromActionStateOutputArray(" + JSON.stringify(values[0]) + ")").padEnd(73, " ") + ' should return ' + "'[" + JSON.stringify(values[1]) + "]'", async function () { - const result = sut.getKeyActionOutputArrayFromActionStateOutputArray(read, values[0] as ActionStateOutput[]); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + [[, []], + [undefined, []], + [null, []], + ].forEach(function (values) { + it(("getKeyActionOutputArrayFromActionStateOutputArray(" + JSON.stringify(values[0]) + ")").padEnd(73, " ") + ' should return ' + "'[" + JSON.stringify(values[1]) + "]'", async function () { + const result = sut.getKeyActionOutputArrayFromActionStateOutputArray(read, values[0] as ActionStateOutput[]); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); }); }); - }); - - describe('Xkb-kmn: createRuleData ', function () { - const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const sutR = new XkbFileReader(compilerTestCallbacks); - [ - [ - ['../data/tests-xkb-kmn/Test_C0.keylayout'], - [new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_A', new TextEncoder().encode('a')), - new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_A', new TextEncoder().encode('A')), - new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_S', new TextEncoder().encode('s')), - new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_D', new TextEncoder().encode('d'))] - ], - [ - ['../data/tests-xkb-kmn/Test_C1.keylayout'], - [new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_S', new TextEncoder().encode('s')), - new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_S', new TextEncoder().encode('S'))] - ], - [ - ['../data/tests-xkb-kmn/Test_C2.keylayout'], - [new Rule("C2", '', '', 0, 0, 'NCAPS', 'K_U', 1, 1, 'CAPS', 'K_A', new TextEncoder().encode('Â'))], - ], - [ - ['../data/tests-xkb-kmn/Test_C3.keylayout'], - [new Rule("C3", 'NCAPS SHIFT', 'K_D', 2, 1, 'NCAPS', 'K_U', 1, 2, 'CAPS', 'K_A', new TextEncoder().encode('Â'))] - ], + describe('Xkb-kmn: createRuleData ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sutR = new XkbFileReader(compilerTestCallbacks); [ - ['../data/tests-xkb-kmn/Test_C3_several.keylayout'], - [new Rule("C3", 'NCAPS RALT', 'K_8', 3, 1, 'CAPS', 'K_U', 1, 3, 'NCAPS', 'K_A', new TextEncoder().encode('â')), - new Rule("C3", 'NCAPS RALT', 'K_8', 3, 0, 'CAPS', 'K_U', 1, 0, 'NCAPS RALT', 'K_A', new TextEncoder().encode('â')), - new Rule("C3", 'NCAPS RALT', 'K_8', 3, 0, 'NCAPS RALT', 'K_U', 2, 2, 'NCAPS', 'K_A', new TextEncoder().encode('â')), - new Rule("C3", 'NCAPS RALT', 'K_8', 3, 0, 'NCAPS RALT', 'K_U', 2, 0, 'NCAPS RALT', 'K_A', new TextEncoder().encode('â'))] - ], - [ - ['../data/tests-xkb-kmn/Test_C0_C1_C2_C3.keylayout'], - [new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_A', new TextEncoder().encode('A')), - new Rule("C2", '', '', 0, 0, 'NCAPS RALT', 'K_EQUAL', 1, 1, 'CAPS', 'K_D', new TextEncoder().encode('Â')), - new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_S', new TextEncoder().encode('S')), - new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'NCAPS RALT', 'K_U', new TextEncoder().encode('S')), - new Rule("C3", 'NCAPS RALT', 'K_8', 6, 1, 'CAPS', 'K_S', 2, 6, 'CAPS', 'K_D', new TextEncoder().encode('Â')), - new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'CAPS', 'K_U', 3, 3, 'CAPS', 'K_D', new TextEncoder().encode('Â')), - new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'NCAPS RALT', 'K_S', 4, 4, 'CAPS', 'K_D', new TextEncoder().encode('Â')), - new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'NCAPS RALT', 'K_U', 5, 5, 'CAPS', 'K_D', new TextEncoder().encode('Â')), - new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_S', new TextEncoder().encode('S')), - new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'NCAPS RALT', 'K_U', new TextEncoder().encode('S')), - new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'CAPS', 'K_S', 2, 0, 'CAPS', 'K_D', new TextEncoder().encode('Â')), - new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'CAPS', 'K_U', 3, 0, 'CAPS', 'K_D', new TextEncoder().encode('Â')), - new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'NCAPS RALT', 'K_S', 4, 0, 'CAPS', 'K_D', new TextEncoder().encode('Â')), - new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'NCAPS RALT', 'K_U', 5, 0, 'CAPS', 'K_D', new TextEncoder().encode('Â')), - new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_U', new TextEncoder().encode('U')),] - ], - ].forEach(function (values: any) { - it('data of \'' + values[0] + "' passed into createRuleData() " + 'should create an array of rules', async function () { - const inputFilename = makePathToFixture(values[0][0]); - const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); - const processedData = sut.convertBound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); - assert.deepEqual(processedData.rules[0], values[1][0]); + [ + ['../data/tests-xkb-kmn/Test_C0.keylayout'], + [new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_A', new TextEncoder().encode('a')), + new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_A', new TextEncoder().encode('A')), + new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_S', new TextEncoder().encode('s')), + new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_D', new TextEncoder().encode('d'))] + ], + [ + ['../data/tests-xkb-kmn/Test_C1.keylayout'], + [new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_S', new TextEncoder().encode('s')), + new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_S', new TextEncoder().encode('S'))] + ], + [ + ['../data/tests-xkb-kmn/Test_C2.keylayout'], + [new Rule("C2", '', '', 0, 0, 'NCAPS', 'K_U', 1, 1, 'CAPS', 'K_A', new TextEncoder().encode('Â'))], + ], + [ + ['../data/tests-xkb-kmn/Test_C3.keylayout'], + [new Rule("C3", 'NCAPS SHIFT', 'K_D', 2, 1, 'NCAPS', 'K_U', 1, 2, 'CAPS', 'K_A', new TextEncoder().encode('Â'))] + ], + + [ + ['../data/tests-xkb-kmn/Test_C3_several.keylayout'], + [new Rule("C3", 'NCAPS RALT', 'K_8', 3, 1, 'CAPS', 'K_U', 1, 3, 'NCAPS', 'K_A', new TextEncoder().encode('â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 3, 0, 'CAPS', 'K_U', 1, 0, 'NCAPS RALT', 'K_A', new TextEncoder().encode('â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 3, 0, 'NCAPS RALT', 'K_U', 2, 2, 'NCAPS', 'K_A', new TextEncoder().encode('â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 3, 0, 'NCAPS RALT', 'K_U', 2, 0, 'NCAPS RALT', 'K_A', new TextEncoder().encode('â'))] + ], + [ + ['../data/tests-xkb-kmn/Test_C0_C1_C2_C3.keylayout'], + [new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_A', new TextEncoder().encode('A')), + new Rule("C2", '', '', 0, 0, 'NCAPS RALT', 'K_EQUAL', 1, 1, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_S', new TextEncoder().encode('S')), + new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'NCAPS RALT', 'K_U', new TextEncoder().encode('S')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 1, 'CAPS', 'K_S', 2, 6, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'CAPS', 'K_U', 3, 3, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'NCAPS RALT', 'K_S', 4, 4, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'NCAPS RALT', 'K_U', 5, 5, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_S', new TextEncoder().encode('S')), + new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'NCAPS RALT', 'K_U', new TextEncoder().encode('S')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'CAPS', 'K_S', 2, 0, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'CAPS', 'K_U', 3, 0, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'NCAPS RALT', 'K_S', 4, 0, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'NCAPS RALT', 'K_U', 5, 0, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_U', new TextEncoder().encode('U')),] + ], + ].forEach(function (values: any) { + it('data of \'' + values[0] + "' passed into createRuleData() " + 'should create an array of rules', async function () { + const inputFilename = makePathToFixture(values[0][0]); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + const processedData = sut.convertBound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); + assert.deepEqual(processedData.rules[0], values[1][0]); + }); }); }); - }); -*/ + */ }); diff --git a/developer/src/kmc-convert/test/kmc-convert-read/xkb-file-reader.tests.ts b/developer/src/kmc-convert/test/kmc-convert-read/xkb-file-reader.tests.ts index e09a85f797a..20e8dc571dd 100644 --- a/developer/src/kmc-convert/test/kmc-convert-read/xkb-file-reader.tests.ts +++ b/developer/src/kmc-convert/test/kmc-convert-read/xkb-file-reader.tests.ts @@ -22,7 +22,7 @@ describe('XkbFileReader', function () { const sutR = new XkbFileReader(compilerTestCallbacks); it('read() should return filled array on correct input', async function () { - const inputFilename = makePathToFixture('../data/tests-xkb-kmn/de_simple'); + const inputFilename = makePathToFixture('../data/tests-xkb-kmn/de-simple'); const result = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); assert.isNotEmpty(result); }); From b0b6728d6738fbdccadb9d38f1d240d4b0728fa0 Mon Sep 17 00:00:00 2001 From: Sabine Date: Thu, 14 May 2026 16:21:10 +0200 Subject: [PATCH 249/251] feat(developer): tidy up --- .../xkb-to-kmn-converter.ts | 178 ++++-------------- 1 file changed, 34 insertions(+), 144 deletions(-) diff --git a/developer/src/kmc-convert/src/kmc-convert-convert/xkb-to-kmn-converter.ts b/developer/src/kmc-convert/src/kmc-convert-convert/xkb-to-kmn-converter.ts index d4f9576bd86..bf33a8f0f4a 100644 --- a/developer/src/kmc-convert/src/kmc-convert-convert/xkb-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/kmc-convert-convert/xkb-to-kmn-converter.ts @@ -150,7 +150,6 @@ export class XkbToKmnConverter { async run(inputFilename_withVariant: string, outputFilename?: string): Promise { const variant_name = inputFilename_withVariant.substring(inputFilename_withVariant.indexOf('(') + 1, inputFilename_withVariant.indexOf(')')); - console.log('variant_name of run', variant_name); let inputFilename = inputFilename_withVariant; if (variant_name) @@ -203,36 +202,26 @@ export class XkbToKmnConverter { rules: [] }; - //const paragraph_name = "basic"; const start_brack = inputfilename.indexOf('('); const end_brack = inputfilename.indexOf(')'); const variant_name = inputfilename.substring(start_brack + 1, end_brack); const inputfilenameUntilBracket = inputfilename.substring(0, start_brack); - - - - - dataObject.keylayoutFilename = inputfilename; if (start_brack >= 0) { dataObject.keylayoutFilename = inputfilenameUntilBracket; } // fill dataObject with filenames, behaviors and (initialized) rules - // dataObject.keylayoutFilename = inputfilename; if (!outputFilename) { if (variant_name) dataObject.kmnFilename = dataObject.keylayoutFilename + "_" + variant_name + '.kmn'; else dataObject.kmnFilename = dataObject.keylayoutFilename + '.kmn'; - //dataObject.kmnFilename = inputfilename + '.kmn'; } else dataObject.kmnFilename = outputFilename; - - console.log('varidataObject.dataObject.keylayoutFilename\n', dataObject.keylayoutFilename, "\n", dataObject.kmnFilename); // fill rules into 'rules' of dataObject const out = this.createRuleData(dataObject, xkb_data); return out; @@ -253,8 +242,6 @@ export class XkbToKmnConverter { // Todo-kmc-convert: create paragraphname from inputfilename // ToDo-kmc-convert remove this-it`s neccessary as we could not process the include (include "de(basic)") const xkbData = xkbData_in.replace(/include \"/g, '\/\/include \"'); - //const paragraph_name = "deadtilde"; - //const paragraph_name = "basic"; const start_vari = dataObject.kmnFilename.lastIndexOf('_'); const end_vari = dataObject.kmnFilename.indexOf('.'); let variant_name = ''; @@ -262,30 +249,18 @@ export class XkbToKmnConverter { variant_name = dataObject.kmnFilename.substring(start_vari + 1, end_vari); - //dataObject.kmnFilename = dataObject.keylayoutFilename.substring(0, start_brack) + "_" + variant_name; - let paragraph_name = ''; // Todo find default keyword (default xkb_symbols "basic") and use this if (variant_name) paragraph_name = variant_name; else { - /* const pos_start_def_keyword = xkbData_in.indexOf('default xkb_symbols \"'); - const keywordstring = xkbData_in.substring(pos_start_def_keyword); - const pos_quote = keywordstring.indexOf('\"'); - const shortstring = keywordstring.substring(pos_quote + 1); - const pos_end_def_keyword = shortstring.indexOf('\"'); - //paragraph_name = "basic"; - paragraph_name = shortstring.substring(0, pos_end_def_keyword);*/ - - //const word= "symbols" paragraph_name = xkbData_in.split(/default xkb_symbols\s*\"(.*?)\"\s\{/)[1]; - } - console.log('paragraph_name', paragraph_name); + // remove all comments, remove whitespace, split into block for each xkb_symbol definition const noComments = xkbData.replace(/\/\*[\s\S]*?\*\/|(?<=[^:])\/\/.*|^\/\/.*/g, ''); - const xkbData_noWhitespace = noComments.replaceAll(/[\s,]+/g, ',').slice(0, -1); - const xkb_symbols_blocks = xkbData_noWhitespace.split("xkb_symbols"); + const noCommentsNoWhitespace = noComments.replaceAll(/[\s,]+/g, ',').slice(0, -1); + const xkb_symbols_blocks = noCommentsNoWhitespace.split("xkb_symbols"); // find paragraphname in xkb_symbols, clean data and return appropriate paragraph for (let i = 0; i < xkb_symbols_blocks.length; i++) { @@ -301,35 +276,6 @@ export class XkbToKmnConverter { return ''; } - /** - * @brief ToDo check description - * @brief* @brief ToDo check description - * @brief member function to extract all lines starting with with '' from input data - * @param xkbData: an string containing the contents of the xkb file - * @return an array of lines containing key - output pairs. - */ - public createCompleteLines(xkbData: string, dataObject: ProcessedData): string[] { - - // in the Configuration file we find the appopriate paragraph between "xkb_symbol " and the next xkb_symbol - // then push all rows starting with "key" to a 1D-Vector - const paragraph = this.findParagraph(xkbData, dataObject); - if (!paragraph) - console.log('ToDo-kmc-convert add Err-msg findParagraph'); - - const lineArray = []; - - // each rule and type in a seperate line - // Todo_kmc-convert needed? - const lines = paragraph.split('key'); - - for (let i = 0; i < lines.length; i++) { - if (lines[i]) { - lineArray.push(lines[i].replaceAll(/[\s;]]+/g, ',').slice(1, -1)); - } - } - return lineArray; - } - public getModifier(typename: string): string[] | null { // ToDo-kmc-convert read levels from file @@ -352,41 +298,37 @@ export class XkbToKmnConverter { } return null; } - public getOutputcher(line: string): string { - // kmc-konvert-better solution - - - - const pos_type = line.indexOf('type'); - if (pos_type >= 0) { - - const pos_type2 = line.indexOf('symbols'); - if (pos_type2 >= 0) { - const shorterline = line.substring(pos_type2); - const pos_equal2 = shorterline.indexOf('"'); - const out = shorterline.substring(pos_equal2); - return out; - - -/* - - const myTip = line.split(/type.*\s*=(.*?)\[/); - if (myTip[2] !== out) - console.log('paragraph_name1 NOT EQUAL ###################################', out, myTip); - else console.log('paragraph_name1 is EQUAL ................#', out, myTip); - return myTip[2];*/ + public get_Keyname(line: string): string { + if (line.indexOf('= 0) { + return line.split((/(\)/)).filter(Boolean)[0]; + } + return ''; + } + public getOutput(line: string): string { + let out: string = ''; + // e.g. if key {type[Group1]="FOUR_LEVEL_PLUS_LOCK", symbols[Group1]=[ssharp, question, backslash, questiondown, 0x1001E9E ]}; + if (line.indexOf('symbols') >= 0) { + out = line.split(/symbols.*(.*?)=,/).filter(Boolean)[1]; + } + // e.g. if key.type[Group1] = "ONE_LEVEL"; + else if (line.indexOf('key.type') >= 0) { + out = ''; + } + // nornal + else if (line.indexOf('= 0) { + const out1arr = line.split(/,/); + out = out1arr[1]; + } + return out; + } - } - } - return line; - } public getKeytype(data_key: string, default_type: string): string { @@ -402,7 +344,6 @@ export class XkbToKmnConverter { return default_type; } - public filldata_paragraph(xkbData: string, dataObject: ProcessedData, data_paragraph_arr: Data_xkb[]): Data_xkb[] { // in the Configuration file we find the appopriate paragraph between "xkb_symbol " and the next xkb_symbol @@ -426,71 +367,25 @@ export class XkbToKmnConverter { for (let i = 0; i < lineArray.length; i++) { - // get Data for key_type OK - const outputChar = []; + // get Data for key_type e.g. "FOUR_LEVEL" const key_type = this.getKeytype(lineArray[i], default_key_type); default_key_type = key_type; - // get Data for modifier OK + // get Data modifier Data of keytype e.g. ["","shift","Caps"] const modi_Data = this.getModifier(key_type); - // get Data for keyname - // Todo-kmc-convert move to function - let keyname = ''; - const pos_key_start = lineArray[i].indexOf('= 0) { - const keyname1 = lineArray[i].substring(pos_key_start); - const pos_key_end = keyname1.indexOf('>'); - keyname = keyname1.substring(pos_key_start, pos_key_end + 1); - } - - // get Data for outputmove to functionbetter solution - let out: string = ''; - const pos_type = lineArray[i].indexOf('type'); - if (pos_type >= 0) { - - // use of key {type[Group1]=" - /* const pos_symbols = lineArray[i].indexOf('symbols'); - if (pos_symbols >= 0) { - const shortstring = lineArray[i].substring(pos_symbols); - const pos_first_equal = shortstring.indexOf('='); - out = shortstring.substring(pos_first_equal + 2); - }*/ - const pos_symbols = lineArray[i].indexOf('symbols'); - if (pos_symbols >= 0) { - out = lineArray[i].split(/symbols.*(.*?)=,/)[2]; - } - else { - // use of key.type - const pos_first_equal = lineArray[i].indexOf('='); - out = lineArray[i].substring(pos_first_equal + 2); - } - } - else { - // normal - if (lineArray[i].indexOf('= 0) { - const completestring = lineArray[i]; - const onlyOut = completestring.split('>,'); - out = onlyOut[1]; - } - } - const elements = out.split(','); - - // get Data for outputChar - for (let j = 0; j < elements.length; j++) { - const outputcharOK = this.getOutputcher(elements[j]); - outputChar.push(outputcharOK); - } - - + // get name of key e.g. '' + const keyname = this.get_Keyname(lineArray[i]); + // get output e.g. '1,exclam,onesuperior,exclamdown' + const out = this.getOutput(lineArray[i]); + const output_elements = out.split(','); const singleData_paragraph: Data_xkb = { xkb_keyname: keyname as string, xkb_keytype: default_key_type, xkb_modifiers: modi_Data as string[], - xkb_output: outputChar, + xkb_output: output_elements, }; if (keyname) { @@ -523,14 +418,9 @@ export class XkbToKmnConverter { const data_paragraph_arr: Data_xkb[] = []; - const lines = this.createCompleteLines(xkb_data, dataObject); // Todo-kmc-convert check data_paragraph_arr vs dataObject this.filldata_paragraph(xkb_data, dataObject, data_paragraph_arr); - // fill darta_data_paragraph - if (!lines) - console.log("ToDo-kmc-convert add ErrorMsg"); - // Todo-kmc-convert check nr(modi)= nr(output) //....................... create a Rule and save to ruleObj ....................... From 7a5c69d4381559dfdc41fbaf404af544595b64b2 Mon Sep 17 00:00:00 2001 From: Sabine Date: Thu, 14 May 2026 16:21:10 +0200 Subject: [PATCH 250/251] feat(developer): tidy up --- .../xkb-to-kmn-converter.ts | 179 +-- .../xkb-to-kmn-converter.tests.ts | 1041 +++++++++-------- 2 files changed, 609 insertions(+), 611 deletions(-) diff --git a/developer/src/kmc-convert/src/kmc-convert-convert/xkb-to-kmn-converter.ts b/developer/src/kmc-convert/src/kmc-convert-convert/xkb-to-kmn-converter.ts index d4f9576bd86..3b74af7868f 100644 --- a/developer/src/kmc-convert/src/kmc-convert-convert/xkb-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/kmc-convert-convert/xkb-to-kmn-converter.ts @@ -19,6 +19,7 @@ - remove comments - remove unused functions - add warning/errormessages + - add .filter(Boolean)[0]; to split() ========================================================= @@ -150,7 +151,6 @@ export class XkbToKmnConverter { async run(inputFilename_withVariant: string, outputFilename?: string): Promise { const variant_name = inputFilename_withVariant.substring(inputFilename_withVariant.indexOf('(') + 1, inputFilename_withVariant.indexOf(')')); - console.log('variant_name of run', variant_name); let inputFilename = inputFilename_withVariant; if (variant_name) @@ -203,36 +203,26 @@ export class XkbToKmnConverter { rules: [] }; - //const paragraph_name = "basic"; const start_brack = inputfilename.indexOf('('); const end_brack = inputfilename.indexOf(')'); const variant_name = inputfilename.substring(start_brack + 1, end_brack); const inputfilenameUntilBracket = inputfilename.substring(0, start_brack); - - - - - dataObject.keylayoutFilename = inputfilename; if (start_brack >= 0) { dataObject.keylayoutFilename = inputfilenameUntilBracket; } // fill dataObject with filenames, behaviors and (initialized) rules - // dataObject.keylayoutFilename = inputfilename; if (!outputFilename) { if (variant_name) dataObject.kmnFilename = dataObject.keylayoutFilename + "_" + variant_name + '.kmn'; else dataObject.kmnFilename = dataObject.keylayoutFilename + '.kmn'; - //dataObject.kmnFilename = inputfilename + '.kmn'; } else dataObject.kmnFilename = outputFilename; - - console.log('varidataObject.dataObject.keylayoutFilename\n', dataObject.keylayoutFilename, "\n", dataObject.kmnFilename); // fill rules into 'rules' of dataObject const out = this.createRuleData(dataObject, xkb_data); return out; @@ -253,8 +243,6 @@ export class XkbToKmnConverter { // Todo-kmc-convert: create paragraphname from inputfilename // ToDo-kmc-convert remove this-it`s neccessary as we could not process the include (include "de(basic)") const xkbData = xkbData_in.replace(/include \"/g, '\/\/include \"'); - //const paragraph_name = "deadtilde"; - //const paragraph_name = "basic"; const start_vari = dataObject.kmnFilename.lastIndexOf('_'); const end_vari = dataObject.kmnFilename.indexOf('.'); let variant_name = ''; @@ -262,30 +250,18 @@ export class XkbToKmnConverter { variant_name = dataObject.kmnFilename.substring(start_vari + 1, end_vari); - //dataObject.kmnFilename = dataObject.keylayoutFilename.substring(0, start_brack) + "_" + variant_name; - let paragraph_name = ''; // Todo find default keyword (default xkb_symbols "basic") and use this if (variant_name) paragraph_name = variant_name; else { - /* const pos_start_def_keyword = xkbData_in.indexOf('default xkb_symbols \"'); - const keywordstring = xkbData_in.substring(pos_start_def_keyword); - const pos_quote = keywordstring.indexOf('\"'); - const shortstring = keywordstring.substring(pos_quote + 1); - const pos_end_def_keyword = shortstring.indexOf('\"'); - //paragraph_name = "basic"; - paragraph_name = shortstring.substring(0, pos_end_def_keyword);*/ - - //const word= "symbols" paragraph_name = xkbData_in.split(/default xkb_symbols\s*\"(.*?)\"\s\{/)[1]; - } - console.log('paragraph_name', paragraph_name); + // remove all comments, remove whitespace, split into block for each xkb_symbol definition const noComments = xkbData.replace(/\/\*[\s\S]*?\*\/|(?<=[^:])\/\/.*|^\/\/.*/g, ''); - const xkbData_noWhitespace = noComments.replaceAll(/[\s,]+/g, ',').slice(0, -1); - const xkb_symbols_blocks = xkbData_noWhitespace.split("xkb_symbols"); + const noCommentsNoWhitespace = noComments.replaceAll(/[\s,]+/g, ',').slice(0, -1); + const xkb_symbols_blocks = noCommentsNoWhitespace.split("xkb_symbols"); // find paragraphname in xkb_symbols, clean data and return appropriate paragraph for (let i = 0; i < xkb_symbols_blocks.length; i++) { @@ -301,35 +277,6 @@ export class XkbToKmnConverter { return ''; } - /** - * @brief ToDo check description - * @brief* @brief ToDo check description - * @brief member function to extract all lines starting with with '' from input data - * @param xkbData: an string containing the contents of the xkb file - * @return an array of lines containing key - output pairs. - */ - public createCompleteLines(xkbData: string, dataObject: ProcessedData): string[] { - - // in the Configuration file we find the appopriate paragraph between "xkb_symbol " and the next xkb_symbol - // then push all rows starting with "key" to a 1D-Vector - const paragraph = this.findParagraph(xkbData, dataObject); - if (!paragraph) - console.log('ToDo-kmc-convert add Err-msg findParagraph'); - - const lineArray = []; - - // each rule and type in a seperate line - // Todo_kmc-convert needed? - const lines = paragraph.split('key'); - - for (let i = 0; i < lines.length; i++) { - if (lines[i]) { - lineArray.push(lines[i].replaceAll(/[\s;]]+/g, ',').slice(1, -1)); - } - } - return lineArray; - } - public getModifier(typename: string): string[] | null { // ToDo-kmc-convert read levels from file @@ -352,41 +299,37 @@ export class XkbToKmnConverter { } return null; } - public getOutputcher(line: string): string { - // kmc-konvert-better solution - - - - const pos_type = line.indexOf('type'); - if (pos_type >= 0) { - - const pos_type2 = line.indexOf('symbols'); - if (pos_type2 >= 0) { - const shorterline = line.substring(pos_type2); - const pos_equal2 = shorterline.indexOf('"'); - const out = shorterline.substring(pos_equal2); - return out; - - -/* - - const myTip = line.split(/type.*\s*=(.*?)\[/); - if (myTip[2] !== out) - console.log('paragraph_name1 NOT EQUAL ###################################', out, myTip); - else console.log('paragraph_name1 is EQUAL ................#', out, myTip); - return myTip[2];*/ + public get_Keyname(line: string): string { + if (line.indexOf('= 0) { + return line.split((/(\)/)).filter(Boolean)[0]; + } + return ''; + } + public getOutput(line: string): string { + let out: string = ''; + // e.g. if key {type[Group1]="FOUR_LEVEL_PLUS_LOCK", symbols[Group1]=[ssharp, question, backslash, questiondown, 0x1001E9E ]}; + if (line.indexOf('symbols') >= 0) { + out = line.split(/symbols.*(.*?)=,/).filter(Boolean)[1]; + } + // e.g. if key.type[Group1] = "ONE_LEVEL"; + else if (line.indexOf('key.type') >= 0) { + out = ''; + } + // nornal + else if (line.indexOf('= 0) { + const out1arr = line.split(/,/); + out = out1arr[1]; + } + return out; + } - } - } - return line; - } public getKeytype(data_key: string, default_type: string): string { @@ -402,7 +345,6 @@ export class XkbToKmnConverter { return default_type; } - public filldata_paragraph(xkbData: string, dataObject: ProcessedData, data_paragraph_arr: Data_xkb[]): Data_xkb[] { // in the Configuration file we find the appopriate paragraph between "xkb_symbol " and the next xkb_symbol @@ -426,71 +368,25 @@ export class XkbToKmnConverter { for (let i = 0; i < lineArray.length; i++) { - // get Data for key_type OK - const outputChar = []; + // get Data for key_type e.g. "FOUR_LEVEL" const key_type = this.getKeytype(lineArray[i], default_key_type); default_key_type = key_type; - // get Data for modifier OK + // get Data modifier Data of keytype e.g. ["","shift","Caps"] const modi_Data = this.getModifier(key_type); - // get Data for keyname - // Todo-kmc-convert move to function - let keyname = ''; - const pos_key_start = lineArray[i].indexOf('= 0) { - const keyname1 = lineArray[i].substring(pos_key_start); - const pos_key_end = keyname1.indexOf('>'); - keyname = keyname1.substring(pos_key_start, pos_key_end + 1); - } - - // get Data for outputmove to functionbetter solution - let out: string = ''; - const pos_type = lineArray[i].indexOf('type'); - if (pos_type >= 0) { - - // use of key {type[Group1]=" - /* const pos_symbols = lineArray[i].indexOf('symbols'); - if (pos_symbols >= 0) { - const shortstring = lineArray[i].substring(pos_symbols); - const pos_first_equal = shortstring.indexOf('='); - out = shortstring.substring(pos_first_equal + 2); - }*/ - const pos_symbols = lineArray[i].indexOf('symbols'); - if (pos_symbols >= 0) { - out = lineArray[i].split(/symbols.*(.*?)=,/)[2]; - } - else { - // use of key.type - const pos_first_equal = lineArray[i].indexOf('='); - out = lineArray[i].substring(pos_first_equal + 2); - } - } - else { - // normal - if (lineArray[i].indexOf('= 0) { - const completestring = lineArray[i]; - const onlyOut = completestring.split('>,'); - out = onlyOut[1]; - } - } - const elements = out.split(','); - - // get Data for outputChar - for (let j = 0; j < elements.length; j++) { - const outputcharOK = this.getOutputcher(elements[j]); - outputChar.push(outputcharOK); - } - - + // get name of key e.g. '' + const keyname = this.get_Keyname(lineArray[i]); + // get output e.g. '1,exclam,onesuperior,exclamdown' + const out = this.getOutput(lineArray[i]); + const output_elements = out.split(','); const singleData_paragraph: Data_xkb = { xkb_keyname: keyname as string, xkb_keytype: default_key_type, xkb_modifiers: modi_Data as string[], - xkb_output: outputChar, + xkb_output: output_elements, }; if (keyname) { @@ -523,14 +419,9 @@ export class XkbToKmnConverter { const data_paragraph_arr: Data_xkb[] = []; - const lines = this.createCompleteLines(xkb_data, dataObject); // Todo-kmc-convert check data_paragraph_arr vs dataObject this.filldata_paragraph(xkb_data, dataObject, data_paragraph_arr); - // fill darta_data_paragraph - if (!lines) - console.log("ToDo-kmc-convert add ErrorMsg"); - // Todo-kmc-convert check nr(modi)= nr(output) //....................... create a Rule and save to ruleObj ....................... diff --git a/developer/src/kmc-convert/test/kmc-convert-convert/xkb-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/kmc-convert-convert/xkb-to-kmn-converter.tests.ts index 69bdcb422d7..9cd10d17434 100644 --- a/developer/src/kmc-convert/test/kmc-convert-convert/xkb-to-kmn-converter.tests.ts +++ b/developer/src/kmc-convert/test/kmc-convert-convert/xkb-to-kmn-converter.tests.ts @@ -36,31 +36,135 @@ describe('XkbToKmnConverter', function () { }); /* - describe('findParagraph ', function () { + describe('Xkb-kmn: getModifier ', function () { const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); [ - ['', ''], + ['ONE_LEVEL', ['']], + ['FOUR_LEVEL_PLUS_LOCK', ["", "SHIFT", "RALT", "SHIFT RALT", "LOCK"]], + ['EIGHT_LEVEL', ["", "SHIFT", "ALT", "SHIFT ALT", "X", "X SHIFT", "X ALT", "X SHIFT ALT"]], + ['', null], + ['unknownLevel', null], + [99, null], + [null, null], + [undefined, null], + ].forEach(function (values) { - it(("findParagraph(" + values[0] + ")").padEnd(26, " ") + "should return " + "'" + values[1] + "'", async function () { - const result = sut.findParagraph(values[0] as string); - assert.equal(result, values[1]); + it(("getModifier(" + values[0] + ")").padEnd(40, " ") + "should return " + "'" + values[1] + "'", async function () { + const result = sut.getModifier(values[0] as string); + assert.deepStrictEqual((result), (values[1])); }); }); }); + describe('Xkb-kmn: get_Keyname ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + [ + [',r,R,paragraph,registered', ''], + [',type,Group1,="FOUR_LEVEL_PLUS_LOCK",symbols[Group1]=[ssharp,question,backslash,questiondown,B;', ''], + ['key { [ 2, quotedbl, twosuperior, oneeighth ] };', null], + ['unknown', null], + ['', null], + [null, null], + [undefined, null], + ].forEach(function (values) { + it(("get_Keyname(" + values[0] + ")").padEnd(40, " ") + " should return " + "'" + values[1] + "'", async function () { + const result = sut.get_Keyname(values[0] as string); + assert.deepStrictEqual((result), (values[1])); + }); + }); + }); - describe('createCompleteLines ', function () { + describe('Xkb-kmn: getOutput ', function () { const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); [ - ['', ''], + [',r,R,paragraph,registered', 'r,R,paragraph,registered'], + [',type,Group1,="FOUR_LEVEL_PLUS_LOCK",symbols,Group1,=,ssharp,question,backslash,questiondown,B', 'ssharp,question,backslash,questiondown,B'], + ['key { [ 2, quotedbl, twosuperior, oneeighth ] };', undefined], + ['unknown', null], + ['', null], + [null, null], + [undefined, null], ].forEach(function (values) { - it(("findPacreateCompleteLinesragraph(" + values[0] + ")").padEnd(26, " ") + "should return " + "'" + values[1] + "'", async function () { - const result = sut.createCompleteLines(values[0] as string); - assert.equal(result, values[1]); + it(("getOutput(" + values[0] + ")").padEnd(40, " ") + " should return " + "'" + values[1] + "'", async function () { + const result = sut.getOutput(values[0] as string); + assert.deepStrictEqual((result), (values[1])); + }); + }); + }); + + describe('Xkb-kmn: getKeytype ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + [ + [',r,R,paragraph,registered', 'DEFAULT_LEVEL'], + [',type,Group1,="FOUR_LEVEL_PLUS_LOCK",symbols[Group1]=[ssharp,question,backslash,questiondown,B;', 'FOUR_LEVEL_PLUS_LOCK'], + ['key { [ 2, quotedbl, twosuperior, oneeighth ] };', 'DEFAULT_LEVEL'], + ['unknown', 'DEFAULT_LEVEL'], + ['', 'DEFAULT_LEVEL'], + [null, null], + [undefined, null], + ].forEach(function (values) { + it(("getKeytype(" + values[0] + ")").padEnd(40, " ") + " should return " + "'" + values[1] + "'", async function () { + const result = sut.getKeytype(values[0] as string, 'DEFAULT_LEVEL'); + assert.deepStrictEqual((result), (values[1])); + }); + }); + }); + + describe('Xkb-kmn: get_KMVirtKC_from_keyname ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + [ + ['', 'K_R'], + ['', 'K_BKQUOTE'], + ['', ''], + ['', 'K_4'], + [null, null], + [undefined, null], + ].forEach(function (values) { + it(("get_KMVirtKC_from_keyname(" + values[0] + ")").padEnd(40, " ") + " should return " + "'" + values[1] + "'", async function () { + const result = sut.get_KMVirtKC_from_keyname(values[0] as string); + assert.deepStrictEqual((result), (values[1])); }); }); });*/ +//...................................................................................................... +//...................................................................................................... +//...................................................................................................... +//...................................................................................................... +//...................................................................................................... +//...................................................................................................... + +/* + describe('findParagraph ', function () { + // Todo + ['variant', 'all definition text'], + ['unexisting vriant', ''], + ['null, null], + ['', ''], + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + [ + ['', ''], + ].forEach(function (values) { + it(("findParagraph(" + values[0] + ")").padEnd(26, " ") + "should return " + "'" + values[1] + "'", async function () { + const result = sut.findParagraph(values[0] as string); + assert.equal(result, values[1]); + }); + }); + }); + + + describe('createCompleteLines ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + [ + ['', ''], + ].forEach(function (values) { + it(("findPacreateCompleteLinesragraph(" + values[0] + ")").padEnd(26, " ") + "should return " + "'" + values[1] + "'", async function () { + const result = sut.createCompleteLines(values[0] as string); + assert.equal(result, values[1]); + }); + }); + });*/ + describe('get_KMVirtKC_from_keyname ', function () { const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); @@ -433,496 +537,499 @@ describe('XkbToKmnConverter', function () { [[[' ', ' '], [' ']], false], ].forEach(function (values) { it(("checkIfCapsIsUsed(" + values[0] + ")").padEnd(40, " ") + "should return " + "'" + values[1] + "'", async function () { - const result = sut.checkIfCapsIsUsed(values[0] as string[][]); + / const result = sut.checkIfCapsIsUsed(values[0] as string[][]); assert.isTrue(result === values[1]); }); }); }); +*/ - describe('Xkb-kmn: getModifierArrayFromKeyModifierArray ', function () { - const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const sutR = new XkbFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/tests-xkb-kmn/Test.keylayout'); - const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); - const converted = sut.convertBound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); - [ - [[{ key: '0', behavior: 0 }], [['', 'shift? caps? ']]], - [[{ key: '0', behavior: 2 }], [['shift? leftShift caps? ', 'anyShift caps?', 'shift leftShift caps ', 'shift? rightShift caps? ']]], - [[{ key: '0', behavior: 999 }], [null]], - [[{ key: '999', behavior: null }], [null]], - [[{ key: '0', behavior: -999 }], [null]], - [[{ key: '0', behavior: null }], [null]], - [[], []], - - ].forEach(function (values) { - it((values[1] !== null) ? - ("getModifierArrayFromKeyModifierArray('" + JSON.stringify(values[0]) + "')").padEnd(68, " ") + " should return '" + JSON.stringify(values[1]) + "'" : - ("getModifierArrayFromKeyModifierArray('" + JSON.stringify(values[0]) + "')").padEnd(68, " ") + " should return '" + "null" + "'", async function () { - const result = sut.getModifierArrayFromKeyModifierArray(converted.modifiers, values[0] as unknown as KeylayoutFileData[]); - assert.deepStrictEqual(JSON.stringify(result), JSON.stringify(values[1])); - }); + /* + + describe('Xkb-kmn: getModifierArrayFromKeyModifierArray ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sutR = new XkbFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/tests-xkb-kmn/Test.keylayout'); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + const converted = sut.convertBound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); + [ + [[{ key: '0', behavior: 0 }], [['', 'shift? caps? ']]], + [[{ key: '0', behavior: 2 }], [['shift? leftShift caps? ', 'anyShift caps?', 'shift leftShift caps ', 'shift? rightShift caps? ']]], + [[{ key: '0', behavior: 999 }], [null]], + [[{ key: '999', behavior: null }], [null]], + [[{ key: '0', behavior: -999 }], [null]], + [[{ key: '0', behavior: null }], [null]], + [[], []], + + ].forEach(function (values) { + it((values[1] !== null) ? + ("getModifierArrayFromKeyModifierArray('" + JSON.stringify(values[0]) + "')").padEnd(68, " ") + " should return '" + JSON.stringify(values[1]) + "'" : + ("getModifierArrayFromKeyModifierArray('" + JSON.stringify(values[0]) + "')").padEnd(68, " ") + " should return '" + "null" + "'", async function () { + const result = sut.getModifierArrayFromKeyModifierArray(converted.modifiers, values[0] as unknown as KeylayoutFileData[]); + assert.deepStrictEqual(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); }); - }); - - describe('Xkb-kmn: getKeyModifierArrayFromActionID ', function () { - const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const sutR = new XkbFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/tests-xkb-kmn/Test.keylayout'); - const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); - [ - ['A_16', [{ "key": "32", "behavior": "5" }]], - ['A_19', [{ "key": "45", "behavior": "5" }]], - ['A_18', [{ "key": "24", "behavior": "0" }, { "key": "24", "behavior": "5" }]], - ['unknown', []], - [undefined, []], - [null, []], - [' ', []], - ['', []], - ].forEach(function (values) { - let outstring = '[ '; - for (let i = 0; i < values[1].length; i++) { - outstring = outstring + "[ " + JSON.stringify(values[1][i]) + "], "; - } - it(("getKeyModifierArrayFromActionID('" + values[0] + "')").padEnd(57, " ") + ' should return ' + outstring.substring(0, outstring.lastIndexOf(']') + 2) + " ]", async function () { - const result = sut.getKeyModifierArrayFromActionID(read, String(values[0])); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + + describe('Xkb-kmn: getKeyModifierArrayFromActionID ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sutR = new XkbFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/tests-xkb-kmn/Test.keylayout'); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + [ + ['A_16', [{ "key": "32", "behavior": "5" }]], + ['A_19', [{ "key": "45", "behavior": "5" }]], + ['A_18', [{ "key": "24", "behavior": "0" }, { "key": "24", "behavior": "5" }]], + ['unknown', []], + [undefined, []], + [null, []], + [' ', []], + ['', []], + ].forEach(function (values) { + let outstring = '[ '; + for (let i = 0; i < values[1].length; i++) { + outstring = outstring + "[ " + JSON.stringify(values[1][i]) + "], "; + } + it(("getKeyModifierArrayFromActionID('" + values[0] + "')").padEnd(57, " ") + ' should return ' + outstring.substring(0, outstring.lastIndexOf(']') + 2) + " ]", async function () { + const result = sut.getKeyModifierArrayFromActionID(read, String(values[0])); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); }); }); - }); - - describe('Xkb-kmn: getActionIdFromActionNext ', function () { - const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const sutR = new XkbFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/tests-xkb-kmn/Test.keylayout'); - const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); - [ - ['none', ''], - ['0', ''], - ['A_18', ''], - ['1', 'A_16'], - ['2', 'A_8'], - ['3', 'A_17'], - ['', ''], - [' ', ''], - ['99', ''], - [null, ''], - [undefined, ''], - ['unknown', ''], - ].forEach(function (values) { - it(("getActionIdFromActionNext('" + values[0] + "')").padEnd(49, " ") + ' should return ' + "'" + values[1] + "'", async function () { - const result = sut.getActionIdFromActionNext(read, String(values[0])); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + + describe('Xkb-kmn: getActionIdFromActionNext ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sutR = new XkbFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/tests-xkb-kmn/Test.keylayout'); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + [ + ['none', ''], + ['0', ''], + ['A_18', ''], + ['1', 'A_16'], + ['2', 'A_8'], + ['3', 'A_17'], + ['', ''], + [' ', ''], + ['99', ''], + [null, ''], + [undefined, ''], + ['unknown', ''], + ].forEach(function (values) { + it(("getActionIdFromActionNext('" + values[0] + "')").padEnd(49, " ") + ' should return ' + "'" + values[1] + "'", async function () { + const result = sut.getActionIdFromActionNext(read, String(values[0])); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); }); }); - }); - - describe('Xkb-kmn: getActionIndexFromActionId ', function () { - const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const sutR = new XkbFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/tests-xkb-kmn/Test.keylayout'); - const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); - [ - ['none', -1], - ['A_16', 8], - ['A_18', 10], - ['A_19', 11], - ['0', -1], - ['', -1], - [' ', -1], - [null, -1], - [undefined, -1], - ['unknown', -1], - ].forEach(function (values) { - it(("getActionIndexFromActionId('" + values[0] + "')").padEnd(50, " ") + ' should return ' + values[1], async function () { - const result = sut.getActionIndexFromActionId(read, String(values[0])); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + + describe('Xkb-kmn: getActionIndexFromActionId ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sutR = new XkbFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/tests-xkb-kmn/Test.keylayout'); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + [ + ['none', -1], + ['A_16', 8], + ['A_18', 10], + ['A_19', 11], + ['0', -1], + ['', -1], + [' ', -1], + [null, -1], + [undefined, -1], + ['unknown', -1], + ].forEach(function (values) { + it(("getActionIndexFromActionId('" + values[0] + "')").padEnd(50, " ") + ' should return ' + values[1], async function () { + const result = sut.getActionIndexFromActionId(read, String(values[0])); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); }); }); - }); - - describe('Xkb-kmn: getOutputFromActionIdNone ', function () { - const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const sutR = new XkbFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/tests-xkb-kmn/Test.keylayout'); - const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); - [ - ['A_14', 'u'], - ['', ''], - [' ', ''], - ['A_18', ''], - ['unknown', ''], - ].forEach(function (values) { - it( - ("getOutputFromActionIdNone('" + values[0] + "')").padEnd(56, " ") + ' should return ' + "'" + values[1] + "'", async function () { + + describe('Xkb-kmn: getOutputFromActionIdNone ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sutR = new XkbFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/tests-xkb-kmn/Test.keylayout'); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + [ + ['A_14', 'u'], + ['', ''], + [' ', ''], + ['A_18', ''], + ['unknown', ''], + ].forEach(function (values) { + it( + ("getOutputFromActionIdNone('" + values[0] + "')").padEnd(56, " ") + ' should return ' + "'" + values[1] + "'", async function () { + const result = sut.getOutputFromActionIdNone(read, String(values[0])); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); + + [[null, ''], + [undefined, ''], + [99, ''], + ].forEach(function (values) { + it(("getOutputFromActionIdNone('" + values[0] + "')").padEnd(56, " ") + ' should return ' + values[1], async function () { const result = sut.getOutputFromActionIdNone(read, String(values[0])); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); - }); - - [[null, ''], - [undefined, ''], - [99, ''], - ].forEach(function (values) { - it(("getOutputFromActionIdNone('" + values[0] + "')").padEnd(56, " ") + ' should return ' + values[1], async function () { - const result = sut.getOutputFromActionIdNone(read, String(values[0])); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); }); - }); - - describe('Xkb-kmn: getKeybehaviorModOutputArrayFromKeyActionbehaviorOutputArray ', function () { - const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const sutR = new XkbFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/tests-xkb-kmn/Test.keylayout'); - const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); - - const b1KeycodeArr: KeylayoutFileData[] = [ - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '0', outchar: 'ˆ' }, - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '1', outchar: 'ˆ' }, - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '2', outchar: 'ˆ' }, - { keyCode: '6', key: 'K_Z', actionId: 'A_0', behavior: '4', outchar: 'ˆ' }, - { keyCode: '25', key: 'K_9', actionId: 'A_0', behavior: '4', outchar: 'ˆ' }, - { keyCode: '43', key: 'K_COMMA', actionId: 'A_0', behavior: '4', outchar: 'ˆ' }, - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '3', outchar: 'ˆ' }, - { keyCode: '0', key: 'K_A', actionId: 'A_1', behavior: '2', outchar: 'Â' }, - { keyCode: '0', key: 'K_A', actionId: 'A_1', behavior: '1', outchar: 'Â' }, - { keyCode: '14', key: 'K_E', actionId: 'A_10', behavior: '0', outchar: 'ê' }, - { keyCode: '34', key: 'K_I', actionId: 'A_11', behavior: '0', outchar: 'î' }, - { keyCode: '31', key: 'K_O', actionId: 'A_13', behavior: '0', outchar: 'ô' }, - { keyCode: '32', key: 'K_U', actionId: 'A_14', behavior: '0', outchar: 'û' }, - { keyCode: '14', key: 'K_E', actionId: 'A_2', behavior: '2', outchar: 'Ê' }, - { keyCode: '14', key: 'K_E', actionId: 'A_2', behavior: '1', outchar: 'Ê' }, - { keyCode: '34', key: 'K_I', actionId: 'A_3', behavior: '2', outchar: 'Î' }, - { keyCode: '34', key: 'K_I', actionId: 'A_3', behavior: '1', outchar: 'Î' }, - { keyCode: '31', key: 'K_O', actionId: 'A_5', behavior: '2', outchar: 'Ô' }, - { keyCode: '31', key: 'K_O', actionId: 'A_5', behavior: '1', outchar: 'Ô' }, - { keyCode: '32', key: 'K_U', actionId: 'A_6', behavior: '2', outchar: 'Û' }, - { keyCode: '32', key: 'K_U', actionId: 'A_6', behavior: '1', outchar: 'Û' }, - { keyCode: '0', key: 'K_A', actionId: 'A_9', behavior: '0', outchar: 'â' } - - ]; - const b1ModifierKeyArr: KeylayoutFileData[] = [ - { actionId: 'A_0', key: 'K_SPACE', behavior: '0', modifier: 'NCAPS', outchar: 'ˆ' }, - { actionId: 'A_0', key: 'K_SPACE', behavior: '1', modifier: 'CAPS', outchar: 'ˆ' }, - { actionId: 'A_0', key: 'K_SPACE', behavior: '2', modifier: 'NCAPS SHIFT', outchar: 'ˆ' }, - { actionId: 'A_0', key: 'K_SPACE', behavior: '2', modifier: 'SHIFT CAPS', outchar: 'ˆ' }, - { actionId: 'A_0', key: 'K_Z', behavior: '4', modifier: 'NCAPS SHIFT RALT', outchar: 'ˆ' }, - { actionId: 'A_0', key: 'K_9', behavior: '4', modifier: 'NCAPS SHIFT RALT', outchar: 'ˆ' }, - { actionId: 'A_0', key: 'K_COMMA', behavior: '4', modifier: 'NCAPS SHIFT RALT', outchar: 'ˆ' }, - { actionId: 'A_0', key: 'K_SPACE', behavior: '3', modifier: 'NCAPS RALT CTRL', outchar: 'ˆ' }, - { actionId: 'A_0', key: 'K_SPACE', behavior: '3', modifier: 'NCAPS CTRL', outchar: 'ˆ' }, - { actionId: 'A_1', key: 'K_A', behavior: '2', modifier: 'NCAPS SHIFT', outchar: 'Â' }, - { actionId: 'A_1', key: 'K_A', behavior: '2', modifier: 'SHIFT CAPS', outchar: 'Â' }, - { actionId: 'A_1', key: 'K_A', behavior: '1', modifier: 'CAPS', outchar: 'Â' }, - { actionId: 'A_10', key: 'K_E', behavior: '0', modifier: 'NCAPS', outchar: 'ê' }, - { actionId: 'A_11', key: 'K_I', behavior: '0', modifier: 'NCAPS', outchar: 'î' }, - { actionId: 'A_13', key: 'K_O', behavior: '0', modifier: 'NCAPS', outchar: 'ô' }, - { actionId: 'A_14', key: 'K_U', behavior: '0', modifier: 'NCAPS', outchar: 'û' }, - { actionId: 'A_2', key: 'K_E', behavior: '2', modifier: 'NCAPS SHIFT', outchar: 'Ê' }, - { actionId: 'A_2', key: 'K_E', behavior: '2', modifier: 'SHIFT CAPS', outchar: 'Ê' }, - { actionId: 'A_2', key: 'K_E', behavior: '1', modifier: 'CAPS', outchar: 'Ê' }, - { actionId: 'A_3', key: 'K_I', behavior: '2', modifier: 'NCAPS SHIFT', outchar: 'Î' }, - { actionId: 'A_3', key: 'K_I', behavior: '2', modifier: 'SHIFT CAPS', outchar: 'Î' }, - { actionId: 'A_3', key: 'K_I', behavior: '1', modifier: 'CAPS', outchar: 'Î' }, - { actionId: 'A_5', key: 'K_O', behavior: '2', modifier: 'NCAPS SHIFT', outchar: 'Ô' }, - { actionId: 'A_5', key: 'K_O', behavior: '2', modifier: 'SHIFT CAPS', outchar: 'Ô' }, - { actionId: 'A_5', key: 'K_O', behavior: '1', modifier: 'CAPS', outchar: 'Ô' }, - { actionId: 'A_6', key: 'K_U', behavior: '2', modifier: 'NCAPS SHIFT', outchar: 'Û' }, - { actionId: 'A_6', key: 'K_U', behavior: '2', modifier: 'SHIFT CAPS', outchar: 'Û' }, - { actionId: 'A_6', key: 'K_U', behavior: '1', modifier: 'CAPS', outchar: 'Û' }, - { actionId: 'A_9', key: 'K_A', behavior: '0', modifier: 'NCAPS', outchar: 'â' } - ]; - - [[b1KeycodeArr, b1ModifierKeyArr], - [[{ keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '0', modifier: '0', outchar: 'ˆ' }], [{ actionId: 'A_0', key: 'K_SPACE', behavior: '0', modifier: 'NCAPS', outchar: 'ˆ' }]], - [[{ keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '0', modifier: '', outchar: 'ˆ' }], [{ actionId: 'A_0', key: 'K_SPACE', behavior: '0', modifier: 'NCAPS', outchar: 'ˆ' }]], - [[{ keyCode: '49', key: 'K_SPACE', actionId: '', behavior: '0', modifier: '0', outchar: 'ˆ' }], [{ actionId: '', key: 'K_SPACE', behavior: '0', modifier: 'NCAPS', outchar: 'ˆ' }]], - [[{ keyCode: '49', key: '', actionId: 'A_0', behavior: '0', modifier: '0', outchar: 'ˆ' }], [{ actionId: 'A_0', key: '', behavior: '0', modifier: 'NCAPS', outchar: 'ˆ' }]], - [[{ keyCode: '', key: 'K_SPACE', actionId: 'A_0', behavior: '0', modifier: '0', outchar: 'ˆ' }], [{ actionId: 'A_0', key: 'K_SPACE', behavior: '0', modifier: 'NCAPS', outchar: 'ˆ' }]], - [[{ keyCode: '', key: '', actionId: '', behavior: '0', modifier: '', outchar: '' }], [{ actionId: '', key: '', behavior: '0', modifier: 'NCAPS', outchar: '' }]], - ].forEach(function (values) { - const isCapsUsed = true; - const stringIn = "getKeybehaviorModOutputArrayFromKeyActionbehaviorOutputArray(['" + "', '" + "', '" + values[0][0].keyCode + "', '" + values[0][0].key + "', '" + values[0][0].actionId + "', '" + values[0][0].modifier + "', '" + values[0][0].outchar + "'])"; - const stringOut = "['" + "', '" + "', '" + values[1][0].key + "', '" + values[1][0].actionId + "', '" + "', '" + values[1][0].modifier + "', '" + values[1][0].outchar + "']"; - - it((JSON.stringify(values[1]).length > 60) ? 'an array of objects should return an array of objects' : - stringIn.padEnd(74, " ") + ' should return ' + stringOut, async function () { - const result = sut.getKeyBehaviorModOutputArrayFromKeyActionBehaviorOutputArray(read, values[0], isCapsUsed); + + describe('Xkb-kmn: getKeybehaviorModOutputArrayFromKeyActionbehaviorOutputArray ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sutR = new XkbFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/tests-xkb-kmn/Test.keylayout'); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + + const b1KeycodeArr: KeylayoutFileData[] = [ + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '0', outchar: 'ˆ' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '1', outchar: 'ˆ' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '2', outchar: 'ˆ' }, + { keyCode: '6', key: 'K_Z', actionId: 'A_0', behavior: '4', outchar: 'ˆ' }, + { keyCode: '25', key: 'K_9', actionId: 'A_0', behavior: '4', outchar: 'ˆ' }, + { keyCode: '43', key: 'K_COMMA', actionId: 'A_0', behavior: '4', outchar: 'ˆ' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '3', outchar: 'ˆ' }, + { keyCode: '0', key: 'K_A', actionId: 'A_1', behavior: '2', outchar: 'Â' }, + { keyCode: '0', key: 'K_A', actionId: 'A_1', behavior: '1', outchar: 'Â' }, + { keyCode: '14', key: 'K_E', actionId: 'A_10', behavior: '0', outchar: 'ê' }, + { keyCode: '34', key: 'K_I', actionId: 'A_11', behavior: '0', outchar: 'î' }, + { keyCode: '31', key: 'K_O', actionId: 'A_13', behavior: '0', outchar: 'ô' }, + { keyCode: '32', key: 'K_U', actionId: 'A_14', behavior: '0', outchar: 'û' }, + { keyCode: '14', key: 'K_E', actionId: 'A_2', behavior: '2', outchar: 'Ê' }, + { keyCode: '14', key: 'K_E', actionId: 'A_2', behavior: '1', outchar: 'Ê' }, + { keyCode: '34', key: 'K_I', actionId: 'A_3', behavior: '2', outchar: 'Î' }, + { keyCode: '34', key: 'K_I', actionId: 'A_3', behavior: '1', outchar: 'Î' }, + { keyCode: '31', key: 'K_O', actionId: 'A_5', behavior: '2', outchar: 'Ô' }, + { keyCode: '31', key: 'K_O', actionId: 'A_5', behavior: '1', outchar: 'Ô' }, + { keyCode: '32', key: 'K_U', actionId: 'A_6', behavior: '2', outchar: 'Û' }, + { keyCode: '32', key: 'K_U', actionId: 'A_6', behavior: '1', outchar: 'Û' }, + { keyCode: '0', key: 'K_A', actionId: 'A_9', behavior: '0', outchar: 'â' } + + ]; + const b1ModifierKeyArr: KeylayoutFileData[] = [ + { actionId: 'A_0', key: 'K_SPACE', behavior: '0', modifier: 'NCAPS', outchar: 'ˆ' }, + { actionId: 'A_0', key: 'K_SPACE', behavior: '1', modifier: 'CAPS', outchar: 'ˆ' }, + { actionId: 'A_0', key: 'K_SPACE', behavior: '2', modifier: 'NCAPS SHIFT', outchar: 'ˆ' }, + { actionId: 'A_0', key: 'K_SPACE', behavior: '2', modifier: 'SHIFT CAPS', outchar: 'ˆ' }, + { actionId: 'A_0', key: 'K_Z', behavior: '4', modifier: 'NCAPS SHIFT RALT', outchar: 'ˆ' }, + { actionId: 'A_0', key: 'K_9', behavior: '4', modifier: 'NCAPS SHIFT RALT', outchar: 'ˆ' }, + { actionId: 'A_0', key: 'K_COMMA', behavior: '4', modifier: 'NCAPS SHIFT RALT', outchar: 'ˆ' }, + { actionId: 'A_0', key: 'K_SPACE', behavior: '3', modifier: 'NCAPS RALT CTRL', outchar: 'ˆ' }, + { actionId: 'A_0', key: 'K_SPACE', behavior: '3', modifier: 'NCAPS CTRL', outchar: 'ˆ' }, + { actionId: 'A_1', key: 'K_A', behavior: '2', modifier: 'NCAPS SHIFT', outchar: 'Â' }, + { actionId: 'A_1', key: 'K_A', behavior: '2', modifier: 'SHIFT CAPS', outchar: 'Â' }, + { actionId: 'A_1', key: 'K_A', behavior: '1', modifier: 'CAPS', outchar: 'Â' }, + { actionId: 'A_10', key: 'K_E', behavior: '0', modifier: 'NCAPS', outchar: 'ê' }, + { actionId: 'A_11', key: 'K_I', behavior: '0', modifier: 'NCAPS', outchar: 'î' }, + { actionId: 'A_13', key: 'K_O', behavior: '0', modifier: 'NCAPS', outchar: 'ô' }, + { actionId: 'A_14', key: 'K_U', behavior: '0', modifier: 'NCAPS', outchar: 'û' }, + { actionId: 'A_2', key: 'K_E', behavior: '2', modifier: 'NCAPS SHIFT', outchar: 'Ê' }, + { actionId: 'A_2', key: 'K_E', behavior: '2', modifier: 'SHIFT CAPS', outchar: 'Ê' }, + { actionId: 'A_2', key: 'K_E', behavior: '1', modifier: 'CAPS', outchar: 'Ê' }, + { actionId: 'A_3', key: 'K_I', behavior: '2', modifier: 'NCAPS SHIFT', outchar: 'Î' }, + { actionId: 'A_3', key: 'K_I', behavior: '2', modifier: 'SHIFT CAPS', outchar: 'Î' }, + { actionId: 'A_3', key: 'K_I', behavior: '1', modifier: 'CAPS', outchar: 'Î' }, + { actionId: 'A_5', key: 'K_O', behavior: '2', modifier: 'NCAPS SHIFT', outchar: 'Ô' }, + { actionId: 'A_5', key: 'K_O', behavior: '2', modifier: 'SHIFT CAPS', outchar: 'Ô' }, + { actionId: 'A_5', key: 'K_O', behavior: '1', modifier: 'CAPS', outchar: 'Ô' }, + { actionId: 'A_6', key: 'K_U', behavior: '2', modifier: 'NCAPS SHIFT', outchar: 'Û' }, + { actionId: 'A_6', key: 'K_U', behavior: '2', modifier: 'SHIFT CAPS', outchar: 'Û' }, + { actionId: 'A_6', key: 'K_U', behavior: '1', modifier: 'CAPS', outchar: 'Û' }, + { actionId: 'A_9', key: 'K_A', behavior: '0', modifier: 'NCAPS', outchar: 'â' } + ]; + + [[b1KeycodeArr, b1ModifierKeyArr], + [[{ keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '0', modifier: '0', outchar: 'ˆ' }], [{ actionId: 'A_0', key: 'K_SPACE', behavior: '0', modifier: 'NCAPS', outchar: 'ˆ' }]], + [[{ keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '0', modifier: '', outchar: 'ˆ' }], [{ actionId: 'A_0', key: 'K_SPACE', behavior: '0', modifier: 'NCAPS', outchar: 'ˆ' }]], + [[{ keyCode: '49', key: 'K_SPACE', actionId: '', behavior: '0', modifier: '0', outchar: 'ˆ' }], [{ actionId: '', key: 'K_SPACE', behavior: '0', modifier: 'NCAPS', outchar: 'ˆ' }]], + [[{ keyCode: '49', key: '', actionId: 'A_0', behavior: '0', modifier: '0', outchar: 'ˆ' }], [{ actionId: 'A_0', key: '', behavior: '0', modifier: 'NCAPS', outchar: 'ˆ' }]], + [[{ keyCode: '', key: 'K_SPACE', actionId: 'A_0', behavior: '0', modifier: '0', outchar: 'ˆ' }], [{ actionId: 'A_0', key: 'K_SPACE', behavior: '0', modifier: 'NCAPS', outchar: 'ˆ' }]], + [[{ keyCode: '', key: '', actionId: '', behavior: '0', modifier: '', outchar: '' }], [{ actionId: '', key: '', behavior: '0', modifier: 'NCAPS', outchar: '' }]], + ].forEach(function (values) { + const isCapsUsed = true; + const stringIn = "getKeybehaviorModOutputArrayFromKeyActionbehaviorOutputArray(['" + "', '" + "', '" + values[0][0].keyCode + "', '" + values[0][0].key + "', '" + values[0][0].actionId + "', '" + values[0][0].modifier + "', '" + values[0][0].outchar + "'])"; + const stringOut = "['" + "', '" + "', '" + values[1][0].key + "', '" + values[1][0].actionId + "', '" + "', '" + values[1][0].modifier + "', '" + values[1][0].outchar + "']"; + + it((JSON.stringify(values[1]).length > 60) ? 'an array of objects should return an array of objects' : + stringIn.padEnd(74, " ") + ' should return ' + stringOut, async function () { + const result = sut.getKeyBehaviorModOutputArrayFromKeyActionBehaviorOutputArray(read, values[0], isCapsUsed); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); + }); + + [[{ keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '0', modifier: '0', outchar: 'ˆ' }, { actionId: 'A_0', key: 'K_SPACE', behavior: '0', modifier: '', outchar: 'ˆ' }], + [{ keyCode: '', key: 'K_SPACE', actionId: 'A_0', behavior: '0', modifier: '0', outchar: 'ˆ' }, { actionId: 'A_0', key: 'K_SPACE', behavior: '0', modifier: '', outchar: 'ˆ' }], + [{ keyCode: '', key: '', actionId: '', behavior: '0', modifier: '', outchar: '' }, { actionId: '', key: '', behavior: '0', modifier: '', outchar: '' }], + ].forEach(function (values) { + const isCapsUsed = false; + const stringIn = "getKeybehaviorModOutputArrayFromKeyActionbehaviorOutputArray([ '" + values[0].keyCode + "', '" + values[0].key + "', '" + values[0].actionId + "', '" + values[0].modifier + "', '" + values[0].outchar + "'])"; + const stringOut = "['" + values[1].actionId + "', '" + "', '" + values[1].modifier + "', '" + values[1].key + "', '" + values[1].outchar + "']"; + + it(stringIn.padEnd(74, " ") + ' should return ' + stringOut, async function () { + const result = sut.getKeyBehaviorModOutputArrayFromKeyActionBehaviorOutputArray(read, [values[0]], isCapsUsed); + assert.equal(JSON.stringify(result), JSON.stringify([values[1]])); + }); + }); + + [[[], []], + [undefined, []], + [null, []], + ].forEach(function (values) { + const isCaps = true; + it(("getKeybehaviorModOutputArrayFromKeyActionbehaviorOutputArray([" + values[0] + "])").padEnd(74, " ") + ' should return ' + "[" + values[1] + "]", async function () { + const result = sut.getKeyBehaviorModOutputArrayFromKeyActionBehaviorOutputArray(read, values[0], isCaps); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); + }); }); - - [[{ keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '0', modifier: '0', outchar: 'ˆ' }, { actionId: 'A_0', key: 'K_SPACE', behavior: '0', modifier: '', outchar: 'ˆ' }], - [{ keyCode: '', key: 'K_SPACE', actionId: 'A_0', behavior: '0', modifier: '0', outchar: 'ˆ' }, { actionId: 'A_0', key: 'K_SPACE', behavior: '0', modifier: '', outchar: 'ˆ' }], - [{ keyCode: '', key: '', actionId: '', behavior: '0', modifier: '', outchar: '' }, { actionId: '', key: '', behavior: '0', modifier: '', outchar: '' }], - ].forEach(function (values) { - const isCapsUsed = false; - const stringIn = "getKeybehaviorModOutputArrayFromKeyActionbehaviorOutputArray([ '" + values[0].keyCode + "', '" + values[0].key + "', '" + values[0].actionId + "', '" + values[0].modifier + "', '" + values[0].outchar + "'])"; - const stringOut = "['" + values[1].actionId + "', '" + "', '" + values[1].modifier + "', '" + values[1].key + "', '" + values[1].outchar + "']"; - - it(stringIn.padEnd(74, " ") + ' should return ' + stringOut, async function () { - const result = sut.getKeyBehaviorModOutputArrayFromKeyActionBehaviorOutputArray(read, [values[0]], isCapsUsed); - assert.equal(JSON.stringify(result), JSON.stringify([values[1]])); + + describe('Xkb-kmn: getActionStateOutputArrayFromActionState ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sutR = new XkbFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/tests-xkb-kmn/Test.keylayout'); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + [['1', [ + { "id": "A_0", "state": "1", "output": "ˆ" }, + { "id": "A_1", "state": "1", "output": "Â" }, + { "id": "A_10", "state": "1", "output": "ê" }, + { "id": "A_11", "state": "1", "output": "î" }, + { "id": "A_13", "state": "1", "output": "ô" }, + { "id": "A_14", "state": "1", "output": "û" }, + { "id": "A_2", "state": "1", "output": "Ê" }, + { "id": "A_3", "state": "1", "output": "Î" }, + { "id": "A_5", "state": "1", "output": "Ô" }, + { "id": "A_6", "state": "1", "output": "Û" }, + { "id": "A_9", "state": "1", "output": "â" } + ],], + ['2', [ + { "id": "A_0", "state": "2", "output": "`" }, + { "id": "A_1", "state": "2", "output": "À" }, + { "id": "A_10", "state": "2", "output": "è" }, + { "id": "A_11", "state": "2", "output": "ì" }, + { "id": "A_13", "state": "2", "output": "ò" }, + { "id": "A_14", "state": "2", "output": "ù" }, + { "id": "A_2", "state": "2", "output": "È" }, + { "id": "A_3", "state": "2", "output": "Ì" }, + { "id": "A_5", "state": "2", "output": "Ò" }, + { "id": "A_6", "state": "2", "output": "Ù" }, + { "id": "A_9", "state": "2", "output": "à" } + ],], + ['789', [],], + ['', [],], + [' ', [],], + [123, [],], + [null, [],], + [undefined, [],], + ].forEach(function (values) { + it((JSON.stringify(values[1]).length > 30) ? + ("getActionStateOutputArrayFromActionState('" + values[0] + "')").padEnd(60, " ") + ' should return an array of objects' : + ("getActionStateOutputArrayFromActionState('" + values[0] + "')").padEnd(60, " ") + ' should return ' + "'" + JSON.stringify(values[1]) + "'", async function () { + const result = sut.getActionStateOutputArrayFromActionState(read, String(values[0])); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); }); }); - - [[[], []], - [undefined, []], - [null, []], - ].forEach(function (values) { - const isCaps = true; - it(("getKeybehaviorModOutputArrayFromKeyActionbehaviorOutputArray([" + values[0] + "])").padEnd(74, " ") + ' should return ' + "[" + values[1] + "]", async function () { - const result = sut.getKeyBehaviorModOutputArrayFromKeyActionBehaviorOutputArray(read, values[0], isCaps); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + + describe('Xkb-kmn: getActionOutputbehaviorKeyModiFromActionIDStateOutput ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sutR = new XkbFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/tests-xkb-kmn/Test.keylayout'); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + const converted = sut.convertBound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); + [ + ['A_1', 'A', true, + [{ "outchar": "A", "actionId": "A_1", "behavior": "1", "key": "K_A", "modifier": "CAPS" }, + { "outchar": "A", "actionId": "A_1", "behavior": "2", "key": "K_A", "modifier": "NCAPS SHIFT" }, + { "outchar": "A", "actionId": "A_1", "behavior": "2", "key": "K_A", "modifier": "SHIFT CAPS" }] + ], + ['A_1', 'A', false, + [{ "outchar": "A", "actionId": "A_1", "behavior": "1", "key": "K_A", "modifier": "CAPS" }, + { "outchar": "A", "actionId": "A_1", "behavior": "2", "key": "K_A", "modifier": "SHIFT" }, + { "outchar": "A", "actionId": "A_1", "behavior": "2", "key": "K_A", "modifier": "SHIFT CAPS" }] + ], + ['A_9', 'a', true, [{ "outchar": "a", "actionId": "A_9", "behavior": "0", "key": "K_A", "modifier": "NCAPS" }]], + ['A_9', 'a', false, [{ "outchar": "a", "actionId": "A_9", "behavior": "0", "key": "K_A", "modifier": "" }]], + ['A_9', 'a', , [{ "outchar": "a", "actionId": "A_9", "behavior": "0", "key": "K_A", "modifier": "" }]], + ['A_9', '', true, [{ "outchar": "", "actionId": "A_9", "behavior": "0", "key": "K_A", "modifier": "NCAPS" }]], + ['A_9', '', false, [{ "outchar": "", "actionId": "A_9", "behavior": "0", "key": "K_A", "modifier": "" }]], + ['', 'a', true, []], + ['', 'a', false, []], + ['', '', , []], + ].forEach(function (values) { + it((JSON.stringify(values[3]).length > 35) ? + ("getActionOutputbehaviorKeyModiFromActionIDStateOutput('" + values[0] + "', '" + values[1] + "', " + values[2] + ")").padEnd(67, " ") + ' should return an array of objects' : + ("getActionOutputbehaviorKeyModiFromActionIDStateOutput('" + values[0] + "', '" + values[1] + "', " + values[2] + ")").padEnd(67, " ") + ' should return ' + "'" + JSON.stringify(values[3]) + "'", async function () { + const result = sut.getActionOutputBehaviorKeyModiFromActionIDStateOutput(read, converted.modifiers, String(values[0]), String(values[1]), Boolean(values[2])); + assert.equal(JSON.stringify(result), JSON.stringify(values[3])); + }); }); }); - }); - - describe('Xkb-kmn: getActionStateOutputArrayFromActionState ', function () { - const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const sutR = new XkbFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/tests-xkb-kmn/Test.keylayout'); - const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); - [['1', [ - { "id": "A_0", "state": "1", "output": "ˆ" }, - { "id": "A_1", "state": "1", "output": "Â" }, - { "id": "A_10", "state": "1", "output": "ê" }, - { "id": "A_11", "state": "1", "output": "î" }, - { "id": "A_13", "state": "1", "output": "ô" }, - { "id": "A_14", "state": "1", "output": "û" }, - { "id": "A_2", "state": "1", "output": "Ê" }, - { "id": "A_3", "state": "1", "output": "Î" }, - { "id": "A_5", "state": "1", "output": "Ô" }, - { "id": "A_6", "state": "1", "output": "Û" }, - { "id": "A_9", "state": "1", "output": "â" } - ],], - ['2', [ - { "id": "A_0", "state": "2", "output": "`" }, - { "id": "A_1", "state": "2", "output": "À" }, - { "id": "A_10", "state": "2", "output": "è" }, - { "id": "A_11", "state": "2", "output": "ì" }, - { "id": "A_13", "state": "2", "output": "ò" }, - { "id": "A_14", "state": "2", "output": "ù" }, - { "id": "A_2", "state": "2", "output": "È" }, - { "id": "A_3", "state": "2", "output": "Ì" }, - { "id": "A_5", "state": "2", "output": "Ò" }, - { "id": "A_6", "state": "2", "output": "Ù" }, - { "id": "A_9", "state": "2", "output": "à" } - ],], - ['789', [],], - ['', [],], - [' ', [],], - [123, [],], - [null, [],], - [undefined, [],], - ].forEach(function (values) { - it((JSON.stringify(values[1]).length > 30) ? - ("getActionStateOutputArrayFromActionState('" + values[0] + "')").padEnd(60, " ") + ' should return an array of objects' : - ("getActionStateOutputArrayFromActionState('" + values[0] + "')").padEnd(60, " ") + ' should return ' + "'" + JSON.stringify(values[1]) + "'", async function () { - const result = sut.getActionStateOutputArrayFromActionState(read, String(values[0])); + + describe('Xkb-kmn: getKeyActionOutputArrayFromActionStateOutputArray ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sutR = new XkbFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/tests-xkb-kmn/Test.keylayout'); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + + const b6ActionIdArr: ActionStateOutput[] = [ + { "id": "A_0", "state": "1", "output": "ˆ" }, + { "id": "A_1", "state": "1", "output": "Â" }, + { "id": "A_10", "state": "1", "output": "ê" }, + { "id": "A_11", "state": "1", "output": "î" }, + { "id": "A_13", "state": "1", "output": "ô" }, + { "id": "A_14", "state": "1", "output": "û" }, + { "id": "A_2", "state": "1", "output": "Ê" }, + { "id": "A_3", "state": "1", "output": "Î" }, + { "id": "A_5", "state": "1", "output": "Ô" }, + { "id": "A_6", "state": "1", "output": "Û" }, + { "id": "A_9", "state": "1", "output": "â" } + ]; + + const b1KeycodeArr: KeylayoutFileData[] = [ + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '0', outchar: 'ˆ' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '1', outchar: 'ˆ' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '2', outchar: 'ˆ' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '3', outchar: 'ˆ' }, + { keyCode: '6', key: 'K_Z', actionId: 'A_0', behavior: '4', outchar: 'ˆ' }, + { keyCode: '25', key: 'K_9', actionId: 'A_0', behavior: '4', outchar: 'ˆ' }, + { keyCode: '43', key: 'K_COMMA', actionId: 'A_0', behavior: '4', outchar: 'ˆ' }, + { keyCode: '0', key: 'K_A', actionId: 'A_1', behavior: '1', outchar: 'Â' }, + { keyCode: '0', key: 'K_A', actionId: 'A_1', behavior: '2', outchar: 'Â' }, + { keyCode: '14', key: 'K_E', actionId: 'A_10', behavior: '0', outchar: 'ê' }, + { keyCode: '34', key: 'K_I', actionId: 'A_11', behavior: '0', outchar: 'î' }, + { keyCode: '31', key: 'K_O', actionId: 'A_13', behavior: '0', outchar: 'ô' }, + { keyCode: '32', key: 'K_U', actionId: 'A_14', behavior: '0', outchar: 'û' }, + { keyCode: '14', key: 'K_E', actionId: 'A_2', behavior: '1', outchar: 'Ê' }, + { keyCode: '14', key: 'K_E', actionId: 'A_2', behavior: '2', outchar: 'Ê' }, + { keyCode: '34', key: 'K_I', actionId: 'A_3', behavior: '1', outchar: 'Î' }, + { keyCode: '34', key: 'K_I', actionId: 'A_3', behavior: '2', outchar: 'Î' }, + { keyCode: '31', key: 'K_O', actionId: 'A_5', behavior: '1', outchar: 'Ô' }, + { keyCode: '31', key: 'K_O', actionId: 'A_5', behavior: '2', outchar: 'Ô' }, + { keyCode: '32', key: 'K_U', actionId: 'A_6', behavior: '1', outchar: 'Û' }, + { keyCode: '32', key: 'K_U', actionId: 'A_6', behavior: '2', outchar: 'Û' }, + { keyCode: '0', key: 'K_A', actionId: 'A_9', behavior: '0', outchar: 'â' } + ]; + + [[b6ActionIdArr, b1KeycodeArr], + ].forEach(function (values) { + it(("getKeyActionOutputArrayFromActionStateOutputArray([['" + JSON.stringify(values[0]) + "'],..])").padEnd(73, " ") + '1 should return an array of objects', async function () { + const result = sut.getKeyActionOutputArrayFromActionStateOutputArray(read, values[0] as ActionStateOutput[]); assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); - }); - }); - - describe('Xkb-kmn: getActionOutputbehaviorKeyModiFromActionIDStateOutput ', function () { - const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const sutR = new XkbFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/tests-xkb-kmn/Test.keylayout'); - const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); - const converted = sut.convertBound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); - [ - ['A_1', 'A', true, - [{ "outchar": "A", "actionId": "A_1", "behavior": "1", "key": "K_A", "modifier": "CAPS" }, - { "outchar": "A", "actionId": "A_1", "behavior": "2", "key": "K_A", "modifier": "NCAPS SHIFT" }, - { "outchar": "A", "actionId": "A_1", "behavior": "2", "key": "K_A", "modifier": "SHIFT CAPS" }] - ], - ['A_1', 'A', false, - [{ "outchar": "A", "actionId": "A_1", "behavior": "1", "key": "K_A", "modifier": "CAPS" }, - { "outchar": "A", "actionId": "A_1", "behavior": "2", "key": "K_A", "modifier": "SHIFT" }, - { "outchar": "A", "actionId": "A_1", "behavior": "2", "key": "K_A", "modifier": "SHIFT CAPS" }] - ], - ['A_9', 'a', true, [{ "outchar": "a", "actionId": "A_9", "behavior": "0", "key": "K_A", "modifier": "NCAPS" }]], - ['A_9', 'a', false, [{ "outchar": "a", "actionId": "A_9", "behavior": "0", "key": "K_A", "modifier": "" }]], - ['A_9', 'a', , [{ "outchar": "a", "actionId": "A_9", "behavior": "0", "key": "K_A", "modifier": "" }]], - ['A_9', '', true, [{ "outchar": "", "actionId": "A_9", "behavior": "0", "key": "K_A", "modifier": "NCAPS" }]], - ['A_9', '', false, [{ "outchar": "", "actionId": "A_9", "behavior": "0", "key": "K_A", "modifier": "" }]], - ['', 'a', true, []], - ['', 'a', false, []], - ['', '', , []], - ].forEach(function (values) { - it((JSON.stringify(values[3]).length > 35) ? - ("getActionOutputbehaviorKeyModiFromActionIDStateOutput('" + values[0] + "', '" + values[1] + "', " + values[2] + ")").padEnd(67, " ") + ' should return an array of objects' : - ("getActionOutputbehaviorKeyModiFromActionIDStateOutput('" + values[0] + "', '" + values[1] + "', " + values[2] + ")").padEnd(67, " ") + ' should return ' + "'" + JSON.stringify(values[3]) + "'", async function () { - const result = sut.getActionOutputBehaviorKeyModiFromActionIDStateOutput(read, converted.modifiers, String(values[0]), String(values[1]), Boolean(values[2])); - assert.equal(JSON.stringify(result), JSON.stringify(values[3])); - }); - }); - }); - - describe('Xkb-kmn: getKeyActionOutputArrayFromActionStateOutputArray ', function () { - const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const sutR = new XkbFileReader(compilerTestCallbacks); - const inputFilename = makePathToFixture('../data/tests-xkb-kmn/Test.keylayout'); - const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); - - const b6ActionIdArr: ActionStateOutput[] = [ - { "id": "A_0", "state": "1", "output": "ˆ" }, - { "id": "A_1", "state": "1", "output": "Â" }, - { "id": "A_10", "state": "1", "output": "ê" }, - { "id": "A_11", "state": "1", "output": "î" }, - { "id": "A_13", "state": "1", "output": "ô" }, - { "id": "A_14", "state": "1", "output": "û" }, - { "id": "A_2", "state": "1", "output": "Ê" }, - { "id": "A_3", "state": "1", "output": "Î" }, - { "id": "A_5", "state": "1", "output": "Ô" }, - { "id": "A_6", "state": "1", "output": "Û" }, - { "id": "A_9", "state": "1", "output": "â" } - ]; - - const b1KeycodeArr: KeylayoutFileData[] = [ - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '0', outchar: 'ˆ' }, - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '1', outchar: 'ˆ' }, - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '2', outchar: 'ˆ' }, - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '3', outchar: 'ˆ' }, - { keyCode: '6', key: 'K_Z', actionId: 'A_0', behavior: '4', outchar: 'ˆ' }, - { keyCode: '25', key: 'K_9', actionId: 'A_0', behavior: '4', outchar: 'ˆ' }, - { keyCode: '43', key: 'K_COMMA', actionId: 'A_0', behavior: '4', outchar: 'ˆ' }, - { keyCode: '0', key: 'K_A', actionId: 'A_1', behavior: '1', outchar: 'Â' }, - { keyCode: '0', key: 'K_A', actionId: 'A_1', behavior: '2', outchar: 'Â' }, - { keyCode: '14', key: 'K_E', actionId: 'A_10', behavior: '0', outchar: 'ê' }, - { keyCode: '34', key: 'K_I', actionId: 'A_11', behavior: '0', outchar: 'î' }, - { keyCode: '31', key: 'K_O', actionId: 'A_13', behavior: '0', outchar: 'ô' }, - { keyCode: '32', key: 'K_U', actionId: 'A_14', behavior: '0', outchar: 'û' }, - { keyCode: '14', key: 'K_E', actionId: 'A_2', behavior: '1', outchar: 'Ê' }, - { keyCode: '14', key: 'K_E', actionId: 'A_2', behavior: '2', outchar: 'Ê' }, - { keyCode: '34', key: 'K_I', actionId: 'A_3', behavior: '1', outchar: 'Î' }, - { keyCode: '34', key: 'K_I', actionId: 'A_3', behavior: '2', outchar: 'Î' }, - { keyCode: '31', key: 'K_O', actionId: 'A_5', behavior: '1', outchar: 'Ô' }, - { keyCode: '31', key: 'K_O', actionId: 'A_5', behavior: '2', outchar: 'Ô' }, - { keyCode: '32', key: 'K_U', actionId: 'A_6', behavior: '1', outchar: 'Û' }, - { keyCode: '32', key: 'K_U', actionId: 'A_6', behavior: '2', outchar: 'Û' }, - { keyCode: '0', key: 'K_A', actionId: 'A_9', behavior: '0', outchar: 'â' } - ]; - - [[b6ActionIdArr, b1KeycodeArr], - ].forEach(function (values) { - it(("getKeyActionOutputArrayFromActionStateOutputArray([['" + JSON.stringify(values[0]) + "'],..])").padEnd(73, " ") + '1 should return an array of objects', async function () { - const result = sut.getKeyActionOutputArrayFromActionStateOutputArray(read, values[0] as ActionStateOutput[]); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); }); - }); - - const oneEntryResult = [ - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '0', outchar: 'ˆ' }, - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '1', outchar: 'ˆ' }, - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '2', outchar: 'ˆ' }, - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '3', outchar: 'ˆ' }, - { keyCode: '6', key: 'K_Z', actionId: 'A_0', behavior: '4', outchar: 'ˆ' }, - { keyCode: '25', key: 'K_9', actionId: 'A_0', behavior: '4', outchar: 'ˆ' }, - { keyCode: '43', key: 'K_COMMA', actionId: 'A_0', behavior: '4', outchar: 'ˆ' } - ]; - const oneEntryResultNoOutput = [ - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '0', outchar: '' }, - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '1', outchar: '' }, - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '2', outchar: '' }, - { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '3', outchar: '' }, - { keyCode: '6', key: 'K_Z', actionId: 'A_0', behavior: '4', outchar: '' }, - { keyCode: '25', key: 'K_9', actionId: 'A_0', behavior: '4', outchar: '' }, - { keyCode: '43', key: 'K_COMMA', actionId: 'A_0', behavior: '4', outchar: '' }, - ]; - - [[[{ "id": "A_0", "state": "1", "output": "ˆ" }], oneEntryResult], - [[{ "id": "A_0", "state": "1", "output": "" }], oneEntryResultNoOutput], - [[{ "id": "A_0", "state": "", "output": "ˆ" }], oneEntryResult], - ].forEach(function (values) { - it(("getKeyActionOutputArrayFromActionStateOutputArray(['" + JSON.stringify(values[0]) + "'])").padEnd(73, " ") + ' should return an array of objects', async function () { - const result = sut.getKeyActionOutputArrayFromActionStateOutputArray(read, values[0] as ActionStateOutput[]); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + const oneEntryResult = [ + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '0', outchar: 'ˆ' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '1', outchar: 'ˆ' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '2', outchar: 'ˆ' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '3', outchar: 'ˆ' }, + { keyCode: '6', key: 'K_Z', actionId: 'A_0', behavior: '4', outchar: 'ˆ' }, + { keyCode: '25', key: 'K_9', actionId: 'A_0', behavior: '4', outchar: 'ˆ' }, + { keyCode: '43', key: 'K_COMMA', actionId: 'A_0', behavior: '4', outchar: 'ˆ' } + ]; + + const oneEntryResultNoOutput = [ + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '0', outchar: '' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '1', outchar: '' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '2', outchar: '' }, + { keyCode: '49', key: 'K_SPACE', actionId: 'A_0', behavior: '3', outchar: '' }, + { keyCode: '6', key: 'K_Z', actionId: 'A_0', behavior: '4', outchar: '' }, + { keyCode: '25', key: 'K_9', actionId: 'A_0', behavior: '4', outchar: '' }, + { keyCode: '43', key: 'K_COMMA', actionId: 'A_0', behavior: '4', outchar: '' }, + ]; + + [[[{ "id": "A_0", "state": "1", "output": "ˆ" }], oneEntryResult], + [[{ "id": "A_0", "state": "1", "output": "" }], oneEntryResultNoOutput], + [[{ "id": "A_0", "state": "", "output": "ˆ" }], oneEntryResult], + ].forEach(function (values) { + it(("getKeyActionOutputArrayFromActionStateOutputArray(['" + JSON.stringify(values[0]) + "'])").padEnd(73, " ") + ' should return an array of objects', async function () { + const result = sut.getKeyActionOutputArrayFromActionStateOutputArray(read, values[0] as ActionStateOutput[]); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); }); - }); - - [[[{ "id": "", "state": "1", "output": "ˆ" }], []], - [[{ "id": "", "state": "", "output": "" }], []], - [[{ "id": " ", "state": " ", "output": "" }], []], - - ].forEach(function (values) { - it(("getKeyActionOutputArrayFromActionStateOutputArray(" + JSON.stringify(values[0]) + ")").padEnd(73, " ") + ' should return ' + "'[" + JSON.stringify(values[1]) + "]'", async function () { - const result = sut.getKeyActionOutputArrayFromActionStateOutputArray(read, values[0] as ActionStateOutput[]); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + + [[[{ "id": "", "state": "1", "output": "ˆ" }], []], + [[{ "id": "", "state": "", "output": "" }], []], + [[{ "id": " ", "state": " ", "output": "" }], []], + + ].forEach(function (values) { + it(("getKeyActionOutputArrayFromActionStateOutputArray(" + JSON.stringify(values[0]) + ")").padEnd(73, " ") + ' should return ' + "'[" + JSON.stringify(values[1]) + "]'", async function () { + const result = sut.getKeyActionOutputArrayFromActionStateOutputArray(read, values[0] as ActionStateOutput[]); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); }); - }); - - [[, []], - [undefined, []], - [null, []], - ].forEach(function (values) { - it(("getKeyActionOutputArrayFromActionStateOutputArray(" + JSON.stringify(values[0]) + ")").padEnd(73, " ") + ' should return ' + "'[" + JSON.stringify(values[1]) + "]'", async function () { - const result = sut.getKeyActionOutputArrayFromActionStateOutputArray(read, values[0] as ActionStateOutput[]); - assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + + [[, []], + [undefined, []], + [null, []], + ].forEach(function (values) { + it(("getKeyActionOutputArrayFromActionStateOutputArray(" + JSON.stringify(values[0]) + ")").padEnd(73, " ") + ' should return ' + "'[" + JSON.stringify(values[1]) + "]'", async function () { + const result = sut.getKeyActionOutputArrayFromActionStateOutputArray(read, values[0] as ActionStateOutput[]); + assert.equal(JSON.stringify(result), JSON.stringify(values[1])); + }); }); }); - }); - - describe('Xkb-kmn: createRuleData ', function () { - const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const sutR = new XkbFileReader(compilerTestCallbacks); - [ - [ - ['../data/tests-xkb-kmn/Test_C0.keylayout'], - [new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_A', new TextEncoder().encode('a')), - new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_A', new TextEncoder().encode('A')), - new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_S', new TextEncoder().encode('s')), - new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_D', new TextEncoder().encode('d'))] - ], - [ - ['../data/tests-xkb-kmn/Test_C1.keylayout'], - [new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_S', new TextEncoder().encode('s')), - new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_S', new TextEncoder().encode('S'))] - ], - [ - ['../data/tests-xkb-kmn/Test_C2.keylayout'], - [new Rule("C2", '', '', 0, 0, 'NCAPS', 'K_U', 1, 1, 'CAPS', 'K_A', new TextEncoder().encode('Â'))], - ], - [ - ['../data/tests-xkb-kmn/Test_C3.keylayout'], - [new Rule("C3", 'NCAPS SHIFT', 'K_D', 2, 1, 'NCAPS', 'K_U', 1, 2, 'CAPS', 'K_A', new TextEncoder().encode('Â'))] - ], - - [ - ['../data/tests-xkb-kmn/Test_C3_several.keylayout'], - [new Rule("C3", 'NCAPS RALT', 'K_8', 3, 1, 'CAPS', 'K_U', 1, 3, 'NCAPS', 'K_A', new TextEncoder().encode('â')), - new Rule("C3", 'NCAPS RALT', 'K_8', 3, 0, 'CAPS', 'K_U', 1, 0, 'NCAPS RALT', 'K_A', new TextEncoder().encode('â')), - new Rule("C3", 'NCAPS RALT', 'K_8', 3, 0, 'NCAPS RALT', 'K_U', 2, 2, 'NCAPS', 'K_A', new TextEncoder().encode('â')), - new Rule("C3", 'NCAPS RALT', 'K_8', 3, 0, 'NCAPS RALT', 'K_U', 2, 0, 'NCAPS RALT', 'K_A', new TextEncoder().encode('â'))] - ], + + describe('Xkb-kmn: createRuleData ', function () { + const sut = new XkbToKmnConverter(compilerTestCallbacks, compilerTestOptions); + const sutR = new XkbFileReader(compilerTestCallbacks); [ - ['../data/tests-xkb-kmn/Test_C0_C1_C2_C3.keylayout'], - [new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_A', new TextEncoder().encode('A')), - new Rule("C2", '', '', 0, 0, 'NCAPS RALT', 'K_EQUAL', 1, 1, 'CAPS', 'K_D', new TextEncoder().encode('Â')), - new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_S', new TextEncoder().encode('S')), - new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'NCAPS RALT', 'K_U', new TextEncoder().encode('S')), - new Rule("C3", 'NCAPS RALT', 'K_8', 6, 1, 'CAPS', 'K_S', 2, 6, 'CAPS', 'K_D', new TextEncoder().encode('Â')), - new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'CAPS', 'K_U', 3, 3, 'CAPS', 'K_D', new TextEncoder().encode('Â')), - new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'NCAPS RALT', 'K_S', 4, 4, 'CAPS', 'K_D', new TextEncoder().encode('Â')), - new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'NCAPS RALT', 'K_U', 5, 5, 'CAPS', 'K_D', new TextEncoder().encode('Â')), - new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_S', new TextEncoder().encode('S')), - new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'NCAPS RALT', 'K_U', new TextEncoder().encode('S')), - new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'CAPS', 'K_S', 2, 0, 'CAPS', 'K_D', new TextEncoder().encode('Â')), - new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'CAPS', 'K_U', 3, 0, 'CAPS', 'K_D', new TextEncoder().encode('Â')), - new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'NCAPS RALT', 'K_S', 4, 0, 'CAPS', 'K_D', new TextEncoder().encode('Â')), - new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'NCAPS RALT', 'K_U', 5, 0, 'CAPS', 'K_D', new TextEncoder().encode('Â')), - new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_U', new TextEncoder().encode('U')),] - ], - ].forEach(function (values: any) { - it('data of \'' + values[0] + "' passed into createRuleData() " + 'should create an array of rules', async function () { - const inputFilename = makePathToFixture(values[0][0]); - const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); - const processedData = sut.convertBound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); - assert.deepEqual(processedData.rules[0], values[1][0]); + [ + ['../data/tests-xkb-kmn/Test_C0.keylayout'], + [new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_A', new TextEncoder().encode('a')), + new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_A', new TextEncoder().encode('A')), + new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_S', new TextEncoder().encode('s')), + new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_D', new TextEncoder().encode('d'))] + ], + [ + ['../data/tests-xkb-kmn/Test_C1.keylayout'], + [new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'NCAPS', 'K_S', new TextEncoder().encode('s')), + new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_S', new TextEncoder().encode('S'))] + ], + [ + ['../data/tests-xkb-kmn/Test_C2.keylayout'], + [new Rule("C2", '', '', 0, 0, 'NCAPS', 'K_U', 1, 1, 'CAPS', 'K_A', new TextEncoder().encode('Â'))], + ], + [ + ['../data/tests-xkb-kmn/Test_C3.keylayout'], + [new Rule("C3", 'NCAPS SHIFT', 'K_D', 2, 1, 'NCAPS', 'K_U', 1, 2, 'CAPS', 'K_A', new TextEncoder().encode('Â'))] + ], + + [ + ['../data/tests-xkb-kmn/Test_C3_several.keylayout'], + [new Rule("C3", 'NCAPS RALT', 'K_8', 3, 1, 'CAPS', 'K_U', 1, 3, 'NCAPS', 'K_A', new TextEncoder().encode('â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 3, 0, 'CAPS', 'K_U', 1, 0, 'NCAPS RALT', 'K_A', new TextEncoder().encode('â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 3, 0, 'NCAPS RALT', 'K_U', 2, 2, 'NCAPS', 'K_A', new TextEncoder().encode('â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 3, 0, 'NCAPS RALT', 'K_U', 2, 0, 'NCAPS RALT', 'K_A', new TextEncoder().encode('â'))] + ], + [ + ['../data/tests-xkb-kmn/Test_C0_C1_C2_C3.keylayout'], + [new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_A', new TextEncoder().encode('A')), + new Rule("C2", '', '', 0, 0, 'NCAPS RALT', 'K_EQUAL', 1, 1, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_S', new TextEncoder().encode('S')), + new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'NCAPS RALT', 'K_U', new TextEncoder().encode('S')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 1, 'CAPS', 'K_S', 2, 6, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'CAPS', 'K_U', 3, 3, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'NCAPS RALT', 'K_S', 4, 4, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'NCAPS RALT', 'K_U', 5, 5, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_S', new TextEncoder().encode('S')), + new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'NCAPS RALT', 'K_U', new TextEncoder().encode('S')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'CAPS', 'K_S', 2, 0, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'CAPS', 'K_U', 3, 0, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'NCAPS RALT', 'K_S', 4, 0, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C3", 'NCAPS RALT', 'K_8', 6, 0, 'NCAPS RALT', 'K_U', 5, 0, 'CAPS', 'K_D', new TextEncoder().encode('Â')), + new Rule("C1", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_U', new TextEncoder().encode('U')),] + ], + ].forEach(function (values: any) { + it('data of \'' + values[0] + "' passed into createRuleData() " + 'should create an array of rules', async function () { + const inputFilename = makePathToFixture(values[0][0]); + const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + const processedData = sut.convertBound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); + assert.deepEqual(processedData.rules[0], values[1][0]); + }); }); }); - }); - */ + */ }); From 95dfd1d4fb40fa5b62d74e3717544b4505564c95 Mon Sep 17 00:00:00 2001 From: Sabine Date: Mon, 18 May 2026 07:46:43 +0200 Subject: [PATCH 251/251] feat (developer): kmc-convert edit tests --- .../kmc-convert-read/kmn-file-reader.tests.ts | 180 +++++++++++++++++- 1 file changed, 178 insertions(+), 2 deletions(-) diff --git a/developer/src/kmc-convert/test/kmc-convert-read/kmn-file-reader.tests.ts b/developer/src/kmc-convert/test/kmc-convert-read/kmn-file-reader.tests.ts index ad7ef9fc6b3..59dfb9c59ee 100644 --- a/developer/src/kmc-convert/test/kmc-convert-read/kmn-file-reader.tests.ts +++ b/developer/src/kmc-convert/test/kmc-convert-read/kmn-file-reader.tests.ts @@ -10,7 +10,11 @@ import 'mocha'; import { assert } from 'chai'; import { compilerTestCallbacks, makePathToFixture } from './../helpers/index.js'; -import { KeylayoutFileReader } from '../../src//kmc-convert-read/keylayout-file-reader.js'; +import { KeylayoutFileReader } from '../../src/kmc-convert-read/keylayout-file-reader.js'; + +import { Keylayout } from "@keymanapp/developer-utils"; +import { KL_KeyMapSelect } from "../../../common/web/utils/src/types/keylayout/keylayout-xml.js"; +import { KL_KeyMap } from "../../../common/web/utils/src/types/keylayout/keylayout-xml.js"; describe('KeylayoutFileReader', function () { @@ -49,4 +53,176 @@ describe('KeylayoutFileReader', function () { }); }); -});*/ + describe("validate() ", function () { + + it('validate() should return true on correct inputfile', async function () { + const sutR = new KeylayoutFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/tests-keylayout-kmn/Test.keylayout'); + const result: Keylayout.KeylayoutXMLSourceFile | null = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + const validated = sutR.validate(result as Keylayout.KeylayoutXMLSourceFile, inputFilename); + assert.isTrue(validated); + }); + + it('validate() should return false on inputfile with unknown tags', async function () { + const sutR = new KeylayoutFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/tests-keylayout-kmn/Test_unknownTags.keylayout'); + const result: Keylayout.KeylayoutXMLSourceFile | null = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + const validated = sutR.validate(result as Keylayout.KeylayoutXMLSourceFile, inputFilename); + assert.isFalse(validated); + }); + + it('validate() should return false on inputfile with additional tags', async function () { + const sutR = new KeylayoutFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/tests-keylayout-kmn/Test_additionalTags.keylayout'); + const result: Keylayout.KeylayoutXMLSourceFile | null = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + const validated = sutR.validate(result as Keylayout.KeylayoutXMLSourceFile, inputFilename); + assert.isFalse(validated); + }); + it('validate() should return false on inputfile with missing tags', async function () { + const sutR = new KeylayoutFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/tests-keylayout-kmn/Test_missingTags.keylayout'); + const result: Keylayout.KeylayoutXMLSourceFile | null = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + const validated = sutR.validate(result as Keylayout.KeylayoutXMLSourceFile, inputFilename); + assert.isFalse(validated); + }); + it('validate() should return false on no entries in action-when', async function () { + const sutR = new KeylayoutFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/tests-keylayout-kmn/Test_noActionWhen.keylayout'); + const result: Keylayout.KeylayoutXMLSourceFile | null = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + const validated = sutR.validate(result as Keylayout.KeylayoutXMLSourceFile, inputFilename); + assert.isFalse(validated); + }); + /* it('validate() should return false on null as input', async function () { + const sutR = new KeylayoutFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/tests-keylayout-kmn/Test_noActionWhen.keylayout'); + //const result: Keylayout.KeylayoutXMLSourceFile | null = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + const validated = sutR.validate(null, inputFilename); + assert.isFalse(validated); + }); + it('validate() should return false on undefined as input', async function () { + const sutR = new KeylayoutFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/tests-keylayout-kmn/Test_noActionWhen.keylayout'); + //const result: Keylayout.KeylayoutXMLSourceFile | null = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + const validated = sutR.validate(undefined, inputFilename); + assert.isFalse(validated); + }); + }); + + describe("read() ", function () { + const sutR = new KeylayoutFileReader(compilerTestCallbacks); + + it('read() should return filled array on correct input', async function () { + + const inputFilename = makePathToFixture('../data/tests-keylayout-kmn/tests-keylayout-kmn/Test.keylayout'); + + const result = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + assert.isNotEmpty(result); + }); + + it('read() should return empty array on empty input', async function () { + const result = sutR.read(compilerTestCallbacks.loadFile("")); + assert.isNull(result); + }); + + it('read() should return empty array on space as input', async function () { + const result = sutR.read(compilerTestCallbacks.loadFile(" ")); + assert.isNull(result); + }); + + it('read() should return empty array on unavailable file name', async function () { + const inputFilenameUnavailable = makePathToFixture('../data/tests-keylayout-kmn/tests-keylayout-kmn/X.keylayout'); + const result = sutR.read(compilerTestCallbacks.loadFile(inputFilenameUnavailable)); + assert.isNull(result); + }); + + it('read() should return empty array on typo in path', async function () { + const result = sutR.read(compilerTestCallbacks.loadFile(makePathToFixture('../data|Test.keylayout'))); + assert.isNull(result); + }); + }); + + describe('findMapIndexinKeymap ', function () { + const keyMapSelect: KL_KeyMapSelect = { + mapIndex: '', + modifier: [] + }; + + keyMapSelect.modifier.push({ keys: 'caps' }); + keyMapSelect.modifier.push({ keys: 'rightOption' }); + keyMapSelect.modifier.push({ keys: 'rightShift caps' }); + + const sutR = new KeylayoutFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/tests-keylayout-kmn/tests-keylayout-kmn/Test.keylayout'); + const jsonO: Keylayout.KeylayoutXMLSourceFile | null = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + [ + ['0', true], + ['7', true], + ['999', false], + ['A', false], + [123, false], + ['', false], + [null, false], + [undefined, false], + ].forEach(function (values) { + it(("findMapIndexinKeymap(keyMapSelect.mapIndex = '" + values[0] + "')").padEnd(40, " ") + "should return " + "'" + values[1] + "'", async function () { + keyMapSelect.mapIndex = values[0] as string; + const result = sutR.findMapIndexinKeymap(jsonO as Keylayout.KeylayoutXMLSourceFile, keyMapSelect); + assert.isTrue(result === values[1]); + }); + }); + }); + + describe('findIndexinKeymapSelect ', function () { + const keyMap: KL_KeyMap = { + index: '', + key: [] + }; + keyMap.key.push({ code: '0', output: 'A' }); + keyMap.key.push({ code: '1', action: 'S' }); + keyMap.key.push({ code: '2', output: 'D' }); + + const sutR = new KeylayoutFileReader(compilerTestCallbacks); + const inputFilename = makePathToFixture('../data/tests-keylayout-kmn/Test.keylayout'); + const jsonO: Keylayout.KeylayoutXMLSourceFile | null = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + [ + ['0', true], + ['7', true], + ['999', false], + ['A', false], + [123, false], + ['', false], + [null, false], + [undefined, false], + ].forEach(function (values) { + it(("findIndexinKeymapSelect(keyMap.index = '" + values[0] + "')").padEnd(40, " ") + "should return " + "'" + values[1] + "'", async function () { + keyMap.index = values[0] as string; + const result = sutR.findIndexinKeymapSelect(jsonO as Keylayout.KeylayoutXMLSourceFile, keyMap); + assert.isTrue(result === values[1]); + }); + }); + }); + + describe('checkForCorrespondingElements ', function () { + const sutR = new KeylayoutFileReader(compilerTestCallbacks); + [ + ['../data/tests-keylayout-kmn/Test.keylayout', true], + ['../data/tests-keylayout-kmn/Test_sameKeyMapAndKeyMapselectAndJisERROR.keylayout', true], + ['../data/tests-keylayout-kmn/Test_moreKeymapSelectThanKeymapERROR.keylayout', false], + ['../data/tests-keylayout-kmn/Test_moreKeyMapThanKeyMapselectERROR.keylayout', false], + ['../data/tests-keylayout-kmn/Test_moreKeyMapThanKeyMapselectAndJisERROR.keylayout', false], + ].forEach(function (values) { + it(("checkForCorrespondingElements in " + values[0] ).padEnd(40, " ") + "should return " + "'" + values[1] + "'", async function () { + const jsonO: Keylayout.KeylayoutXMLSourceFile | null = sutR.read(compilerTestCallbacks.loadFile(makePathToFixture(values[0] as string))); + const result = sutR.checkForCorrespondingElements(jsonO as Keylayout.KeylayoutXMLSourceFile); + assert.isTrue(result === values[1]); + }); + }); + }); + + + + + +}); + +*/