diff --git a/developer/src/kmc-convert/src/converter-messages.ts b/developer/src/kmc-convert/src/converter-messages.ts index 2453d00851..d062652f7f 100644 --- a/developer/src/kmc-convert/src/converter-messages.ts +++ b/developer/src/kmc-convert/src/converter-messages.ts @@ -18,9 +18,9 @@ const SevError = CompilerErrorSeverity.Error | Namespace; export class ConverterMessages { static ERROR_FileNotFound = SevError | 0x0003; - static Error_FileNotFound = (o: { inputFilename: string; }) => m( + static Error_FileNotFound = (o?: { inputFilename: string | null; }) => m( this.ERROR_FileNotFound, - `Input filename '${def(o.inputFilename)}' does not exist or could not be loaded.` + `Input filename '${def(o?.inputFilename)}' does not exist or could not be loaded.` ); static ERROR_InvalidFile = SevError | 0x0004; diff --git a/developer/src/kmc-convert/src/converter.ts b/developer/src/kmc-convert/src/converter.ts index f60e2c285e..bdb841438c 100644 --- a/developer/src/kmc-convert/src/converter.ts +++ b/developer/src/kmc-convert/src/converter.ts @@ -68,9 +68,9 @@ export class Converter implements KeymanCompiler { return null; } - const ConverterClass = ConverterClassFactory.find(inputFilename, outputFilename); + const ConverterClass = ConverterClassFactory.find(inputFilename, outputFilename ?? '.kmn'); if (!ConverterClass) { - this.callbacks.reportMessage(ConverterMessages.Error_NoConverterFound({ inputFilename, outputFilename })); + this.callbacks.reportMessage(ConverterMessages.Error_NoConverterFound({ inputFilename, outputFilename: outputFilename ?? '' })); 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 21c6dd5bee..d35e32de56 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 @@ -17,9 +17,10 @@ export class KeylayoutFileReader { constructor(private callbacks: CompilerCallbacks /*,private options: CompilerOptions*/) { }; - /** - * @brief helper function to find a specific keyMap index in a keyMapSet + * @brief Helper function to check if a specific keyMap index exists in a keyMapSet. + * This is neccessary because the amount of must correspond to + * the amount of . * @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 @@ -36,7 +37,9 @@ export class KeylayoutFileReader { } /** - * @brief helper function to find a specific keyMapSelect index in a modifierMap + * @brief Helper function to check if a specific keyMapSelect index exists in a modifierMap. + * This is neccessary because the amount of must correspond to + * the amount of . * @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 @@ -53,8 +56,8 @@ export class KeylayoutFileReader { } /** - * @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) + * @brief member function checking if all keyMapSelect elements have exact one corresponding keyMap element (per keyMapSet) + * 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 @@ -82,6 +85,10 @@ export class KeylayoutFileReader { * @returns true if valid, false if invalid */ public validate(source: Keylayout.KeylayoutXMLSourceFile, inputFilename: string): boolean { + if (!source) { + this.callbacks.reportMessage(ConverterMessages.Error_UnableToReadFile({ inputFilename: inputFilename })); + return false; + } if (!SchemaValidators.default.keylayout(source)) { for (const err of (SchemaValidators.default.keylayout).errors) { this.callbacks.reportMessage(DeveloperUtilsMessages.Error_InvalidXml({ @@ -148,7 +155,7 @@ 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 */ - public read(source: Uint8Array): Keylayout.KeylayoutXMLSourceFile { + public read(source: Uint8Array): Keylayout.KeylayoutXMLSourceFile | null { try { const data = new TextDecoder().decode(source); 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 8d76b2c3f1..cc7157c9f4 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,7 +109,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) { throw new Error('Input filename is required'); @@ -118,7 +118,7 @@ export class KeylayoutToKmnConverter { const KeylayoutReader = new KeylayoutFileReader(this.callbacks/*, this.options*/); const binaryData = this.callbacks.loadFile(inputFilename); - const jsonO: Keylayout.KeylayoutXMLSourceFile = KeylayoutReader.read(binaryData); + const jsonO: Keylayout.KeylayoutXMLSourceFile | null = KeylayoutReader.read(binaryData); if (!jsonO) { this.callbacks.reportMessage(ConverterMessages.Error_UnableToReadFile({ inputFilename: inputFilename })); @@ -128,7 +128,7 @@ export class KeylayoutToKmnConverter { if (!KeylayoutReader.validate(jsonO, inputFilename)) { return null; } - } catch (e) { + } catch (e: any) { this.callbacks.reportMessage(ConverterMessages.Error_InvalidFile({ errorText: e.toString() })); return null; } @@ -137,10 +137,16 @@ export class KeylayoutToKmnConverter { const kmnFileWriter = new KmnFileWriter(this.callbacks, this.options); // write to object/ConverterToKmnResult - const outputKmn = kmnFileWriter.write(processedData); + const outputKmn = processedData ? kmnFileWriter.write(processedData) : null; + + if (!processedData || !outputKmn) { + return null; + } const result: ConverterToKmnResult = { artifacts: { - kmn: { data: outputKmn, filename: processedData.kmnFilename } + kmn: { + data: outputKmn, filename: processedData.kmnFilename + } } }; return result; @@ -151,7 +157,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: Keylayout.KeylayoutXMLSourceFile, inputfilename: string, outputFilename?: string): ProcessedData { + private convert(jsonObj: Keylayout.KeylayoutXMLSourceFile, inputfilename: string, outputFilename?: string): ProcessedData | null { // modifiers for each behavior const modifierBehavior: string[][] = []; @@ -197,7 +203,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: Keylayout.KeylayoutXMLSourceFile): ProcessedData { + public createRuleData(dataUkelele: ProcessedData, jsonObj: Keylayout.KeylayoutXMLSourceFile): ProcessedData | null { const rules: Rule[] = []; let dkCounterC3: number = 0; @@ -228,7 +234,7 @@ 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) { // loop modifiers for (let l = 0; l < dataUkelele.modifiers[i].length; l++) { @@ -292,8 +298,8 @@ export class KeylayoutToKmnConverter { /* dk for C2*/ 0, /* unique B */ 0, - /* modifierKey*/ b1ModifierKeyObj[m].modifier, - /* key */ b1ModifierKeyObj[m].key, + /* modifierKey*/ b1ModifierKeyObj[m].modifier ?? "", + /* key */ b1ModifierKeyObj[m].key ?? "", /* output */ new TextEncoder().encode(outputchar) ); if ((outputchar !== undefined) && (outputchar !== "undefined") && (outputchar !== "")) { @@ -338,7 +344,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) as string[][]; // ........................................................................................................................................................................................ @@ -372,8 +378,8 @@ export class KeylayoutToKmnConverter { /* dk for C2*/ dkCounterC2++, /* unique B */ 0, - /* modifierKey*/ b1ModifierKeyObj[n4].modifier, - /* key */ b1ModifierKeyObj[n4].key, + /* modifierKey*/ b1ModifierKeyObj[n4].modifier ?? "", + /* key */ b1ModifierKeyObj[n4].key ?? "", /* output */ new TextEncoder().encode(b1ModifierKeyObj[n4].outchar), ); if ((b1ModifierKeyObj[n4].outchar !== undefined) @@ -402,21 +408,22 @@ 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) { + for (const when of jsonObj.keyboard.actions.action[b1ActionIndex].when) { + if ((when['state'] !== "none") + && (when['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 = when['state'] as string; + /* e.g. next = 1 */ const b5ValueNext: string = when['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); + /* e.g. [ [ 'anyOption', 'Caps' ] ]*/ const b4DeadkeyModifierObj: string[][] = this.getModifierArrayFromKeyModifierArray(dataUkelele.modifiers, b4DeadkeyObj) as string[][]; // ........................................................................................................................................................................................... // Data of Block Nr 3 ........................................................................................................................................................................ @@ -428,7 +435,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) as string[][]; // ........................................................................................................................................................................................... // 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 ) ......................................... @@ -439,17 +446,17 @@ 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++) { - 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++) { + 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( + ruleObj = new Rule( /* ruleType */ "C3", /* modifierPrevDeadkey*/ this.createKmnModifier(b2PrevDeadkeyModifierObj[n1][n2], isCapsused), /* prevDeadkey */ this.mapUkeleleKeycodeToVK(Number(b2PrevDeadkeyObj[n3].key)), @@ -461,14 +468,15 @@ export class KeylayoutToKmnConverter { /* dk for C2*/ 0, /* unique B */ 0, - /* modifierKey*/ b1ModifierKeyObj[n7].modifier, - /* key */ b1ModifierKeyObj[n7].key, + /* 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); + ); + if ((b1ModifierKeyObj[n7].outchar !== undefined) + && (b1ModifierKeyObj[n7].outchar !== "undefined") + && (b1ModifierKeyObj[n7].outchar !== "")) { + rules.push(ruleObj); + } } } } @@ -930,6 +938,7 @@ export class KeylayoutToKmnConverter { * @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))) { @@ -948,7 +957,7 @@ export class KeylayoutToKmnConverter { } } // remove duplicates - const uniquekeyBehaviorModOutput = keyBehaviorModOutput.reduce((unique, o) => { + const uniquekeyBehaviorModOutput = keyBehaviorModOutput.reduce((unique, o) => { if (!unique.some(obj => obj.actionId === o.actionId && obj.key === o.key && @@ -999,7 +1008,7 @@ export class KeylayoutToKmnConverter { //............................................................................. // remove duplicates - const uniqueactionOutputBehaviorKey = actionOutputBehaviorKeyModi.reduce((unique, o) => { + const uniqueactionOutputBehaviorKey = actionOutputBehaviorKeyModi.reduce((unique, o) => { if (!unique.some(obj => obj.outchar === o.outchar && obj.actionId === o.actionId && 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 7eb4d14768..6c9679d019 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,66 +9,49 @@ import { CompilerCallbacks, CompilerOptions } from "@keymanapp/developer-utils"; import { KeylayoutToKmnConverter, ProcessedData, Rule } from './keylayout-to-kmn-converter.js'; -import { ConverterMessages } from '../converter-messages.js'; import KEYMAN_VERSION from "@keymanapp/keyman-version"; interface MessageCharacter { message: string; character: string; }; -// Todo-kmc-convert edit interface -interface RuleReview { - warningMessage_0: string; - warningMessages_1: string; - warningMessages_2: string; - hasWarning_0: boolean; - hasWarning_1: boolean; - hasWarning_2: boolean; - warningMessages: string[]; - type: 'RuleReview'; +interface RuleReview { + warningMessages: string[]; + extraWarning: string; + type: 'RuleReview' | 'UnavailableModifier' | 'UnavailableSuperiorRule' | + 'DuplicateRule' | 'AmbiguousRule' | 'WarningTextSet'; + compare_type: string; isEarlier: boolean; - isused: boolean; - context: string; - prevDK_modifier: string; - prevDK_key: string; - DK_modifier: string; - DK_key: string; + // dk_id[0]: prev_dk; dk_id[1]: dk; + dk_id: [number, number]; + // dk_prefix[0]: prev_dk_prefix; dk_prefix[1]: dk_prefix; + dk_prefix: [string, string]; + prevDk_modifier: string; + prevDk_key: string; + Dk_modifier: string; + Dk_key: string; modifier: string; key: string; output: string; - }; -//interface UnavailableModifier /*extends RuleReview*/ { -/*interface UnavailableModifier { + +interface UnavailableModifier extends RuleReview { type: 'UnavailableModifier'; - isEarlier: boolean; - isused: boolean; - context: string; - prevDK_modifier: string; - prevDK_key: string; - DK_modifier: string; - DK_key: string; - modifier: string; - key: string; - output: string; - warningMessage: string[]; -};*/ -interface RuleReview { - type: 'RuleReview'; - isEarlier: boolean; - isused: boolean; - context: string; - prevDK_modifier: string; - prevDK_key: string; - DK_modifier: string; - DK_key: string; - modifier: string; - key: string; - output: string; - - warningMessages: string[]; }; +interface UnavailableSuperiorRule extends RuleReview { + type: 'UnavailableSuperiorRule'; +}; +interface DuplicateRules extends RuleReview { + type: 'DuplicateRule'; +}; +interface AmbiguousRules extends RuleReview { + type: 'AmbiguousRule'; +}; +interface WarningTextSet extends RuleReview { + type: 'WarningTextSet'; +}; + export class KmnFileWriter { constructor(private callbacks: CompilerCallbacks, private options: CompilerOptions) { }; @@ -90,12 +73,7 @@ export class KmnFileWriter { 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; - } + return new TextEncoder().encode(data); } /** @@ -103,7 +81,10 @@ export class KmnFileWriter { * @param dataUkelele an object containing all data read from a .keylayout file * @return string - all stores to be printed */ - public writeKmnFileHeader(dataUkelele: ProcessedData): string { + public writeKmnFileHeader(dataUkelele: ProcessedData | null): string { + if (!dataUkelele) { + return ""; + } let data: string = ""; @@ -130,8 +111,10 @@ export class KmnFileWriter { * @param dataUkelele an object containing all data read from a .keylayout file * @return string - all rules to be printed */ - public writeDataRules(dataUkelele: ProcessedData): string { - + public writeDataRules(dataUkelele: ProcessedData | null): string { + if (!dataUkelele) { + return ""; + } const keylayoutKmnConverter = new KeylayoutToKmnConverter(this.callbacks, this.options); let data: string = ""; @@ -165,7 +148,7 @@ export class KmnFileWriter { unique.push(o); } return unique; - }, []); + }, [] as Rule[]); //................................................ C0 C1 ................................................................ @@ -194,15 +177,19 @@ export class KmnFileWriter { // 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 - const warnText = this.reviewRules(uniqueDataRules, k); + const warnText = this.reviewRules(uniqueDataRules, k).warningMessages; const outputCharacter = new TextDecoder().decode(uniqueDataRules[k].output); // 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); + let versionOutputCharacter; const characterMessage = this.writeCharacterOrUnicode(outputCharacter, warnText[2]); - const versionOutputCharacter = characterMessage.character; - warnText[2] = characterMessage.message; + if (characterMessage !== null) { + 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 @@ -255,15 +242,19 @@ export class KmnFileWriter { // 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 - const warnText = this.reviewRules(uniqueDataRules, k); + const warnText = this.reviewRules(uniqueDataRules, k).warningMessages; + let versionOutputCharacter; const outputCharacter = new TextDecoder().decode(uniqueDataRules[k].output); // 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); + const characterMessage = this.writeCharacterOrUnicode(outputCharacter, warnText[2]); - const versionOutputCharacter = characterMessage.character; - warnText[2] = characterMessage.message; + if (characterMessage !== null) { + 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 @@ -339,12 +330,16 @@ export class KmnFileWriter { // 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 - const warnText = this.reviewRules(uniqueDataRules, k); + const warnText = this.reviewRules(uniqueDataRules, k).warningMessages; const outputCharacter = new TextDecoder().decode(uniqueDataRules[k].output); // TODO-kmc-convert: after merge of PR 14569 use functions from util instead of the ones in this class + let versionOutputCharacter; const characterMessage = this.writeCharacterOrUnicode(outputCharacter, warnText[2]); - const versionOutputCharacter = characterMessage.character; - warnText[2] = characterMessage.message; + if (characterMessage !== null) { + 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 @@ -416,12 +411,9 @@ export class KmnFileWriter { + "] > " + versionOutputCharacter + "\n"; - } - } } - if ((warnText[0].indexOf("duplicate") < 0) || (warnText[1].indexOf("duplicate") < 0) || (warnText[2].indexOf("duplicate") < 0)) { data += "\n"; } @@ -430,6 +422,147 @@ export class KmnFileWriter { return data; } + /** + * @brief take a child object of RuleReview and return the appropriate warning message array + * @param inObj : an object containing filtered data for a specified comparison + * @param posWarning : index specifying to which element of the warning message array a warning message will be added: + * outMsg[0]: Warning for part 1 of a rule (e.g. modifier_prev_dk + key_prev_dk > prev_dk) + * outMsg[1]: Warning for part 2 of a rule (e.g. (prev_dk +) modifier_dk + key_dk > dk) + * outMsg[2]: Warning for part 3 of a rule (e.g. (dk +) modifier+key > output) + * see here on parts of a rule: + * https://docs.google.com/document/d/12J3NGO6RxIthCpZDTR8FYSRjiMgXJDLwPY2z9xqKzJ0/edit?tab=t.0#heading=h.16sx096j6jmy + * @return outMsg the warning message array for all parts + */ + public createWarningText(inObj: RuleReview, posWarning: number = 2): string[] { + + const outMsg = [...inObj.warningMessages]; + + if (inObj.compare_type === 'unav_C0_C1') { + outMsg[posWarning] = 'unavailable modifier '; + } + + if (inObj.compare_type === 'unav_C2') { + // if the dk is unavailable, the modifiers of the dependant C0 rule will get a warning 'unavailable superior rule ' + if (inObj.Dk_modifier) { + outMsg[1] = 'unavailable modifier '; + outMsg[2] = 'unavailable superior rule ( [' + + inObj.Dk_modifier + ' ' + + inObj.Dk_key + + '] > dk(' + + inObj.dk_prefix[1] + + inObj.dk_id[1] + + ') ) : '; + } + + if (inObj.modifier) { + outMsg[2] = 'unavailable modifier '; + } + } + + if (inObj.compare_type === 'unav_C3') { + + // if the dk is unavailable, the modifiers of the dependant C0 rule will get a warning 'unavailable superior rule ' + if (inObj.prevDk_modifier) { + outMsg[0] = 'unavailable modifier '; + outMsg[1] = 'unavailable superior rule ( [' + + inObj.prevDk_modifier + ' ' + + inObj.prevDk_key + + '] > dk(' + + inObj.dk_prefix[0] + + inObj.dk_id[0] + + ') ) : '; + } + + + // if the dk is unavailable, the modifiers of the dependant C0 rule will get a warning 'unavailable superior rule ' + if (inObj.Dk_modifier) { + outMsg[1] += 'unavailable modifier '; + outMsg[2] = 'unavailable superior rule ( [' + + inObj.Dk_modifier + ' ' + + inObj.Dk_key + + '] > dk(' + + inObj.dk_prefix[1] + + inObj.dk_id[1] + + ') ) : '; + } + + if (inObj.modifier) { + outMsg[2] = 'unavailable modifier '; + } + } + + if (inObj.compare_type === 'amb_1_1' || inObj.compare_type === 'dup_1_1') { + + outMsg[posWarning] = inObj.warningMessages[posWarning] + + ((inObj.type === 'AmbiguousRule') ? 'ambiguous ' : 'duplicate ') + 'rule: ' + + (inObj.isEarlier ? 'earlier' : 'later') + + ': [' + inObj.modifier + ' ' + inObj.key + '] > \'' + + inObj.output + '\' '; + } + + + if (inObj.compare_type === 'amb_2_2' || inObj.compare_type === 'dup_2_2' + || inObj.compare_type === 'amb_2_1' + || inObj.compare_type === 'amb_2_4') { + + const textsegment = ( + ((inObj.type === 'AmbiguousRule') ? 'ambiguous ' : 'duplicate ') + 'rule: ' + + (inObj.isEarlier ? 'earlier' : 'later') + + ': [' + inObj.Dk_modifier + ' ' + inObj.Dk_key + '] > dk(' + + inObj.dk_prefix[1] + inObj.dk_id[1] + ') '); + + if (outMsg[posWarning].indexOf(textsegment) === -1) + outMsg[posWarning] += textsegment; + } + + + if (inObj.compare_type === 'amb_4_4' || inObj.compare_type === 'dup_4_4' + || inObj.compare_type === 'amb_4_1' + || inObj.compare_type === 'amb_4_2') { + + const textsegment = ( + ((inObj.type === 'AmbiguousRule') ? 'ambiguous ' : 'duplicate ') + 'rule: ' + + (inObj.isEarlier ? 'earlier' : 'later') + + ': [' + inObj.prevDk_modifier + ' ' + inObj.prevDk_key + '] > dk(' + + inObj.dk_prefix[0] + inObj.dk_id[0] + ') '); + + if (outMsg[posWarning].indexOf(textsegment) === -1) + outMsg[posWarning] += textsegment; + } + + + if (inObj.compare_type === 'amb_5_5' || inObj.compare_type === 'dup_5_5') { + + const textsegment = ( + ((inObj.type === 'AmbiguousRule') ? 'ambiguous ' : 'duplicate ') + 'rule: ' + + (inObj.isEarlier ? 'earlier' : 'later') + + ': dk(' + inObj.dk_prefix[0] + inObj.dk_id[0] + ") + [" + + inObj.Dk_modifier + " " + inObj.Dk_key + "] > " + + 'dk(' + inObj.dk_prefix[1] + inObj.dk_id[1] + ") "); + + if (outMsg[1].indexOf(textsegment) === -1) + outMsg[1] += textsegment; + } + + + if (inObj.compare_type === 'amb_6_3' || inObj.compare_type === 'dup_6_3' + || inObj.compare_type === 'amb_3_3' || inObj.compare_type === 'dup_3_3' + || inObj.compare_type === 'amb_6_6' || inObj.compare_type === 'dup_6_6') { + + const textsegment = ( + ((inObj.type === 'AmbiguousRule') ? 'ambiguous ' : 'duplicate ') + 'rule: ' + + (inObj.isEarlier ? 'earlier' : 'later') + + ': dk(' + inObj.dk_prefix[1] + inObj.dk_id[1] + ") + [" + + inObj.modifier + " " + inObj.key + "] > \'" + + inObj.output + "\' "); + + if (outMsg[posWarning].indexOf(textsegment) === -1) + outMsg[posWarning] += textsegment; + } + + return outMsg; + } + /** * @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. @@ -439,285 +572,95 @@ export class KmnFileWriter { * @param index the index of a rule in Rule[] * @return a string[] containing possible warnings for a rule */ + public reviewRules(rule: Rule[], index: number): RuleReview { - public reviewRules(rule: Rule[], index: number): string[] { - - const resultWarnings: RuleReview = { - - warningMessage_0: '', - warningMessages_1: '', - warningMessages_2: '', - hasWarning_0: false, - hasWarning_1: false, - hasWarning_2: false, - - type: 'RuleReview', - isused: false, - isEarlier: false, - context: '', - prevDK_modifier: '', - prevDK_key: '', - DK_modifier: '', - DK_key: '', - modifier: '', - key: '', - output: '', + const unavailableModiWarnings = { + type: 'UnavailableModifier', warningMessages: ['', '', ''], - }; - - /* const resultWarnings: UnavailableModifier = { - type: 'UnavailableModifier', - isused: false, - isEarlier: false, - context: '', - prevDK_modifier: '', - prevDK_key: '', - DK_modifier: '', - DK_key: '', - modifier: '', - key: '', - output: '', - warningMessage: Array(3).fill("") - };*/ - /*const resultAll: RuleReview = { - type: 'RuleReview', - isused: false, - isEarlier: false, - context: '', - prevDK_modifier: '', - prevDK_key: '', - DK_modifier: '', - DK_key: '', - modifier: '', - key: '', output: '', - warningMessage: Array(3).fill("") - };*/ + } as UnavailableModifier; - /* - resultWarnings.type = ''; - resultWarnings.isused = true; - resultWarnings.prevDK_key = rule[index].prevDeadkey; - resultWarnings.prevDK_modifier = rule[index].modifierPrevDeadkey; - resultWarnings.DK_modifier = rule[index].modifierDeadkey; - resultWarnings.DK_key = rule[index].deadkey; - resultWarnings.modifier = rule[index].modifierKey; - resultWarnings.key = rule[index].key; - resultWarnings.output = new TextDecoder().decode(rule[index].output); - resultWarnings.warningMessage[0] = ""; - resultWarnings.warningMessage[1] = ""; - resultWarnings.warningMessage[2] = ""; - */ + const unavailableSuperiWarnings = { + type: 'UnavailableSuperiorRule', + warningMessages: ['', '', ''], + output: '', + } as UnavailableSuperiorRule; + + const duplicateWarnings = { + type: 'DuplicateRule', + warningMessages: ['', '', ''], + output: '', + } as DuplicateRules; + + const ambiguousWarnings = { + type: 'AmbiguousRule', + warningMessages: ['', '', ''], + output: '', + } as AmbiguousRules; + + const resultWarningTextSet = { + warningMessages: ['', '', ''], + } as WarningTextSet; const keylayoutKmnConverter = new KeylayoutToKmnConverter(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 : "; - // resultWarnings.warningMessages[2] = "unavailable modifier : "; - resultWarnings.hasWarning_2 = true; - - resultWarnings.type = 'RuleReview'; - resultWarnings.isused = true; - resultWarnings.modifier = rule[index].modifierKey; - resultWarnings.key = rule[index].key; - resultWarnings.output = new TextDecoder().decode(rule[index].output); - resultWarnings.warningMessages[2] = "unavailable modifier : "; + unavailableModiWarnings.compare_type = 'unav_C0_C1'; + unavailableModiWarnings.warningMessages = this.createWarningText(unavailableModiWarnings); } } + 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 - + ") ) : "; - - /* resultWarnings.warningMessages[1] = "unavailable modifier : "; - resultWarnings.hasWarning_1 = true; - resultWarnings.warningMessages[2] = "unavailable superior rule ( [" - + rule[index].modifierDeadkey + " " - + rule[index].deadkey - + "] > dk(A" - + rule[index].idDeadkey - + ") ) : "; - resultWarnings.hasWarning_2 = true;*/ - - - resultWarnings.type = 'RuleReview'; - resultWarnings.isused = true; - resultWarnings.DK_modifier = rule[index].modifierDeadkey; - resultWarnings.DK_key = rule[index].deadkey; - resultWarnings.modifier = rule[index].modifierKey; - resultWarnings.key = rule[index].key; - resultWarnings.output = new TextDecoder().decode(rule[index].output); - resultWarnings.warningMessages[1] = "unavailable modifier : "; - resultWarnings.warningMessages[2] = "unavailable superior rule ( [" - + rule[index].modifierDeadkey + " " - + rule[index].deadkey - + "] > dk(A" - + rule[index].idDeadkey - + ") ) : "; + unavailableSuperiWarnings.compare_type = 'unav_C2'; + unavailableSuperiWarnings.dk_prefix = ['C', 'A']; + unavailableSuperiWarnings.dk_id = [rule[index].idPrevDeadkey, rule[index].idDeadkey]; + unavailableSuperiWarnings.Dk_modifier = rule[index].modifierDeadkey; + unavailableSuperiWarnings.Dk_key = rule[index].deadkey; + unavailableSuperiWarnings.warningMessages = this.createWarningText(unavailableSuperiWarnings); } if (!keylayoutKmnConverter.isAcceptableKeymanModifier(rule[index].modifierKey)) { - warningText[2] = "unavailable modifier : "; - - /* resultWarnings.warningMessages[2] = "unavailable modifier : "; - resultWarnings.hasWarning_2 = true;*/ - - resultWarnings.type = 'RuleReview'; - resultWarnings.isused = true; - resultWarnings.prevDK_key = rule[index].prevDeadkey; - resultWarnings.prevDK_modifier = rule[index].modifierPrevDeadkey; - resultWarnings.DK_modifier = rule[index].modifierDeadkey; - resultWarnings.DK_key = rule[index].deadkey; - resultWarnings.modifier = rule[index].modifierKey; - resultWarnings.key = rule[index].key; - resultWarnings.output = new TextDecoder().decode(rule[index].output); - resultWarnings.warningMessages[2] = "unavailable modifier : "; + unavailableModiWarnings.compare_type = 'unav_C2'; + unavailableModiWarnings.modifier = rule[index].modifierKey; + unavailableModiWarnings.key = rule[index].key; + unavailableModiWarnings.warningMessages = this.createWarningText(unavailableModiWarnings); } } + 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 - + ") ) : "; - warningText[2] = "unavailable superior rules ( [" - + rule[index].modifierPrevDeadkey + " " - + rule[index].prevDeadkey - + "] > dk(A" - + rule[index].idPrevDeadkey - + ") ) and ( dk(A" + - + rule[index].idPrevDeadkey + ") [" - + rule[index].modifierDeadkey + " " - + rule[index].deadkey - + "] > dk(B" - + rule[index].idDeadkey - + ") ) : "; - /* resultWarnings.warningMessages[0] = "unavailable modifier : "; - resultWarnings.hasWarning_0 = true; - - resultWarnings.warningMessages[1] = "unavailable superior rule ( [" - + rule[index].modifierPrevDeadkey + " " - + rule[index].prevDeadkey - + "] > dk(A" - + rule[index].idPrevDeadkey - + ") ) : "; - resultWarnings.hasWarning_1 = true; - resultWarnings.warningMessages[2] = "unavailable superior rules ( [" - + rule[index].modifierPrevDeadkey + " " - + rule[index].prevDeadkey - + "] > dk(A" - + rule[index].idPrevDeadkey - + ") ) and ( dk(A" + - + rule[index].idPrevDeadkey + ") [" - + rule[index].modifierDeadkey + " " - + rule[index].deadkey - + "] > dk(B" - + rule[index].idDeadkey - + ") ) : ";*/ - - resultWarnings.type = 'RuleReview'; - resultWarnings.isused = true; - resultWarnings.prevDK_key = rule[index].prevDeadkey; - resultWarnings.prevDK_modifier = rule[index].modifierPrevDeadkey; - resultWarnings.DK_modifier = rule[index].modifierDeadkey; - resultWarnings.DK_key = rule[index].deadkey; - resultWarnings.modifier = rule[index].modifierKey; - resultWarnings.key = rule[index].key; - resultWarnings.output = new TextDecoder().decode(rule[index].output); - - resultWarnings.warningMessages[0] = "unavailable modifier : "; - - resultWarnings.warningMessages[1] = "unavailable superior rule ( [" - + rule[index].modifierPrevDeadkey + " " - + rule[index].prevDeadkey - + "] > dk(A" - + rule[index].idPrevDeadkey - + ") ) : "; - resultWarnings.warningMessages[2] = "unavailable superior rules ( [" - + rule[index].modifierPrevDeadkey + " " - + rule[index].prevDeadkey - + "] > dk(A" - + rule[index].idPrevDeadkey - + ") ) and ( dk(A" + - + rule[index].idPrevDeadkey + ") [" - + rule[index].modifierDeadkey + " " - + rule[index].deadkey - + "] > dk(B" - + rule[index].idDeadkey - + ") ) : "; - + unavailableSuperiWarnings.compare_type = 'unav_C3'; + unavailableSuperiWarnings.dk_prefix = ['A', '']; + unavailableSuperiWarnings.dk_id = [rule[index].idPrevDeadkey, rule[index].idDeadkey]; + unavailableSuperiWarnings.prevDk_modifier = rule[index].modifierPrevDeadkey; + unavailableSuperiWarnings.prevDk_key = rule[index].prevDeadkey; + unavailableSuperiWarnings.warningMessages = this.createWarningText(unavailableSuperiWarnings, 2); } 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 - + ") ) : "; - /*resultWarnings.warningMessages[1] = "unavailable modifier : "; - resultWarnings.hasWarning_1 = true; - resultWarnings.warningMessages[2] = "unavailable superior rule ( [" - + rule[index].modifierDeadkey + " " - + rule[index].deadkey - + "] > dk(B" - + rule[index].idDeadkey - + ") ) : "; - resultWarnings.hasWarning_2 = true;*/ - - - resultWarnings.type = 'RuleReview'; - resultWarnings.isused = true; - resultWarnings.prevDK_key = rule[index].prevDeadkey; - resultWarnings.prevDK_modifier = rule[index].modifierPrevDeadkey; - resultWarnings.DK_modifier = rule[index].modifierDeadkey; - resultWarnings.DK_key = rule[index].deadkey; - resultWarnings.modifier = rule[index].modifierKey; - resultWarnings.key = rule[index].key; - resultWarnings.output = new TextDecoder().decode(rule[index].output); - resultWarnings.warningMessages[1] = "unavailable modifier : "; - resultWarnings.warningMessages[2] = "unavailable superior rule ( [" - + rule[index].modifierDeadkey + " " - + rule[index].deadkey - + "] > dk(B" - + rule[index].idDeadkey - + ") ) : "; + unavailableSuperiWarnings.compare_type = 'unav_C3'; + unavailableSuperiWarnings.prevDk_modifier = ''; + unavailableSuperiWarnings.dk_prefix = ['', 'B']; + unavailableSuperiWarnings.dk_id = [rule[index].idPrevDeadkey, rule[index].idDeadkey]; + unavailableSuperiWarnings.Dk_modifier = rule[index].modifierDeadkey; + unavailableSuperiWarnings.Dk_key = rule[index].deadkey; + unavailableSuperiWarnings.warningMessages = this.createWarningText(unavailableSuperiWarnings, 2); } if (!keylayoutKmnConverter.isAcceptableKeymanModifier(rule[index].modifierKey)) { - warningText[2] += "unavailable modifier : "; - /*resultWarnings.warningMessages[2] += "unavailable modifier : "; - resultWarnings.hasWarning_2 = true;*/ - - resultWarnings.type = 'RuleReview'; - resultWarnings.isused = true; - resultWarnings.prevDK_key = rule[index].prevDeadkey; - resultWarnings.prevDK_modifier = rule[index].modifierPrevDeadkey; - resultWarnings.DK_modifier = rule[index].modifierDeadkey; - resultWarnings.DK_key = rule[index].deadkey; - resultWarnings.modifier = rule[index].modifierKey; - resultWarnings.key = rule[index].key; - resultWarnings.output = new TextDecoder().decode(rule[index].output); - resultWarnings.warningMessages[2] += "unavailable modifier : "; - + unavailableModiWarnings.compare_type = 'unav_C3'; + unavailableModiWarnings.modifier = rule[index].modifierKey; + unavailableModiWarnings.key = rule[index].key; + unavailableModiWarnings.warningMessages = this.createWarningText(unavailableModiWarnings, 2); } } + // ------------------------- check ambiguous/duplicate rules ------------------------- if ((rule[index].ruleType === "C0") || (rule[index].ruleType === "C1")) { @@ -762,165 +705,52 @@ export class KmnFileWriter { ); 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_4_1[0].idDeadkey - + ") "); - /* resultWarnings.warningMessages[2] = resultWarnings.warningMessages[2] + ("ambiguous rule: later: [" - + amb_4_1[0].modifierPrevDeadkey - + " " - + amb_4_1[0].prevDeadkey - + "] > dk(C" - + amb_2_1[0].idDeadkey - + ") "); - resultWarnings.hasWarning_2 = true;*/ + ambiguousWarnings.compare_type = 'amb_4_1'; + ambiguousWarnings.isEarlier = false; + ambiguousWarnings.dk_prefix = ['C', 'A']; + ambiguousWarnings.dk_id = [amb_4_1[0].idPrevDeadkey, amb_4_1[0].idDeadkey]; + ambiguousWarnings.prevDk_modifier = amb_4_1[0].modifierPrevDeadkey; + ambiguousWarnings.prevDk_key = amb_4_1[0].prevDeadkey; + ambiguousWarnings.warningMessages = this.createWarningText(ambiguousWarnings, 2); - - resultWarnings.type = 'RuleReview'; - resultWarnings.isused = true; - resultWarnings.prevDK_key = rule[index].prevDeadkey; - resultWarnings.prevDK_modifier = rule[index].modifierPrevDeadkey; - resultWarnings.DK_modifier = rule[index].modifierDeadkey; - resultWarnings.DK_key = rule[index].deadkey; - resultWarnings.modifier = rule[index].modifierKey; - resultWarnings.key = rule[index].key; - resultWarnings.output = new TextDecoder().decode(rule[index].output); - resultWarnings.warningMessages[2] = resultWarnings.warningMessages[2] + ("ambiguous rule: later: [" - + amb_4_1[0].modifierPrevDeadkey - + " " - + amb_4_1[0].prevDeadkey - + "] > dk(C" - + amb_4_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 - + ") "); - /* resultWarnings.warningMessages[2] = resultWarnings.warningMessages[2] - + ("ambiguous rule: later: [" - + amb_2_1[0].modifierDeadkey - + " " - + amb_2_1[0].deadkey - + "] > dk(A" - + amb_2_1[0].idDeadkey - + ") "); - resultWarnings.hasWarning_2 = true;*/ - - resultWarnings.type = 'RuleReview'; - resultWarnings.isused = true; - resultWarnings.prevDK_key = rule[index].prevDeadkey; - resultWarnings.prevDK_modifier = rule[index].modifierPrevDeadkey; - resultWarnings.DK_modifier = rule[index].modifierDeadkey; - resultWarnings.DK_key = rule[index].deadkey; - resultWarnings.modifier = rule[index].modifierKey; - resultWarnings.key = rule[index].key; - resultWarnings.output = new TextDecoder().decode(rule[index].output); - resultWarnings.warningMessages[2] = resultWarnings.warningMessages[2] - + ("ambiguous rule: later: [" - + amb_2_1[0].modifierDeadkey - + " " - + amb_2_1[0].deadkey - + "] > dk(A" - + amb_2_1[0].idDeadkey - + ") "); - - + ambiguousWarnings.compare_type = 'amb_2_1'; + ambiguousWarnings.isEarlier = false; + ambiguousWarnings.dk_prefix = ['', 'A']; + ambiguousWarnings.dk_id = [amb_2_1[0].idPrevDeadkey, amb_2_1[0].idDeadkey]; + ambiguousWarnings.Dk_modifier = amb_2_1[0].modifierDeadkey; + ambiguousWarnings.Dk_key = amb_2_1[0].deadkey; + ambiguousWarnings.warningMessages = this.createWarningText(ambiguousWarnings, 2); } 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 - + "\' "); - /* resultWarnings.warningMessages[2] = resultWarnings.warningMessages[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 - + "\' "); - resultWarnings.hasWarning_2 = true;*/ - - - resultWarnings.type = 'RuleReview'; - resultWarnings.isused = true; - resultWarnings.prevDK_key = rule[index].prevDeadkey; - resultWarnings.prevDK_modifier = rule[index].modifierPrevDeadkey; - resultWarnings.DK_modifier = rule[index].modifierDeadkey; - resultWarnings.DK_key = rule[index].deadkey; - resultWarnings.modifier = rule[index].modifierKey; - resultWarnings.key = rule[index].key; - resultWarnings.output = new TextDecoder().decode(rule[index].output); - resultWarnings.warningMessages[2] = resultWarnings.warningMessages[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 - + "\' "); + ambiguousWarnings.compare_type = 'amb_1_1'; + ambiguousWarnings.isEarlier = true; + ambiguousWarnings.modifier = amb_1_1[0].modifierKey; + ambiguousWarnings.key = amb_1_1[0].key; + const outputCharacter = this.writeCharacterOrUnicode(new TextDecoder().decode(amb_1_1[0].output)); + if (outputCharacter !== null) { + ambiguousWarnings.output = outputCharacter.character; + } + ambiguousWarnings.warningMessages = this.createWarningText(ambiguousWarnings, 2); } 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 - + "\' "); - /* resultWarnings.warningMessages[2] = resultWarnings.warningMessages[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 - + "\' "); - resultWarnings.hasWarning_2 = true;*/ - - resultWarnings.type = 'RuleReview'; - resultWarnings.isused = true; - resultWarnings.prevDK_key = rule[index].prevDeadkey; - resultWarnings.prevDK_modifier = rule[index].modifierPrevDeadkey; - resultWarnings.DK_modifier = rule[index].modifierDeadkey; - resultWarnings.DK_key = rule[index].deadkey; - resultWarnings.modifier = rule[index].modifierKey; - resultWarnings.key = rule[index].key; - resultWarnings.output = new TextDecoder().decode(rule[index].output); - resultWarnings.warningMessages[2] = resultWarnings.warningMessages[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 - + "\' "); + duplicateWarnings.compare_type = 'dup_1_1'; + duplicateWarnings.isEarlier = true; + duplicateWarnings.modifier = dup_1_1[0].modifierKey; + duplicateWarnings.key = dup_1_1[0].key; + const outputCharacter = this.writeCharacterOrUnicode(new TextDecoder().decode(dup_1_1[0].output)); + if (outputCharacter !== null) { + duplicateWarnings.output = outputCharacter.character; + } + duplicateWarnings.warningMessages = this.createWarningText(duplicateWarnings, 2); } } - /* console.log("compare", ((resultWarnings.warningMessage[0] === warningText[0]) - && (resultWarnings.warningMessage[1] === warningText[1]) - && (resultWarnings.warningMessage[2] === warningText[2])));*/ - if (rule[index].ruleType === "C2") { @@ -972,208 +802,66 @@ export class KmnFileWriter { ); 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 - + ") "); - /*resultWarnings.warningMessages[1] = resultWarnings.warningMessages[1] - + ("ambiguous rule: earlier: [" - + amb_2_2[0].modifierDeadkey - + " " - + amb_2_2[0].deadkey - + "] > dk(C" - + amb_2_2[0].idDeadkey - + ") "); - resultWarnings.hasWarning_1 = true;*/ - - resultWarnings.type = 'RuleReview'; - resultWarnings.isused = true; - resultWarnings.prevDK_key = rule[index].prevDeadkey; - resultWarnings.prevDK_modifier = rule[index].modifierPrevDeadkey; - resultWarnings.DK_modifier = rule[index].modifierDeadkey; - resultWarnings.DK_key = rule[index].deadkey; - resultWarnings.modifier = rule[index].modifierKey; - resultWarnings.key = rule[index].key; - resultWarnings.output = new TextDecoder().decode(rule[index].output); - resultWarnings.warningMessages[1] = resultWarnings.warningMessages[1] - + ("ambiguous rule: earlier: [" - + amb_2_2[0].modifierDeadkey - + " " - + amb_2_2[0].deadkey - + "] > dk(C" - + amb_2_2[0].idDeadkey - + ") "); - + ambiguousWarnings.compare_type = 'amb_2_2'; + ambiguousWarnings.isEarlier = true; + ambiguousWarnings.dk_prefix = ['', 'C']; + ambiguousWarnings.dk_id = [amb_2_2[0].idPrevDeadkey, amb_2_2[0].idDeadkey]; + ambiguousWarnings.Dk_modifier = amb_2_2[0].modifierDeadkey; + ambiguousWarnings.Dk_key = amb_2_2[0].deadkey; + ambiguousWarnings.warningMessages = this.createWarningText(ambiguousWarnings, 1); } 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 - + ") "); - /* resultWarnings.warningMessages[1] = resultWarnings.warningMessages[1] + ("duplicate rule: earlier: [" - + dup_2_2[0].modifierDeadkey - + " " - + dup_2_2[0].deadkey - + "] > dk(C" - + dup_2_2[0].idDeadkey - + ") "); - resultWarnings.hasWarning_1 = true;*/ - - resultWarnings.type = 'RuleReview'; - resultWarnings.isused = true; - resultWarnings.prevDK_key = rule[index].prevDeadkey; - resultWarnings.prevDK_modifier = rule[index].modifierPrevDeadkey; - resultWarnings.DK_modifier = rule[index].modifierDeadkey; - resultWarnings.DK_key = rule[index].deadkey; - resultWarnings.modifier = rule[index].modifierKey; - resultWarnings.key = rule[index].key; - resultWarnings.output = new TextDecoder().decode(rule[index].output); - - resultWarnings.warningMessages[1] = resultWarnings.warningMessages[1] + ("duplicate rule: earlier: [" - + dup_2_2[0].modifierDeadkey - + " " - + dup_2_2[0].deadkey - + "] > dk(C" - + dup_2_2[0].idDeadkey - + ") "); + duplicateWarnings.compare_type = 'dup_2_2'; + duplicateWarnings.isEarlier = true; + duplicateWarnings.dk_prefix = ['', 'C']; + duplicateWarnings.dk_id = [dup_2_2[0].idPrevDeadkey, dup_2_2[0].idDeadkey]; + duplicateWarnings.Dk_modifier = dup_2_2[0].modifierDeadkey; + duplicateWarnings.Dk_key = dup_2_2[0].deadkey; + duplicateWarnings.warningMessages = this.createWarningText(duplicateWarnings, 1); } 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 - + "\' "); - /* resultWarnings.warningMessages[2] = resultWarnings.warningMessages[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 - + "\' "); - resultWarnings.hasWarning_2 = true;*/ + ambiguousWarnings.compare_type = 'amb_3_3'; + ambiguousWarnings.isEarlier = true; + ambiguousWarnings.dk_prefix = ['', 'A']; + ambiguousWarnings.dk_id = [amb_3_3[0].idPrevDeadkey, amb_3_3[0].idDeadkey]; + ambiguousWarnings.modifier = amb_3_3[0].modifierKey; + ambiguousWarnings.key = amb_3_3[0].key; + const outputCharacter = this.writeCharacterOrUnicode(new TextDecoder().decode(amb_3_3[0].output)); + if (outputCharacter !== null) { + ambiguousWarnings.output = outputCharacter.character; + } + ambiguousWarnings.warningMessages = this.createWarningText(ambiguousWarnings, 2); - resultWarnings.type = 'RuleReview'; - resultWarnings.isused = true; - resultWarnings.prevDK_key = rule[index].prevDeadkey; - resultWarnings.prevDK_modifier = rule[index].modifierPrevDeadkey; - resultWarnings.DK_modifier = rule[index].modifierDeadkey; - resultWarnings.DK_key = rule[index].deadkey; - resultWarnings.modifier = rule[index].modifierKey; - resultWarnings.key = rule[index].key; - resultWarnings.output = new TextDecoder().decode(rule[index].output); - resultWarnings.warningMessages[2] = resultWarnings.warningMessages[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 - + "\' "); - /* resultWarnings.warningMessages[2] = resultWarnings.warningMessages[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 - + "\' "); - resultWarnings.hasWarning_2 = true;*/ - - resultWarnings.type = 'RuleReview'; - resultWarnings.isused = true; - resultWarnings.prevDK_key = rule[index].prevDeadkey; - resultWarnings.prevDK_modifier = rule[index].modifierPrevDeadkey; - resultWarnings.DK_modifier = rule[index].modifierDeadkey; - resultWarnings.DK_key = rule[index].deadkey; - resultWarnings.modifier = rule[index].modifierKey; - resultWarnings.key = rule[index].key; - resultWarnings.output = new TextDecoder().decode(rule[index].output); - resultWarnings.warningMessages[2] = resultWarnings.warningMessages[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 - + "\' "); - + duplicateWarnings.compare_type = 'dup_3_3'; + duplicateWarnings.isEarlier = true; + duplicateWarnings.dk_id = [dup_3_3[0].idPrevDeadkey, dup_3_3[0].idDeadkey]; + duplicateWarnings.dk_prefix = ['', 'A']; + duplicateWarnings.modifier = dup_3_3[0].modifierKey; + duplicateWarnings.key = dup_3_3[0].key; + const outputCharacter = this.writeCharacterOrUnicode(new TextDecoder().decode(dup_3_3[0].output)); + if (outputCharacter !== null) { + duplicateWarnings.output = outputCharacter.character; + } + duplicateWarnings.warningMessages = this.createWarningText(duplicateWarnings, 2); } 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 - + ") "); - /* resultWarnings.warningMessages[0] = resultWarnings.warningMessages[0] - + ("ambiguous rule: later: [" - + amb_4_2[0].modifierPrevDeadkey - + " " - + amb_4_2[0].prevDeadkey - + "] > dk(C" - + amb_4_2[0].idPrevDeadkey - + ") "); - resultWarnings.hasWarning_0 = true;*/ - - resultWarnings.type = 'RuleReview'; - resultWarnings.isused = true; - resultWarnings.prevDK_key = rule[index].prevDeadkey; - resultWarnings.prevDK_modifier = rule[index].modifierPrevDeadkey; - resultWarnings.DK_modifier = rule[index].modifierDeadkey; - resultWarnings.DK_key = rule[index].deadkey; - resultWarnings.modifier = rule[index].modifierKey; - resultWarnings.key = rule[index].key; - resultWarnings.output = new TextDecoder().decode(rule[index].output); - resultWarnings.warningMessages[0] = resultWarnings.warningMessages[0] - + ("ambiguous rule: later: [" - + amb_4_2[0].modifierPrevDeadkey - + " " - + amb_4_2[0].prevDeadkey - + "] > dk(C" - + amb_4_2[0].idPrevDeadkey - + ") "); - + ambiguousWarnings.compare_type = 'amb_4_2'; + ambiguousWarnings.isEarlier = false; + ambiguousWarnings.dk_prefix = ['C', '']; + ambiguousWarnings.dk_id = [amb_4_2[0].idPrevDeadkey, amb_4_2[0].idDeadkey]; + ambiguousWarnings.prevDk_modifier = amb_4_2[0].modifierPrevDeadkey; + ambiguousWarnings.prevDk_key = amb_4_2[0].prevDeadkey; + ambiguousWarnings.warningMessages = this.createWarningText(ambiguousWarnings, 0); } } + if (rule[index].ruleType === "C3") { // 2-4 + [CAPS K_N] > dk(C11) <-> + [CAPS K_N] > dk(B11) @@ -1256,375 +944,119 @@ 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.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 - ); + 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 - + ") "); - /*resultWarnings.warningMessages[0] = resultWarnings.warningMessages[0] + ("ambiguous rule: earlier: [" - + amb_2_4[0].modifierDeadkey - + " " - + amb_2_4[0].deadkey - + "] > dk(A" - + amb_2_4[0].idDeadkey - + ") "); - resultWarnings.hasWarning_0 = true;*/ - - resultWarnings.type = 'RuleReview'; - resultWarnings.isused = true; - resultWarnings.prevDK_key = rule[index].prevDeadkey; - resultWarnings.prevDK_modifier = rule[index].modifierPrevDeadkey; - resultWarnings.DK_modifier = rule[index].modifierDeadkey; - resultWarnings.DK_key = rule[index].deadkey; - resultWarnings.modifier = rule[index].modifierKey; - resultWarnings.key = rule[index].key; - resultWarnings.output = new TextDecoder().decode(rule[index].output); - resultWarnings.warningMessages[0] = resultWarnings.warningMessages[0] + ("ambiguous rule: earlier: [" - + amb_2_4[0].modifierDeadkey - + " " - + amb_2_4[0].deadkey - + "] > dk(A" - + amb_2_4[0].idDeadkey - + ") "); - + ambiguousWarnings.compare_type = 'amb_2_4'; + ambiguousWarnings.isEarlier = true; + ambiguousWarnings.dk_prefix = ['', 'A']; + ambiguousWarnings.dk_id = [amb_2_4[0].idPrevDeadkey, amb_2_4[0].idDeadkey]; + ambiguousWarnings.Dk_modifier = amb_2_4[0].modifierDeadkey; + ambiguousWarnings.Dk_key = amb_2_4[0].deadkey; + ambiguousWarnings.warningMessages = this.createWarningText(ambiguousWarnings, 0); } 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 - + "\' "); - /*resultWarnings.warningMessages[1] = resultWarnings.warningMessages[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 - + "\' "); - resultWarnings.hasWarning_1 = true;*/ - - resultWarnings.type = 'RuleReview'; - resultWarnings.isused = true; - resultWarnings.prevDK_key = rule[index].prevDeadkey; - resultWarnings.prevDK_modifier = rule[index].modifierPrevDeadkey; - resultWarnings.DK_modifier = rule[index].modifierDeadkey; - resultWarnings.DK_key = rule[index].deadkey; - resultWarnings.modifier = rule[index].modifierKey; - resultWarnings.key = rule[index].key; - resultWarnings.output = new TextDecoder().decode(rule[index].output); - resultWarnings.warningMessages[1] = resultWarnings.warningMessages[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 - + "\' "); + ambiguousWarnings.compare_type = 'amb_6_3'; + ambiguousWarnings.isEarlier = true; + ambiguousWarnings.dk_prefix = ['', 'C']; + ambiguousWarnings.dk_id = [amb_6_3[0].idPrevDeadkey, amb_6_3[0].idDeadkey]; + ambiguousWarnings.modifier = amb_6_3[0].modifierKey; + ambiguousWarnings.key = amb_6_3[0].key; + const outputCharacter = this.writeCharacterOrUnicode(new TextDecoder().decode(amb_6_3[0].output)); + if (outputCharacter !== null) { + ambiguousWarnings.output = outputCharacter.character; + } + ambiguousWarnings.warningMessages = this.createWarningText(ambiguousWarnings, 1); } 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 - + "\' "); - /* resultWarnings.warningMessages[1] = resultWarnings.warningMessages[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 - + "\' "); - resultWarnings.hasWarning_1 = true;*/ - - resultWarnings.type = 'RuleReview'; - resultWarnings.isused = true; - resultWarnings.prevDK_key = rule[index].prevDeadkey; - resultWarnings.prevDK_modifier = rule[index].modifierPrevDeadkey; - resultWarnings.DK_modifier = rule[index].modifierDeadkey; - resultWarnings.DK_key = rule[index].deadkey; - resultWarnings.modifier = rule[index].modifierKey; - resultWarnings.key = rule[index].key; - resultWarnings.output = new TextDecoder().decode(rule[index].output); - resultWarnings.warningMessages[1] = resultWarnings.warningMessages[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 - + "\' "); + duplicateWarnings.compare_type = 'dup_6_3'; + duplicateWarnings.isEarlier = true; + duplicateWarnings.dk_prefix = ['', 'C']; + duplicateWarnings.dk_id = [dup_6_3[0].idPrevDeadkey, dup_6_3[0].idDeadkey]; + duplicateWarnings.modifier = dup_6_3[0].modifierKey; + duplicateWarnings.key = dup_6_3[0].key; + const outputCharacter = this.writeCharacterOrUnicode(new TextDecoder().decode(dup_6_3[0].output)); + if (outputCharacter !== null) { + duplicateWarnings.output = outputCharacter.character; + } + duplicateWarnings.warningMessages = this.createWarningText(duplicateWarnings, 1); } 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 - + ") "); - /* resultWarnings.warningMessages[0] = resultWarnings.warningMessages[0] + ("ambiguous rule: earlier: [" - + amb_4_4[0].modifierPrevDeadkey - + " " - + amb_4_4[0].prevDeadkey - + "] > dk(C" - + amb_4_4[0].idPrevDeadkey - + ") "); - resultWarnings.hasWarning_0 = true;*/ - - resultWarnings.type = 'RuleReview'; - resultWarnings.isused = true; - resultWarnings.prevDK_key = rule[index].prevDeadkey; - resultWarnings.prevDK_modifier = rule[index].modifierPrevDeadkey; - resultWarnings.DK_modifier = rule[index].modifierDeadkey; - resultWarnings.DK_key = rule[index].deadkey; - resultWarnings.modifier = rule[index].modifierKey; - resultWarnings.key = rule[index].key; - resultWarnings.output = new TextDecoder().decode(rule[index].output); - resultWarnings.warningMessages[0] = resultWarnings.warningMessages[0] + ("ambiguous rule: earlier: [" - + amb_4_4[0].modifierPrevDeadkey - + " " - + amb_4_4[0].prevDeadkey - + "] > dk(C" - + amb_4_4[0].idPrevDeadkey - + ") "); + ambiguousWarnings.compare_type = 'amb_4_4'; + ambiguousWarnings.isEarlier = true; + ambiguousWarnings.dk_prefix = ['C', '']; + ambiguousWarnings.dk_id = [amb_4_4[0].idPrevDeadkey, amb_4_4[0].idDeadkey]; + ambiguousWarnings.prevDk_modifier = amb_4_4[0].modifierPrevDeadkey; + ambiguousWarnings.prevDk_key = amb_4_4[0].prevDeadkey; + ambiguousWarnings.warningMessages = this.createWarningText(ambiguousWarnings, 0); } 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 - + ") "); - /* resultWarnings.warningMessages[0] = resultWarnings.warningMessages[0] + ("duplicate rule: earlier: [" - + dup_4_4[0].modifierPrevDeadkey - + " " - + dup_4_4[0].prevDeadkey - + "] > dk(C" - + dup_4_4[0].idPrevDeadkey - + ") "); - resultWarnings.hasWarning_0 = true;*/ - - resultWarnings.type = 'RuleReview'; - resultWarnings.isused = true; - resultWarnings.prevDK_key = rule[index].prevDeadkey; - resultWarnings.prevDK_modifier = rule[index].modifierPrevDeadkey; - resultWarnings.DK_modifier = rule[index].modifierDeadkey; - resultWarnings.DK_key = rule[index].deadkey; - resultWarnings.modifier = rule[index].modifierKey; - resultWarnings.key = rule[index].key; - resultWarnings.output = new TextDecoder().decode(rule[index].output); - resultWarnings.warningMessages[0] = resultWarnings.warningMessages[0] + ("duplicate rule: earlier: [" - + dup_4_4[0].modifierPrevDeadkey - + " " - + dup_4_4[0].prevDeadkey - + "] > dk(C" - + dup_4_4[0].idPrevDeadkey - + ") "); + duplicateWarnings.compare_type = 'dup_4_4'; + duplicateWarnings.isEarlier = true; + duplicateWarnings.dk_prefix = ['C', '']; + duplicateWarnings.dk_id = [dup_4_4[0].idPrevDeadkey, dup_4_4[0].idDeadkey]; + duplicateWarnings.prevDk_modifier = dup_4_4[0].modifierPrevDeadkey; + duplicateWarnings.prevDk_key = dup_4_4[0].prevDeadkey; + duplicateWarnings.warningMessages = this.createWarningText(duplicateWarnings, 0); } 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 - + ") "); - /* resultWarnings.warningMessages[1] = resultWarnings.warningMessages[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 - + ") "); - resultWarnings.hasWarning_1 = true;*/ - - resultWarnings.type = 'RuleReview'; - resultWarnings.isused = true; - resultWarnings.prevDK_key = rule[index].prevDeadkey; - resultWarnings.prevDK_modifier = rule[index].modifierPrevDeadkey; - resultWarnings.DK_modifier = rule[index].modifierDeadkey; - resultWarnings.DK_key = rule[index].deadkey; - resultWarnings.modifier = rule[index].modifierKey; - resultWarnings.key = rule[index].key; - resultWarnings.output = new TextDecoder().decode(rule[index].output); - resultWarnings.warningMessages[1] = resultWarnings.warningMessages[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 - + ") "); + ambiguousWarnings.compare_type = 'amb_5_5'; + ambiguousWarnings.isEarlier = true; + ambiguousWarnings.dk_prefix = ['C', 'B']; + ambiguousWarnings.dk_id = [amb_5_5[0].idPrevDeadkey, amb_5_5[0].idDeadkey]; + ambiguousWarnings.Dk_modifier = amb_5_5[0].modifierDeadkey; + ambiguousWarnings.Dk_key = amb_5_5[0].deadkey; + ambiguousWarnings.warningMessages = this.createWarningText(ambiguousWarnings); } 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 - + ") "); - /* resultWarnings.warningMessages[1] = resultWarnings.warningMessages[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 - + ") "); - resultWarnings.hasWarning_1 = true;*/ - - resultWarnings.type = 'RuleReview'; - resultWarnings.isused = true; - resultWarnings.prevDK_key = rule[index].prevDeadkey; - resultWarnings.prevDK_modifier = rule[index].modifierPrevDeadkey; - resultWarnings.DK_modifier = rule[index].modifierDeadkey; - resultWarnings.DK_key = rule[index].deadkey; - resultWarnings.modifier = rule[index].modifierKey; - resultWarnings.key = rule[index].key; - resultWarnings.output = new TextDecoder().decode(rule[index].output); - resultWarnings.warningMessages[1] = resultWarnings.warningMessages[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 - + ") "); - + duplicateWarnings.compare_type = 'dup_5_5'; + duplicateWarnings.isEarlier = true; + duplicateWarnings.dk_prefix = ['C', 'B']; + duplicateWarnings.dk_id = [dup_5_5[0].idPrevDeadkey, dup_5_5[0].idDeadkey]; + duplicateWarnings.Dk_modifier = rule[index].modifierDeadkey; + duplicateWarnings.Dk_key = rule[index].deadkey; + duplicateWarnings.warningMessages = this.createWarningText(duplicateWarnings, 1); } 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 - + "\' "); - resultWarnings.warningMessages[2] = resultWarnings.warningMessages[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 - + "\' "); - resultWarnings.hasWarning_2 = true; - /* resultAll - resultWarnings.type = ''; - resultWarnings.isused = true; - resultWarnings.prevDK_key = rule[index].prevDeadkey; - resultWarnings.prevDK_modifier = rule[index].modifierPrevDeadkey; - resultWarnings.DK_modifier = rule[index].modifierDeadkey; - resultWarnings.DK_key = rule[index].deadkey; - resultWarnings.modifier = rule[index].modifierKey; - resultWarnings.key = rule[index].key; - resultWarnings.output = new TextDecoder().decode(rule[index].output); - resultWarnings.warningMessage[0] = ""; - resultWarnings.warningMessage[1] = ""; - resultWarnings.warningMessage[2] = ""; - */ + ambiguousWarnings.compare_type = 'amb_6_6'; + ambiguousWarnings.isEarlier = true; + ambiguousWarnings.dk_prefix = ['', 'B']; + ambiguousWarnings.dk_id = [amb_6_6[0].idPrevDeadkey, amb_6_6[0].idDeadkey]; + ambiguousWarnings.modifier = amb_6_6[0].modifierKey; + ambiguousWarnings.key = amb_6_6[0].key; + const outputCharacter = this.writeCharacterOrUnicode(new TextDecoder().decode(amb_6_6[0].output)); + if (outputCharacter !== null) { + ambiguousWarnings.output = outputCharacter.character; + } + ambiguousWarnings.warningMessages = this.createWarningText(ambiguousWarnings, 2); } 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 - + "\' "); - /* resultWarnings.warningMessages[2] = resultWarnings.warningMessages[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 - + "\' "); - resultWarnings.hasWarning_2 = true;*/ - - resultWarnings.type = 'RuleReview'; - resultWarnings.isused = true; - resultWarnings.prevDK_key = rule[index].prevDeadkey; - resultWarnings.prevDK_modifier = rule[index].modifierPrevDeadkey; - resultWarnings.DK_modifier = rule[index].modifierDeadkey; - resultWarnings.DK_key = rule[index].deadkey; - resultWarnings.modifier = rule[index].modifierKey; - resultWarnings.key = rule[index].key; - resultWarnings.output = new TextDecoder().decode(rule[index].output); - resultWarnings.warningMessages[2] = resultWarnings.warningMessages[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 - + "\' "); + duplicateWarnings.compare_type = 'dup_6_6'; + duplicateWarnings.isEarlier = true; + duplicateWarnings.dk_prefix = ['', 'B']; + duplicateWarnings.dk_id = [dup_6_6[0].idPrevDeadkey, dup_6_6[0].idDeadkey]; + duplicateWarnings.modifier = dup_6_6[0].modifierKey; + duplicateWarnings.key = dup_6_6[0].key; + const outputCharacter = this.writeCharacterOrUnicode(new TextDecoder().decode(dup_6_6[0].output)); + if (outputCharacter !== null) { + duplicateWarnings.output = outputCharacter.character; + } + duplicateWarnings.warningMessages = this.createWarningText(duplicateWarnings, 2); } } @@ -1635,88 +1067,38 @@ export class KmnFileWriter { // 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 ! "; - /* resultAll - resultWarnings.type = ''; - resultWarnings.isused = true; - resultWarnings.prevDK_key = rule[index].prevDeadkey; - resultWarnings.prevDK_modifier = rule[index].modifierPrevDeadkey; - resultWarnings.DK_modifier = rule[index].modifierDeadkey; - resultWarnings.DK_key = rule[index].deadkey; - resultWarnings.modifier = rule[index].modifierKey; - resultWarnings.key = rule[index].key; - resultWarnings.output = new TextDecoder().decode(rule[index].output); - resultWarnings.warningMessage[0] = ""; - resultWarnings.warningMessage[1] = ""; - resultWarnings.warningMessage[2] = ""; - */ + const extraWarning = "PLEASE CHECK THAT 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 (resultWarnings.warningMessages[0]) { - resultWarnings.warningMessages[0] = "c WARNING: " + resultWarnings.warningMessages[0] + "here: "; - - if ((resultWarnings.warningMessages[0].indexOf("earlier:") > 0) && (resultWarnings.warningMessages[0].indexOf("later:") > 0)) { - resultWarnings.warningMessages[0] = resultWarnings.warningMessages[0] + extraWarning; + for (let i = 0; i < 3; i++) { + if (ambiguousWarnings.warningMessages[i] !== "") { + if ((ambiguousWarnings.warningMessages[i].indexOf("earlier:") > -1) && (ambiguousWarnings.warningMessages[i].indexOf("later:") > -1)) { + ambiguousWarnings.warningMessages[i] = ambiguousWarnings.warningMessages[i] + 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 (resultWarnings.warningMessages[1] !== "") { - resultWarnings.warningMessages[1] = "c WARNING: " + resultWarnings.warningMessages[1] + "here: "; - if ((resultWarnings.warningMessages[1].indexOf("earlier:") > 0) && (resultWarnings.warningMessages[1].indexOf("later:") > 0)) { - resultWarnings.warningMessages[1] = resultWarnings.warningMessages[1] + extraWarning; - } + for (let i = 0; i < 3; i++) { + const completeWarning = + unavailableSuperiWarnings.warningMessages[i] + + duplicateWarnings.warningMessages[i] + + ambiguousWarnings.warningMessages[i] + + unavailableModiWarnings.warningMessages[i]; + + completeWarning ? (resultWarningTextSet.warningMessages[i] = "c WARNING: " + completeWarning + " here: ") : resultWarningTextSet.warningMessages[i] = ''; } - 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; - } - } - - if (resultWarnings.warningMessages[2] !== "") { - resultWarnings.warningMessages[2] = "c WARNING: " + resultWarnings.warningMessages[2] + "here: "; - - if ((resultWarnings.warningMessages[2].indexOf("earlier:") > 0) && (resultWarnings.warningMessages[2].indexOf("later:") > 0)) { - resultWarnings.warningMessages[2] = resultWarnings.warningMessages[2] + extraWarning; - } - } - - /* - warningText[0] = resultWarnings.warningMessage[0] - warningText[1] = resultWarnings.warningMessage[1] - warningText[2] =resultWarnings.warningMessage[2]*/ - - - warningText[0] = resultWarnings.warningMessages[0]; - warningText[1] = resultWarnings.warningMessages[1]; - warningText[2] = resultWarnings.warningMessages[2]; - - return warningText; + return resultWarningTextSet; } /** - * @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 { + * @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 | null { if ((ctr === null) || (ctr === undefined)) { return null; @@ -1735,8 +1117,14 @@ export class KmnFileWriter { 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) : KeylayoutToKmnConverter.MAX_CTRL_CHARACTER + const ctr_val = ( + m_uni + ? parseInt(m_uni[1], 16) + : m_hex + ? parseInt(m_hex[1], 16) + : m_dec + ? parseInt(m_dec[1], 10) + : KeylayoutToKmnConverter.MAX_CTRL_CHARACTER ); if (ctr.length === 0) { @@ -1760,7 +1148,7 @@ export class KmnFileWriter { msg_control = "Use of a control character "; } else { - out.character = this.convertToUnicodeCharacter(ctr);; + out.character = this.convertToUnicodeCharacter(ctr) ?? ""; } // add a warning message @@ -1781,10 +1169,9 @@ 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(inputString: string): string | undefined { - - // null, undefined will later be refused for conversion + // null, undefined will later be treated as '' in conversion if (inputString == null || inputString == undefined) { return undefined; } @@ -1873,6 +1260,7 @@ export class KmnFileWriter { } return undefined; } + /** @internal */ public unitTestEndpoints = { reviewRules: this.reviewRules.bind(this), diff --git a/developer/src/kmc-convert/test/data/OutputXName.bb b/developer/src/kmc-convert/test/data/OutputXName.bb deleted file mode 100644 index 6e45decf3b..0000000000 --- a/developer/src/kmc-convert/test/data/OutputXName.bb +++ /dev/null @@ -1,1290 +0,0 @@ - -c .................................................................................................................. -c .................................................................................................................. -c Keyman keyboard generated by kmn-convert version: 19.0.230 -c from Ukelele file: C:\Projects\keyman\keyman\developer\src\kmc-convert\test\data\Test.keylayout -c .................................................................................................................. -c .................................................................................................................. - -store(&TARGETS) 'desktop' - -begin Unicode > use(main) - -group(main) using keys - - -+ [NCAPS K_A] > 'A' -+ [CAPS K_A] > 'A' -+ [NCAPS SHIFT K_A] > 'A' -+ [SHIFT CAPS K_A] > 'A' -+ [NCAPS RALT CTRL K_A] > '😀' -+ [NCAPS CTRL K_A] > '😀' -+ [NCAPS SHIFT RALT K_A] > 'Å' -+ [NCAPS RALT K_A] > 'å' -c WARNING: ambiguous rule: earlier: [CAPS K_A] > 'A' here: + [CAPS K_A] > 'å' -+ [CAPS RALT K_A] > 'Å' - -+ [NCAPS K_S] > 's' -+ [CAPS K_S] > 'S' -+ [NCAPS SHIFT K_S] > 'S' -+ [SHIFT CAPS K_S] > 'S' -+ [NCAPS RALT CTRL K_S] > '😁' -+ [NCAPS CTRL K_S] > '😁' -+ [NCAPS SHIFT RALT K_S] > '¯' -+ [NCAPS RALT K_S] > 'ß' -c WARNING: ambiguous rule: earlier: [CAPS K_S] > 'S' here: + [CAPS K_S] > 'ß' -+ [CAPS RALT K_S] > 'ß' - -+ [NCAPS K_D] > 'd' -+ [CAPS K_D] > 'D' -+ [NCAPS SHIFT K_D] > 'D' -+ [SHIFT CAPS K_D] > 'D' -+ [NCAPS RALT CTRL K_D] > 'ሴ' -+ [NCAPS CTRL K_D] > 'ሴ' -+ [NCAPS SHIFT RALT K_D] > '˘' -+ [NCAPS RALT K_D] > '∂' -c WARNING: ambiguous rule: earlier: [CAPS K_D] > 'D' here: + [CAPS K_D] > '∂' -+ [CAPS RALT K_D] > '∂' - -+ [NCAPS K_F] > 'f' -+ [CAPS K_F] > 'F' -+ [NCAPS SHIFT K_F] > 'F' -+ [SHIFT CAPS K_F] > 'F' -+ [NCAPS RALT CTRL K_F] > 'ሴ' -+ [NCAPS CTRL K_F] > 'ሴ' -+ [NCAPS SHIFT RALT K_F] > '˙' -+ [NCAPS RALT K_F] > 'ƒ' -c WARNING: ambiguous rule: earlier: [CAPS K_F] > 'F' here: + [CAPS K_F] > 'ƒ' -+ [CAPS RALT K_F] > 'ƒ' - -+ [NCAPS K_H] > 'h' -+ [CAPS K_H] > '@' -+ [NCAPS SHIFT K_H] > 'H' -+ [SHIFT CAPS K_H] > 'H' -+ [NCAPS RALT CTRL K_H] > '😎' -+ [NCAPS CTRL K_H] > '😎' -+ [NCAPS SHIFT RALT K_H] > '¸' -+ [NCAPS RALT K_H] > '∆' -c WARNING: ambiguous rule: earlier: [CAPS K_H] > '@' here: + [CAPS K_H] > '∆' -c WARNING: ambiguous rule: earlier: [NCAPS RALT K_H] > '∆' here: + [NCAPS RALT K_H] > 'ẞ' -+ [CAPS RALT K_H] > '€' - -+ [NCAPS K_G] > 'g' -+ [CAPS K_G] > 'G' -+ [NCAPS SHIFT K_G] > 'G' -+ [SHIFT CAPS K_G] > 'G' -c WARNING: Use of a control character + [NCAPS RALT CTRL K_G] > U+0007 -c WARNING: Use of a control character + [NCAPS CTRL K_G] > U+0007 -+ [NCAPS SHIFT RALT K_G] > '˚' -+ [NCAPS RALT K_G] > '∞' -c WARNING: ambiguous rule: earlier: [CAPS K_G] > 'G' here: + [CAPS K_G] > '∞' -+ [CAPS RALT K_G] > '∞' - -+ [NCAPS K_Z] > 'z' -+ [CAPS K_Z] > 'Z' -+ [NCAPS SHIFT K_Z] > 'Z' -+ [SHIFT CAPS K_Z] > 'Z' -c WARNING: Use of a control character + [NCAPS RALT CTRL K_Z] > U+0017 -c WARNING: Use of a control character + [NCAPS CTRL K_Z] > U+0017 -+ [NCAPS K_SPACE] > ' ' -+ [CAPS K_SPACE] > ' ' -+ [NCAPS SHIFT K_SPACE] > ' ' -+ [SHIFT CAPS K_SPACE] > ' ' -+ [NCAPS RALT CTRL K_SPACE] > ' ' -+ [NCAPS CTRL K_SPACE] > ' ' - -+ [NCAPS SHIFT RALT K_Z] > ' ' - -+ [NCAPS SHIFT RALT K_9] > ' ' - -+ [NCAPS SHIFT RALT K_COMMA] > ' ' -+ [NCAPS RALT K_Z] > '∑' -c WARNING: ambiguous rule: earlier: [CAPS K_Z] > 'Z' here: + [CAPS K_Z] > '∑' -+ [CAPS RALT K_Z] > '∑' - -+ [NCAPS K_X] > 'x' -+ [CAPS K_X] > 'X' -+ [NCAPS SHIFT K_X] > 'X' -+ [SHIFT CAPS K_X] > 'X' -c WARNING: Use of a control character + [NCAPS RALT CTRL K_X] > U+0018 -c WARNING: Use of a control character + [NCAPS CTRL K_X] > U+0018 -+ [NCAPS SHIFT RALT K_X] > '‡' -+ [NCAPS RALT K_X] > '†' -c WARNING: ambiguous rule: earlier: [CAPS K_X] > 'X' here: + [CAPS K_X] > '†' -+ [CAPS RALT K_X] > '†' - -+ [NCAPS K_C] > 'c' -+ [CAPS K_C] > 'C' -+ [NCAPS SHIFT K_C] > 'C' -+ [SHIFT CAPS K_C] > 'C' -c WARNING: Use of a control character + [NCAPS RALT CTRL K_C] > U+0003 -c WARNING: Use of a control character + [NCAPS CTRL K_C] > U+0003 -+ [NCAPS SHIFT RALT K_C] > 'Á' -+ [NCAPS RALT K_C] > '©' -c WARNING: ambiguous rule: earlier: [CAPS K_C] > 'C' here: + [CAPS K_C] > '©' -+ [CAPS RALT K_C] > '©' - -+ [NCAPS K_V] > 'v' -+ [CAPS K_V] > 'V' -+ [NCAPS SHIFT K_V] > 'V' -+ [SHIFT CAPS K_V] > 'V' -c WARNING: Use of a control character + [NCAPS RALT CTRL K_V] > U+0016 -c WARNING: Use of a control character + [NCAPS CTRL K_V] > U+0016 -+ [NCAPS SHIFT RALT K_V] > 'É' -+ [NCAPS RALT K_V] > '√' -c WARNING: ambiguous rule: earlier: [CAPS K_V] > 'V' here: + [CAPS K_V] > '√' -+ [CAPS RALT K_V] > '√' - -+ [NCAPS K_BKQUOTE] > '\' -+ [CAPS K_BKQUOTE] > '\' -+ [NCAPS SHIFT K_BKQUOTE] > '|' -+ [SHIFT CAPS K_BKQUOTE] > '|' -c WARNING: Use of a control character + [NCAPS RALT CTRL K_BKQUOTE] > U+001C -c WARNING: Use of a control character + [NCAPS CTRL K_BKQUOTE] > U+001C -+ [NCAPS SHIFT RALT K_BKQUOTE] > 'ı' -+ [NCAPS RALT K_BKQUOTE] > '`' -c WARNING: ambiguous rule: earlier: [CAPS K_BKQUOTE] > '\' here: + [CAPS K_BKQUOTE] > '`' -+ [CAPS RALT K_BKQUOTE] > '`' - -+ [NCAPS K_B] > 'b' -+ [CAPS K_B] > 'B' -+ [NCAPS SHIFT K_B] > 'B' -+ [SHIFT CAPS K_B] > 'B' -c WARNING: Use of a control character + [NCAPS RALT CTRL K_B] > U+0002 -c WARNING: Use of a control character + [NCAPS CTRL K_B] > U+0002 -+ [NCAPS SHIFT RALT K_B] > 'Í' -+ [NCAPS RALT K_B] > '∫' -c WARNING: ambiguous rule: earlier: [CAPS K_B] > 'B' here: + [CAPS K_B] > '∫' -+ [CAPS RALT K_B] > '∫' - -+ [NCAPS K_Q] > 'q' -+ [CAPS K_Q] > 'Q' -+ [NCAPS SHIFT K_Q] > 'Q' -+ [SHIFT CAPS K_Q] > 'Q' -c WARNING: Use of a control character + [NCAPS RALT CTRL K_Q] > U+0011 -c WARNING: Use of a control character + [NCAPS CTRL K_Q] > U+0011 -+ [NCAPS SHIFT RALT K_Q] > '‚' -+ [NCAPS RALT K_Q] > '„' -c WARNING: ambiguous rule: earlier: [CAPS K_Q] > 'Q' here: + [CAPS K_Q] > '„' -+ [CAPS RALT K_Q] > '„' - -+ [NCAPS K_W] > 'w' -+ [CAPS K_W] > 'W' -+ [NCAPS SHIFT K_W] > 'W' -+ [SHIFT CAPS K_W] > 'W' -c WARNING: Use of a control character + [NCAPS RALT CTRL K_W] > U+001A -c WARNING: Use of a control character + [NCAPS CTRL K_W] > U+001A -+ [NCAPS SHIFT RALT K_W] > 'À' -+ [NCAPS RALT K_W] > 'Ω' -c WARNING: ambiguous rule: earlier: [CAPS K_W] > 'W' here: + [CAPS K_W] > 'Ω' -+ [CAPS RALT K_W] > 'Ω' -+ [NCAPS K_E] > 'e' -+ [CAPS K_E] > 'E' -+ [NCAPS SHIFT K_E] > 'E' -+ [SHIFT CAPS K_E] > 'E' -c WARNING: Use of a control character + [NCAPS RALT CTRL K_E] > U+0005 -c WARNING: Use of a control character + [NCAPS CTRL K_E] > U+0005 -+ [NCAPS SHIFT RALT K_E] > 'È' -+ [NCAPS RALT K_E] > '€' -c WARNING: ambiguous rule: earlier: [CAPS K_E] > 'E' here: + [CAPS K_E] > '€' -+ [CAPS RALT K_E] > '€' - -+ [NCAPS K_R] > 'r' -+ [CAPS K_R] > 'R' -+ [NCAPS SHIFT K_R] > 'R' -+ [SHIFT CAPS K_R] > 'R' -c WARNING: Use of a control character + [NCAPS RALT CTRL K_R] > U+0012 -c WARNING: Use of a control character + [NCAPS CTRL K_R] > U+0012 -+ [NCAPS SHIFT RALT K_R] > 'Ì' -+ [NCAPS RALT K_R] > '®' -c WARNING: ambiguous rule: earlier: [CAPS K_R] > 'R' here: + [CAPS K_R] > '®' -+ [CAPS RALT K_R] > '®' -+ [NCAPS K_Y] > 'y' -+ [CAPS K_Y] > 'Y' -+ [NCAPS SHIFT K_Y] > 'Y' -+ [SHIFT CAPS K_Y] > 'Y' -c WARNING: Use of a control character + [NCAPS RALT CTRL K_Y] > U+0019 -c WARNING: Use of a control character + [NCAPS CTRL K_Y] > U+0019 -+ [NCAPS SHIFT RALT K_Y] > 'Æ' -+ [NCAPS RALT K_Y] > 'æ' -c WARNING: ambiguous rule: earlier: [CAPS K_Y] > 'Y' here: + [CAPS K_Y] > 'æ' -+ [CAPS RALT K_Y] > 'Æ' - -+ [NCAPS K_T] > 't' -+ [CAPS K_T] > 'T' -+ [NCAPS SHIFT K_T] > 'T' -+ [SHIFT CAPS K_T] > 'T' -c WARNING: Use of a control character + [NCAPS RALT CTRL K_T] > U+0014 -c WARNING: Use of a control character + [NCAPS CTRL K_T] > U+0014 -+ [NCAPS SHIFT RALT K_T] > 'Ò' -+ [NCAPS RALT K_T] > '™' -c WARNING: ambiguous rule: earlier: [CAPS K_T] > 'T' here: + [CAPS K_T] > '™' -+ [CAPS RALT K_T] > '™' - -+ [NCAPS K_1] > '1' -+ [CAPS K_1] > '1' -+ [NCAPS SHIFT K_1] > '!' -+ [SHIFT CAPS K_1] > '!' -+ [NCAPS RALT CTRL K_1] > '1' -+ [NCAPS CTRL K_1] > '1' -+ [NCAPS SHIFT RALT K_1] > '»' -+ [NCAPS RALT K_1] > '«' -c WARNING: ambiguous rule: earlier: [CAPS K_1] > '1' here: + [CAPS K_1] > '«' -+ [CAPS RALT K_1] > '«' - -+ [NCAPS K_2] > '2' -+ [CAPS K_2] > '2' -+ [NCAPS SHIFT K_2] > '"' -+ [SHIFT CAPS K_2] > '"' -+ [NCAPS RALT CTRL K_2] > '2' -+ [NCAPS CTRL K_2] > '2' -+ [NCAPS SHIFT RALT K_2] > '”' -+ [NCAPS RALT K_2] > '“' -c WARNING: ambiguous rule: earlier: [CAPS K_2] > '2' here: + [CAPS K_2] > '“' -+ [CAPS RALT K_2] > '“' - -+ [NCAPS K_3] > '3' -+ [CAPS K_3] > '3' -+ [NCAPS SHIFT K_3] > '£' -+ [SHIFT CAPS K_3] > '£' -+ [NCAPS RALT CTRL K_3] > '3' -+ [NCAPS CTRL K_3] > '3' -+ [NCAPS SHIFT RALT K_3] > '’' -+ [NCAPS RALT K_3] > '‘' -c WARNING: ambiguous rule: earlier: [CAPS K_3] > '3' here: + [CAPS K_3] > '‘' -+ [CAPS RALT K_3] > '‘' - -+ [NCAPS K_4] > '4' -+ [CAPS K_4] > '4' -+ [NCAPS SHIFT K_4] > '$' -+ [SHIFT CAPS K_4] > '$' -+ [NCAPS RALT CTRL K_4] > '4' -+ [NCAPS CTRL K_4] > '4' -+ [NCAPS SHIFT RALT K_4] > '¢' -+ [NCAPS RALT K_4] > '¥' -c WARNING: ambiguous rule: earlier: [CAPS K_4] > '4' here: + [CAPS K_4] > '¥' -+ [CAPS RALT K_4] > '¥' - -+ [NCAPS K_6] > '6' -+ [CAPS K_6] > '6' -+ [NCAPS SHIFT K_6] > '&' -+ [SHIFT CAPS K_6] > '&' -+ [NCAPS RALT CTRL K_6] > '6' -+ [NCAPS CTRL K_6] > '6' -+ [NCAPS SHIFT RALT K_6] > '›' -+ [NCAPS RALT K_6] > '‹' -c WARNING: ambiguous rule: earlier: [CAPS K_6] > '6' here: + [CAPS K_6] > '‹' -+ [CAPS RALT K_6] > '‹' - -+ [NCAPS K_5] > '5' -+ [CAPS K_5] > '5' -+ [NCAPS SHIFT K_5] > '%' -+ [SHIFT CAPS K_5] > '%' -+ [NCAPS RALT CTRL K_5] > '5' -+ [NCAPS CTRL K_5] > '5' -+ [NCAPS SHIFT RALT K_5] > '‰' -+ [NCAPS RALT K_5] > '~' -c WARNING: ambiguous rule: earlier: [CAPS K_5] > '5' here: + [CAPS K_5] > '~' -+ [CAPS RALT K_5] > '~' -c WARNING: ambiguous rule: later: [CAPS K_EQUAL] > dk(A3) here: + [CAPS K_EQUAL] > 'ì' -+ [NCAPS SHIFT K_EQUAL] > '^' -+ [SHIFT CAPS K_EQUAL] > '^' -+ [NCAPS RALT CTRL K_EQUAL] > '=' -+ [NCAPS CTRL K_EQUAL] > '=' -+ [NCAPS SHIFT RALT K_EQUAL] > '±' -c WARNING: ambiguous rule: later: [NCAPS RALT K_EQUAL] > dk(A2) here: + [NCAPS RALT K_EQUAL] > 'ˆ' -+ [CAPS RALT K_EQUAL] > 'ˆ' - -+ [NCAPS K_9] > '9' -c WARNING: ambiguous rule: later: [CAPS K_9] > dk(A5) here: + [CAPS K_9] > '9' -+ [NCAPS SHIFT K_9] > ')' -+ [SHIFT CAPS K_9] > ')' -+ [NCAPS RALT CTRL K_9] > '9' -+ [NCAPS CTRL K_9] > '9' -c WARNING: ambiguous rule: later: [NCAPS RALT K_9] > dk(A4) here: + [NCAPS RALT K_9] > '`' -+ [CAPS RALT K_9] > '`' - -+ [NCAPS K_7] > '7' -+ [CAPS K_7] > '7' -+ [NCAPS SHIFT K_7] > '/' -+ [SHIFT CAPS K_7] > '/' -+ [NCAPS RALT CTRL K_7] > '7' -+ [NCAPS CTRL K_7] > '7' -+ [NCAPS SHIFT RALT K_7] > '⁄' -+ [NCAPS RALT K_7] > '÷' -c WARNING: ambiguous rule: earlier: [CAPS K_7] > '7' here: + [CAPS K_7] > '÷' -+ [CAPS RALT K_7] > '÷' - -+ [NCAPS K_HYPHEN] > "'" -+ [CAPS K_HYPHEN] > "'" -+ [NCAPS SHIFT K_HYPHEN] > '?' -+ [SHIFT CAPS K_HYPHEN] > '?' -c WARNING: Use of a control character + [NCAPS RALT CTRL K_HYPHEN] > U+001F -c WARNING: Use of a control character + [NCAPS CTRL K_HYPHEN] > U+001F -+ [NCAPS SHIFT RALT K_HYPHEN] > '¿' -+ [NCAPS RALT K_HYPHEN] > '¡' -c WARNING: ambiguous rule: earlier: [CAPS K_HYPHEN] > ''' here: + [CAPS K_HYPHEN] > '¡' -+ [CAPS RALT K_HYPHEN] > '¡' - -+ [NCAPS K_8] > '8' -c WARNING: ambiguous rule: later: [CAPS K_8] > dk(C13) ambiguous rule: later: [CAPS K_8] > dk(A13) here: + [CAPS K_8] > '8' -+ [NCAPS SHIFT K_8] > '(' -+ [SHIFT CAPS K_8] > '(' -+ [NCAPS RALT CTRL K_8] > '8' -+ [NCAPS CTRL K_8] > '8' -+ [NCAPS SHIFT RALT K_8] > '' -c WARNING: ambiguous rule: later: [NCAPS RALT K_8] > dk(C12) ambiguous rule: later: [NCAPS RALT K_8] > dk(A12) here: + [NCAPS RALT K_8] > '´' -+ [CAPS RALT K_8] > '´' - -+ [NCAPS K_0] > '0' -+ [CAPS K_0] > '0' -+ [NCAPS SHIFT K_0] > '=' -+ [SHIFT CAPS K_0] > '=' -+ [NCAPS RALT CTRL K_0] > '0' -+ [NCAPS CTRL K_0] > '0' -+ [NCAPS SHIFT RALT K_0] > '≈' -+ [NCAPS RALT K_0] > '≠' -c WARNING: ambiguous rule: earlier: [CAPS K_0] > '0' here: + [CAPS K_0] > '≠' -+ [CAPS RALT K_0] > '≠' - -+ [NCAPS K_RBRKT] > '+' -+ [CAPS K_RBRKT] > '+' -+ [NCAPS SHIFT K_RBRKT] > '*' -+ [SHIFT CAPS K_RBRKT] > '*' -c WARNING: Use of a control character + [NCAPS RALT CTRL K_RBRKT] > U+001D -c WARNING: Use of a control character + [NCAPS CTRL K_RBRKT] > U+001D -+ [NCAPS SHIFT RALT K_RBRKT] > '}' -+ [NCAPS RALT K_RBRKT] > ']' -c WARNING: ambiguous rule: earlier: [CAPS K_RBRKT] > '+' here: + [CAPS K_RBRKT] > ']' -+ [CAPS RALT K_RBRKT] > ']' -+ [NCAPS K_O] > 'o' -+ [CAPS K_O] > 'O' -+ [NCAPS SHIFT K_O] > 'O' -+ [SHIFT CAPS K_O] > 'O' -c WARNING: Use of a control character + [NCAPS RALT CTRL K_O] > U+000F -c WARNING: Use of a control character + [NCAPS CTRL K_O] > U+000F -+ [NCAPS SHIFT RALT K_O] > 'Ø' -+ [NCAPS RALT K_O] > 'ø' -c WARNING: ambiguous rule: earlier: [CAPS K_O] > 'O' here: + [CAPS K_O] > 'ø' -+ [CAPS RALT K_O] > 'Ø' -+ [NCAPS K_U] > 'u' -c WARNING: ambiguous rule: later: [CAPS K_U] > dk(A9) here: + [CAPS K_U] > 'U' -+ [NCAPS SHIFT K_U] > 'U' -+ [SHIFT CAPS K_U] > 'U' -c WARNING: Use of a control character + [NCAPS RALT CTRL K_U] > U+0015 -c WARNING: Use of a control character + [NCAPS CTRL K_U] > U+0015 -+ [NCAPS SHIFT RALT K_U] > 'Ù' -c WARNING: ambiguous rule: later: [NCAPS RALT K_U] > dk(A8) here: + [NCAPS RALT K_U] > '¨' -+ [CAPS RALT K_U] > '¨' - -+ [NCAPS K_LBRKT] > 'è' -+ [CAPS K_LBRKT] > 'è' -+ [NCAPS SHIFT K_LBRKT] > 'é' -+ [SHIFT CAPS K_LBRKT] > 'é' -c WARNING: Use of a control character + [NCAPS RALT CTRL K_LBRKT] > U+001E -c WARNING: Use of a control character + [NCAPS CTRL K_LBRKT] > U+001E -+ [NCAPS SHIFT RALT K_LBRKT] > '{' -+ [NCAPS RALT K_LBRKT] > '[' -c WARNING: ambiguous rule: earlier: [CAPS K_LBRKT] > 'è' here: + [CAPS K_LBRKT] > '[' -+ [CAPS RALT K_LBRKT] > '[' -+ [NCAPS K_I] > 'i' -+ [CAPS K_I] > 'I' -+ [NCAPS SHIFT K_I] > 'I' -+ [SHIFT CAPS K_I] > 'I' -c WARNING: Use of a control character + [NCAPS RALT CTRL K_I] > U+0009 -c WARNING: Use of a control character + [NCAPS CTRL K_I] > U+0009 -+ [NCAPS SHIFT RALT K_I] > 'Œ' -+ [NCAPS RALT K_I] > 'œ' -c WARNING: ambiguous rule: earlier: [CAPS K_I] > 'I' here: + [CAPS K_I] > 'œ' -+ [CAPS RALT K_I] > 'Œ' - -+ [NCAPS K_P] > 'p' -+ [CAPS K_P] > 'P' -+ [NCAPS SHIFT K_P] > 'P' -+ [SHIFT CAPS K_P] > 'P' -c WARNING: Use of a control character + [NCAPS RALT CTRL K_P] > U+0010 -c WARNING: Use of a control character + [NCAPS CTRL K_P] > U+0010 -+ [NCAPS SHIFT RALT K_P] > '∏' -+ [NCAPS RALT K_P] > 'π' -c WARNING: ambiguous rule: earlier: [CAPS K_P] > 'P' here: + [CAPS K_P] > 'π' -+ [CAPS RALT K_P] > '∏' - -+ [NCAPS K_L] > 'l' -+ [CAPS K_L] > 'L' -+ [NCAPS SHIFT K_L] > 'L' -+ [SHIFT CAPS K_L] > 'L' -c WARNING: Use of a control character + [NCAPS RALT CTRL K_L] > U+000C -c WARNING: Use of a control character + [NCAPS CTRL K_L] > U+000C -+ [NCAPS SHIFT RALT K_L] > 'ˇ' -+ [NCAPS RALT K_L] > '¬' -c WARNING: ambiguous rule: earlier: [CAPS K_L] > 'L' here: + [CAPS K_L] > '¬' -+ [CAPS RALT K_L] > '¬' - -+ [NCAPS K_J] > 'j' -+ [CAPS K_J] > 'J' -+ [NCAPS SHIFT K_J] > 'J' -+ [SHIFT CAPS K_J] > 'J' -c WARNING: Use of a control character + [NCAPS RALT CTRL K_J] > U+000A -c WARNING: Use of a control character + [NCAPS CTRL K_J] > U+000A -+ [NCAPS SHIFT RALT K_J] > '˝' -+ [NCAPS RALT K_J] > 'ª' -c WARNING: ambiguous rule: earlier: [CAPS K_J] > 'J' here: + [CAPS K_J] > 'ª' -+ [CAPS RALT K_J] > 'ª' - -+ [NCAPS K_QUOTE] > 'à' -+ [CAPS K_QUOTE] > 'à' -+ [NCAPS SHIFT K_QUOTE] > '°' -+ [SHIFT CAPS K_QUOTE] > '°' -+ [NCAPS RALT CTRL K_QUOTE] > '%' -+ [NCAPS CTRL K_QUOTE] > '%' -+ [NCAPS SHIFT RALT K_QUOTE] > '∞' -+ [NCAPS RALT K_QUOTE] > '#' -c WARNING: ambiguous rule: earlier: [CAPS K_QUOTE] > 'à' here: + [CAPS K_QUOTE] > '#' -+ [CAPS RALT K_QUOTE] > '#' - -+ [NCAPS K_K] > 'k' -+ [CAPS K_K] > 'K' -+ [NCAPS SHIFT K_K] > 'K' -+ [SHIFT CAPS K_K] > 'K' -c WARNING: Use of a control character + [NCAPS RALT CTRL K_K] > U+000B -c WARNING: Use of a control character + [NCAPS CTRL K_K] > U+000B -+ [NCAPS SHIFT RALT K_K] > '˛' -+ [NCAPS RALT K_K] > 'º' -c WARNING: ambiguous rule: earlier: [CAPS K_K] > 'K' here: + [CAPS K_K] > 'º' -+ [CAPS RALT K_K] > 'º' - -+ [NCAPS K_COLON] > 'ò' -+ [CAPS K_COLON] > 'ò' -+ [NCAPS SHIFT K_COLON] > 'ç' -+ [SHIFT CAPS K_COLON] > 'ç' -c WARNING: Use of a control character + [NCAPS RALT CTRL K_COLON] > U+000D -c WARNING: Use of a control character + [NCAPS CTRL K_COLON] > U+000D -+ [NCAPS SHIFT RALT K_COLON] > 'Ç' -+ [NCAPS RALT K_COLON] > '@' -c WARNING: ambiguous rule: earlier: [CAPS K_COLON] > 'ò' here: + [CAPS K_COLON] > '@' -+ [CAPS RALT K_COLON] > '@' - -+ [NCAPS K_BKSLASH] > 'ù' -+ [CAPS K_BKSLASH] > 'ù' -+ [NCAPS SHIFT K_BKSLASH] > '§' -+ [SHIFT CAPS K_BKSLASH] > '§' -+ [NCAPS RALT CTRL K_BKSLASH] > '°' -+ [NCAPS CTRL K_BKSLASH] > '°' -+ [NCAPS SHIFT RALT K_BKSLASH] > '◊' -+ [NCAPS RALT K_BKSLASH] > '¶' -c WARNING: ambiguous rule: earlier: [CAPS K_BKSLASH] > 'ù' here: + [CAPS K_BKSLASH] > '¶' -+ [CAPS RALT K_BKSLASH] > '¶' - -+ [NCAPS K_COMMA] > ',' -+ [CAPS K_COMMA] > ',' -+ [NCAPS SHIFT K_COMMA] > ';' -+ [SHIFT CAPS K_COMMA] > ';' -+ [NCAPS RALT CTRL K_COMMA] > '.' -+ [NCAPS CTRL K_COMMA] > '.' -+ [NCAPS RALT K_COMMA] > '…' -c WARNING: ambiguous rule: earlier: [CAPS K_COMMA] > ',' here: + [CAPS K_COMMA] > '…' -+ [CAPS RALT K_COMMA] > '…' - -+ [NCAPS K_SLASH] > '-' -+ [CAPS K_SLASH] > '-' -+ [NCAPS SHIFT K_SLASH] > '_' -+ [SHIFT CAPS K_SLASH] > '_' -+ [NCAPS RALT CTRL K_SLASH] > '!' -+ [NCAPS CTRL K_SLASH] > '!' -+ [NCAPS SHIFT RALT K_SLASH] > '—' -+ [NCAPS RALT K_SLASH] > '–' -c WARNING: ambiguous rule: earlier: [CAPS K_SLASH] > '-' here: + [CAPS K_SLASH] > '–' -+ [CAPS RALT K_SLASH] > '–' -+ [NCAPS K_N] > 'n' -c WARNING: ambiguous rule: later: [CAPS K_N] > dk(A11) here: + [CAPS K_N] > 'N' -+ [NCAPS SHIFT K_N] > 'N' -+ [SHIFT CAPS K_N] > 'N' -c WARNING: Use of a control character + [NCAPS RALT CTRL K_N] > U+000E -c WARNING: Use of a control character + [NCAPS CTRL K_N] > U+000E -+ [NCAPS SHIFT RALT K_N] > 'Ó' -c WARNING: ambiguous rule: later: [NCAPS RALT K_N] > dk(A10) here: + [NCAPS RALT K_N] > '˜' -+ [CAPS RALT K_N] > '˜' - -+ [NCAPS K_M] > 'm' -+ [CAPS K_M] > 'M' -+ [NCAPS SHIFT K_M] > 'M' -+ [SHIFT CAPS K_M] > 'M' -+ [NCAPS RALT CTRL K_M] > '?' -+ [NCAPS CTRL K_M] > '?' -+ [NCAPS SHIFT RALT K_M] > 'Ú' -+ [NCAPS RALT K_M] > 'µ' -c WARNING: ambiguous rule: earlier: [CAPS K_M] > 'M' here: + [CAPS K_M] > 'µ' -+ [CAPS RALT K_M] > 'µ' - -+ [NCAPS K_PERIOD] > '.' -+ [CAPS K_PERIOD] > '.' -+ [NCAPS SHIFT K_PERIOD] > ':' -+ [SHIFT CAPS K_PERIOD] > ':' -+ [NCAPS RALT CTRL K_PERIOD] > '/' -+ [NCAPS CTRL K_PERIOD] > '/' -+ [NCAPS SHIFT RALT K_PERIOD] > '·' -+ [NCAPS RALT K_PERIOD] > '•' -c WARNING: ambiguous rule: earlier: [CAPS K_PERIOD] > '.' here: + [CAPS K_PERIOD] > '•' -+ [CAPS RALT K_PERIOD] > '•' - -+ [NCAPS SHIFT RALT K_SPACE] > ' ' -+ [NCAPS RALT K_SPACE] > ' ' -c WARNING: ambiguous rule: earlier: [CAPS K_SPACE] > ' ' here: + [CAPS K_SPACE] > ' ' -+ [CAPS RALT K_SPACE] > ' ' -+ [NCAPS K_EQUAL] > dk(A1) -dk(A1) + [NCAPS K_SPACE] > 'ˆ' - -dk(A1) + [CAPS K_SPACE] > 'ˆ' - -dk(A1) + [NCAPS SHIFT K_SPACE] > 'ˆ' - -dk(A1) + [SHIFT CAPS K_SPACE] > 'ˆ' - -dk(A1) + [NCAPS RALT CTRL K_SPACE] > 'ˆ' - -dk(A1) + [NCAPS CTRL K_SPACE] > 'ˆ' - -dk(A1) + [NCAPS SHIFT RALT K_Z] > 'ˆ' - -dk(A1) + [NCAPS SHIFT RALT K_9] > 'ˆ' - -dk(A1) + [NCAPS SHIFT RALT K_COMMA] > 'ˆ' - -dk(A1) + [CAPS K_A] > 'Â' - -dk(A1) + [NCAPS SHIFT K_A] > 'Â' - -dk(A1) + [SHIFT CAPS K_A] > 'Â' - -dk(A1) + [NCAPS K_E] > 'ê' - -dk(A1) + [NCAPS K_I] > 'î' - -dk(A1) + [NCAPS K_O] > 'ô' - -dk(A1) + [NCAPS K_U] > 'û' - -dk(A1) + [CAPS K_E] > 'Ê' - -dk(A1) + [NCAPS SHIFT K_E] > 'Ê' - -dk(A1) + [SHIFT CAPS K_E] > 'Ê' - -dk(A1) + [CAPS K_I] > 'Î' - -dk(A1) + [NCAPS SHIFT K_I] > 'Î' - -dk(A1) + [SHIFT CAPS K_I] > 'Î' - -dk(A1) + [CAPS K_O] > 'Ô' - -dk(A1) + [NCAPS SHIFT K_O] > 'Ô' - -dk(A1) + [SHIFT CAPS K_O] > 'Ô' - -dk(A1) + [CAPS K_U] > 'Û' - -dk(A1) + [NCAPS SHIFT K_U] > 'Û' - -dk(A1) + [SHIFT CAPS K_U] > 'Û' - -dk(A1) + [NCAPS K_A] > 'â' - -+ [NCAPS RALT K_EQUAL] > dk(A2) -dk(A2) + [NCAPS K_SPACE] > 'ˆ' - -dk(A2) + [CAPS K_SPACE] > 'ˆ' - -dk(A2) + [NCAPS SHIFT K_SPACE] > 'ˆ' - -dk(A2) + [SHIFT CAPS K_SPACE] > 'ˆ' - -dk(A2) + [NCAPS RALT CTRL K_SPACE] > 'ˆ' - -dk(A2) + [NCAPS CTRL K_SPACE] > 'ˆ' - -dk(A2) + [NCAPS SHIFT RALT K_Z] > 'ˆ' - -dk(A2) + [NCAPS SHIFT RALT K_9] > 'ˆ' - -dk(A2) + [NCAPS SHIFT RALT K_COMMA] > 'ˆ' - -dk(A2) + [CAPS K_A] > 'Â' - -dk(A2) + [NCAPS SHIFT K_A] > 'Â' - -dk(A2) + [SHIFT CAPS K_A] > 'Â' - -dk(A2) + [NCAPS K_E] > 'ê' - -dk(A2) + [NCAPS K_I] > 'î' - -dk(A2) + [NCAPS K_O] > 'ô' - -dk(A2) + [NCAPS K_U] > 'û' - -dk(A2) + [CAPS K_E] > 'Ê' - -dk(A2) + [NCAPS SHIFT K_E] > 'Ê' - -dk(A2) + [SHIFT CAPS K_E] > 'Ê' - -dk(A2) + [CAPS K_I] > 'Î' - -dk(A2) + [NCAPS SHIFT K_I] > 'Î' - -dk(A2) + [SHIFT CAPS K_I] > 'Î' - -dk(A2) + [CAPS K_O] > 'Ô' - -dk(A2) + [NCAPS SHIFT K_O] > 'Ô' - -dk(A2) + [SHIFT CAPS K_O] > 'Ô' - -dk(A2) + [CAPS K_U] > 'Û' - -dk(A2) + [NCAPS SHIFT K_U] > 'Û' - -dk(A2) + [SHIFT CAPS K_U] > 'Û' - -dk(A2) + [NCAPS K_A] > 'â' - -+ [CAPS K_EQUAL] > dk(A3) -dk(A3) + [NCAPS K_SPACE] > 'ˆ' - -dk(A3) + [CAPS K_SPACE] > 'ˆ' - -dk(A3) + [NCAPS SHIFT K_SPACE] > 'ˆ' - -dk(A3) + [SHIFT CAPS K_SPACE] > 'ˆ' - -dk(A3) + [NCAPS RALT CTRL K_SPACE] > 'ˆ' - -dk(A3) + [NCAPS CTRL K_SPACE] > 'ˆ' - -dk(A3) + [NCAPS SHIFT RALT K_Z] > 'ˆ' - -dk(A3) + [NCAPS SHIFT RALT K_9] > 'ˆ' - -dk(A3) + [NCAPS SHIFT RALT K_COMMA] > 'ˆ' - -dk(A3) + [CAPS K_A] > 'Â' - -dk(A3) + [NCAPS SHIFT K_A] > 'Â' - -dk(A3) + [SHIFT CAPS K_A] > 'Â' - -dk(A3) + [NCAPS K_E] > 'ê' - -dk(A3) + [NCAPS K_I] > 'î' - -dk(A3) + [NCAPS K_O] > 'ô' - -dk(A3) + [NCAPS K_U] > 'û' - -dk(A3) + [CAPS K_E] > 'Ê' - -dk(A3) + [NCAPS SHIFT K_E] > 'Ê' - -dk(A3) + [SHIFT CAPS K_E] > 'Ê' - -dk(A3) + [CAPS K_I] > 'Î' - -dk(A3) + [NCAPS SHIFT K_I] > 'Î' - -dk(A3) + [SHIFT CAPS K_I] > 'Î' - -dk(A3) + [CAPS K_O] > 'Ô' - -dk(A3) + [NCAPS SHIFT K_O] > 'Ô' - -dk(A3) + [SHIFT CAPS K_O] > 'Ô' - -dk(A3) + [CAPS K_U] > 'Û' - -dk(A3) + [NCAPS SHIFT K_U] > 'Û' - -dk(A3) + [SHIFT CAPS K_U] > 'Û' - -dk(A3) + [NCAPS K_A] > 'â' - -+ [NCAPS RALT K_9] > dk(A4) -dk(A4) + [NCAPS K_SPACE] > '`' - -dk(A4) + [CAPS K_SPACE] > '`' - -dk(A4) + [NCAPS SHIFT K_SPACE] > '`' - -dk(A4) + [SHIFT CAPS K_SPACE] > '`' - -dk(A4) + [NCAPS RALT CTRL K_SPACE] > '`' - -dk(A4) + [NCAPS CTRL K_SPACE] > '`' - -dk(A4) + [NCAPS SHIFT RALT K_Z] > '`' - -dk(A4) + [NCAPS SHIFT RALT K_9] > '`' - -dk(A4) + [NCAPS SHIFT RALT K_COMMA] > '`' - -dk(A4) + [CAPS K_A] > 'À' - -dk(A4) + [NCAPS SHIFT K_A] > 'À' - -dk(A4) + [SHIFT CAPS K_A] > 'À' - -dk(A4) + [NCAPS K_E] > 'è' - -dk(A4) + [NCAPS K_I] > 'ì' - -dk(A4) + [NCAPS K_O] > 'ò' - -dk(A4) + [NCAPS K_U] > 'ù' - -dk(A4) + [CAPS K_E] > 'È' - -dk(A4) + [NCAPS SHIFT K_E] > 'È' - -dk(A4) + [SHIFT CAPS K_E] > 'È' - -dk(A4) + [CAPS K_I] > 'Ì' - -dk(A4) + [NCAPS SHIFT K_I] > 'Ì' - -dk(A4) + [SHIFT CAPS K_I] > 'Ì' - -dk(A4) + [CAPS K_O] > 'Ò' - -dk(A4) + [NCAPS SHIFT K_O] > 'Ò' - -dk(A4) + [SHIFT CAPS K_O] > 'Ò' - -dk(A4) + [CAPS K_U] > 'Ù' - -dk(A4) + [NCAPS SHIFT K_U] > 'Ù' - -dk(A4) + [SHIFT CAPS K_U] > 'Ù' - -dk(A4) + [NCAPS K_A] > 'à' - -+ [CAPS K_9] > dk(A5) -dk(A5) + [NCAPS K_SPACE] > '`' - -dk(A5) + [CAPS K_SPACE] > '`' - -dk(A5) + [NCAPS SHIFT K_SPACE] > '`' - -dk(A5) + [SHIFT CAPS K_SPACE] > '`' - -dk(A5) + [NCAPS RALT CTRL K_SPACE] > '`' - -dk(A5) + [NCAPS CTRL K_SPACE] > '`' - -dk(A5) + [NCAPS SHIFT RALT K_Z] > '`' - -dk(A5) + [NCAPS SHIFT RALT K_9] > '`' - -dk(A5) + [NCAPS SHIFT RALT K_COMMA] > '`' - -dk(A5) + [CAPS K_A] > 'À' - -dk(A5) + [NCAPS SHIFT K_A] > 'À' - -dk(A5) + [SHIFT CAPS K_A] > 'À' - -dk(A5) + [NCAPS K_E] > 'è' - -dk(A5) + [NCAPS K_I] > 'ì' - -dk(A5) + [NCAPS K_O] > 'ò' - -dk(A5) + [NCAPS K_U] > 'ù' - -dk(A5) + [CAPS K_E] > 'È' - -dk(A5) + [NCAPS SHIFT K_E] > 'È' - -dk(A5) + [SHIFT CAPS K_E] > 'È' - -dk(A5) + [CAPS K_I] > 'Ì' - -dk(A5) + [NCAPS SHIFT K_I] > 'Ì' - -dk(A5) + [SHIFT CAPS K_I] > 'Ì' - -dk(A5) + [CAPS K_O] > 'Ò' - -dk(A5) + [NCAPS SHIFT K_O] > 'Ò' - -dk(A5) + [SHIFT CAPS K_O] > 'Ò' - -dk(A5) + [CAPS K_U] > 'Ù' - -dk(A5) + [NCAPS SHIFT K_U] > 'Ù' - -dk(A5) + [SHIFT CAPS K_U] > 'Ù' - -dk(A5) + [NCAPS K_A] > 'à' - -+ [NCAPS RALT K_8] > dk(A12) -dk(A12) + [NCAPS K_SPACE] > '´' - -dk(A12) + [CAPS K_SPACE] > '´' - -dk(A12) + [NCAPS SHIFT K_SPACE] > '´' - -dk(A12) + [SHIFT CAPS K_SPACE] > '´' - -dk(A12) + [NCAPS RALT CTRL K_SPACE] > '´' - -dk(A12) + [NCAPS CTRL K_SPACE] > '´' - -dk(A12) + [NCAPS SHIFT RALT K_Z] > '´' - -dk(A12) + [NCAPS SHIFT RALT K_9] > '´' - -dk(A12) + [NCAPS SHIFT RALT K_COMMA] > '´' - -dk(A12) + [CAPS K_A] > 'Á' - -dk(A12) + [NCAPS SHIFT K_A] > 'Á' - -dk(A12) + [SHIFT CAPS K_A] > 'Á' - -dk(A12) + [NCAPS K_E] > 'é' - -dk(A12) + [NCAPS K_I] > 'í' - -dk(A12) + [NCAPS K_O] > 'ó' - -dk(A12) + [NCAPS K_U] > 'ú' - -dk(A12) + [CAPS K_E] > 'É' - -dk(A12) + [NCAPS SHIFT K_E] > 'É' - -dk(A12) + [SHIFT CAPS K_E] > 'É' - -dk(A12) + [CAPS K_I] > 'Í' - -dk(A12) + [NCAPS SHIFT K_I] > 'Í' - -dk(A12) + [SHIFT CAPS K_I] > 'Í' - -dk(A12) + [CAPS K_O] > 'Ó' - -dk(A12) + [NCAPS SHIFT K_O] > 'Ó' - -dk(A12) + [SHIFT CAPS K_O] > 'Ó' - -dk(A12) + [CAPS K_U] > 'Ú' - -dk(A12) + [NCAPS SHIFT K_U] > 'Ú' - -dk(A12) + [SHIFT CAPS K_U] > 'Ú' - -dk(A12) + [NCAPS K_A] > 'á' - -+ [CAPS K_8] > dk(A13) -dk(A13) + [NCAPS K_SPACE] > '´' - -dk(A13) + [CAPS K_SPACE] > '´' - -dk(A13) + [NCAPS SHIFT K_SPACE] > '´' - -dk(A13) + [SHIFT CAPS K_SPACE] > '´' - -dk(A13) + [NCAPS RALT CTRL K_SPACE] > '´' - -dk(A13) + [NCAPS CTRL K_SPACE] > '´' - -dk(A13) + [NCAPS SHIFT RALT K_Z] > '´' - -dk(A13) + [NCAPS SHIFT RALT K_9] > '´' - -dk(A13) + [NCAPS SHIFT RALT K_COMMA] > '´' - -dk(A13) + [CAPS K_A] > 'Á' - -dk(A13) + [NCAPS SHIFT K_A] > 'Á' - -dk(A13) + [SHIFT CAPS K_A] > 'Á' - -dk(A13) + [NCAPS K_E] > 'é' - -dk(A13) + [NCAPS K_I] > 'í' - -dk(A13) + [NCAPS K_O] > 'ó' - -dk(A13) + [NCAPS K_U] > 'ú' - -dk(A13) + [CAPS K_E] > 'É' - -dk(A13) + [NCAPS SHIFT K_E] > 'É' - -dk(A13) + [SHIFT CAPS K_E] > 'É' - -dk(A13) + [CAPS K_I] > 'Í' - -dk(A13) + [NCAPS SHIFT K_I] > 'Í' - -dk(A13) + [SHIFT CAPS K_I] > 'Í' - -dk(A13) + [CAPS K_O] > 'Ó' - -dk(A13) + [NCAPS SHIFT K_O] > 'Ó' - -dk(A13) + [SHIFT CAPS K_O] > 'Ó' - -dk(A13) + [CAPS K_U] > 'Ú' - -dk(A13) + [NCAPS SHIFT K_U] > 'Ú' - -dk(A13) + [SHIFT CAPS K_U] > 'Ú' - -dk(A13) + [NCAPS K_A] > 'á' - -+ [NCAPS RALT K_U] > dk(A8) -dk(A8) + [NCAPS K_SPACE] > '¨' - -dk(A8) + [CAPS K_SPACE] > '¨' - -dk(A8) + [NCAPS SHIFT K_SPACE] > '¨' - -dk(A8) + [SHIFT CAPS K_SPACE] > '¨' - -dk(A8) + [NCAPS RALT CTRL K_SPACE] > '¨' - -dk(A8) + [NCAPS CTRL K_SPACE] > '¨' - -dk(A8) + [NCAPS SHIFT RALT K_Z] > '¨' - -dk(A8) + [NCAPS SHIFT RALT K_9] > '¨' - -dk(A8) + [NCAPS SHIFT RALT K_COMMA] > '¨' - -dk(A8) + [CAPS K_A] > 'Ä' - -dk(A8) + [NCAPS SHIFT K_A] > 'Ä' - -dk(A8) + [SHIFT CAPS K_A] > 'Ä' - -dk(A8) + [NCAPS K_E] > 'ë' - -dk(A8) + [NCAPS K_I] > 'ï' - -dk(A8) + [NCAPS K_O] > 'ö' - -dk(A8) + [NCAPS K_U] > 'ü' - -dk(A8) + [NCAPS K_Y] > 'ÿ' - -dk(A8) + [CAPS K_E] > 'Ë' - -dk(A8) + [NCAPS SHIFT K_E] > 'Ë' - -dk(A8) + [SHIFT CAPS K_E] > 'Ë' - -dk(A8) + [CAPS K_I] > 'Ï' - -dk(A8) + [NCAPS SHIFT K_I] > 'Ï' - -dk(A8) + [SHIFT CAPS K_I] > 'Ï' - -dk(A8) + [CAPS K_O] > 'Ö' - -dk(A8) + [NCAPS SHIFT K_O] > 'Ö' - -dk(A8) + [SHIFT CAPS K_O] > 'Ö' - -dk(A8) + [CAPS K_U] > 'Ü' - -dk(A8) + [NCAPS SHIFT K_U] > 'Ü' - -dk(A8) + [SHIFT CAPS K_U] > 'Ü' - -dk(A8) + [CAPS K_Y] > 'Ÿ' - -dk(A8) + [NCAPS SHIFT K_Y] > 'Ÿ' - -dk(A8) + [SHIFT CAPS K_Y] > 'Ÿ' - -dk(A8) + [NCAPS K_A] > 'ä' - -+ [CAPS K_U] > dk(A9) -dk(A9) + [NCAPS K_SPACE] > '¨' - -dk(A9) + [CAPS K_SPACE] > '¨' - -dk(A9) + [NCAPS SHIFT K_SPACE] > '¨' - -dk(A9) + [SHIFT CAPS K_SPACE] > '¨' - -dk(A9) + [NCAPS RALT CTRL K_SPACE] > '¨' - -dk(A9) + [NCAPS CTRL K_SPACE] > '¨' - -dk(A9) + [NCAPS SHIFT RALT K_Z] > '¨' - -dk(A9) + [NCAPS SHIFT RALT K_9] > '¨' - -dk(A9) + [NCAPS SHIFT RALT K_COMMA] > '¨' - -dk(A9) + [CAPS K_A] > 'Ä' - -dk(A9) + [NCAPS SHIFT K_A] > 'Ä' - -dk(A9) + [SHIFT CAPS K_A] > 'Ä' - -dk(A9) + [NCAPS K_E] > 'ë' - -dk(A9) + [NCAPS K_I] > 'ï' - -dk(A9) + [NCAPS K_O] > 'ö' - -dk(A9) + [NCAPS K_U] > 'ü' - -dk(A9) + [NCAPS K_Y] > 'ÿ' - -dk(A9) + [CAPS K_E] > 'Ë' - -dk(A9) + [NCAPS SHIFT K_E] > 'Ë' - -dk(A9) + [SHIFT CAPS K_E] > 'Ë' - -dk(A9) + [CAPS K_I] > 'Ï' - -dk(A9) + [NCAPS SHIFT K_I] > 'Ï' - -dk(A9) + [SHIFT CAPS K_I] > 'Ï' - -dk(A9) + [CAPS K_O] > 'Ö' - -dk(A9) + [NCAPS SHIFT K_O] > 'Ö' - -dk(A9) + [SHIFT CAPS K_O] > 'Ö' - -dk(A9) + [CAPS K_U] > 'Ü' - -dk(A9) + [NCAPS SHIFT K_U] > 'Ü' - -dk(A9) + [SHIFT CAPS K_U] > 'Ü' - -dk(A9) + [CAPS K_Y] > 'Ÿ' - -dk(A9) + [NCAPS SHIFT K_Y] > 'Ÿ' - -dk(A9) + [SHIFT CAPS K_Y] > 'Ÿ' - -dk(A9) + [NCAPS K_A] > 'ä' - -+ [NCAPS RALT K_N] > dk(A10) -dk(A10) + [NCAPS K_SPACE] > '˜' - -dk(A10) + [CAPS K_SPACE] > '˜' - -dk(A10) + [NCAPS SHIFT K_SPACE] > '˜' - -dk(A10) + [SHIFT CAPS K_SPACE] > '˜' - -dk(A10) + [NCAPS RALT CTRL K_SPACE] > '˜' - -dk(A10) + [NCAPS CTRL K_SPACE] > '˜' - -dk(A10) + [NCAPS SHIFT RALT K_Z] > '˜' - -dk(A10) + [NCAPS SHIFT RALT K_9] > '˜' - -dk(A10) + [NCAPS SHIFT RALT K_COMMA] > '˜' - -dk(A10) + [CAPS K_A] > 'Ã' - -dk(A10) + [NCAPS SHIFT K_A] > 'Ã' - -dk(A10) + [SHIFT CAPS K_A] > 'Ã' - -dk(A10) + [NCAPS K_N] > 'ñ' - -dk(A10) + [NCAPS K_O] > 'õ' - -dk(A10) + [CAPS K_N] > 'Ñ' - -dk(A10) + [NCAPS SHIFT K_N] > 'Ñ' - -dk(A10) + [SHIFT CAPS K_N] > 'Ñ' - -dk(A10) + [CAPS K_O] > 'Õ' - -dk(A10) + [NCAPS SHIFT K_O] > 'Õ' - -dk(A10) + [SHIFT CAPS K_O] > 'Õ' - -dk(A10) + [NCAPS K_A] > 'ã' - -+ [CAPS K_N] > dk(A11) -dk(A11) + [NCAPS K_SPACE] > '˜' - -dk(A11) + [CAPS K_SPACE] > '˜' - -dk(A11) + [NCAPS SHIFT K_SPACE] > '˜' - -dk(A11) + [SHIFT CAPS K_SPACE] > '˜' - -dk(A11) + [NCAPS RALT CTRL K_SPACE] > '˜' - -dk(A11) + [NCAPS CTRL K_SPACE] > '˜' - -dk(A11) + [NCAPS SHIFT RALT K_Z] > '˜' - -dk(A11) + [NCAPS SHIFT RALT K_9] > '˜' - -dk(A11) + [NCAPS SHIFT RALT K_COMMA] > '˜' - -dk(A11) + [CAPS K_A] > 'Ã' - -dk(A11) + [NCAPS SHIFT K_A] > 'Ã' - -dk(A11) + [SHIFT CAPS K_A] > 'Ã' - -dk(A11) + [NCAPS K_N] > 'ñ' - -dk(A11) + [NCAPS K_O] > 'õ' - -dk(A11) + [CAPS K_N] > 'Ñ' - -dk(A11) + [NCAPS SHIFT K_N] > 'Ñ' - -dk(A11) + [SHIFT CAPS K_N] > 'Ñ' - -dk(A11) + [CAPS K_O] > 'Õ' - -dk(A11) + [NCAPS SHIFT K_O] > 'Õ' - -dk(A11) + [SHIFT CAPS K_O] > 'Õ' - -dk(A11) + [NCAPS K_A] > 'ã' - -c WARNING: ambiguous rule: earlier: [NCAPS RALT K_8] > dk(A12) here: + [NCAPS RALT K_8] > dk(A12) -dk(A12) + [NCAPS RALT K_U] > dk(B8) -dk(B8) + [NCAPS K_SPACE] > 'ˆ' - -dk(B8) + [CAPS K_SPACE] > 'ˆ' - -dk(B8) + [NCAPS SHIFT K_SPACE] > 'ˆ' - -dk(B8) + [SHIFT CAPS K_SPACE] > 'ˆ' - -dk(B8) + [NCAPS RALT CTRL K_SPACE] > 'ˆ' - -dk(B8) + [NCAPS CTRL K_SPACE] > 'ˆ' - -dk(B8) + [NCAPS SHIFT RALT K_Z] > 'ˆ' - -dk(B8) + [NCAPS SHIFT RALT K_9] > 'ˆ' - -dk(B8) + [NCAPS SHIFT RALT K_COMMA] > 'ˆ' - -dk(B8) + [CAPS K_A] > 'Â' - -dk(B8) + [NCAPS SHIFT K_A] > 'Â' - -dk(B8) + [SHIFT CAPS K_A] > 'Â' - -dk(B8) + [NCAPS K_E] > 'ê' - -dk(B8) + [NCAPS K_I] > 'î' - -dk(B8) + [NCAPS K_O] > 'ô' - -dk(B8) + [NCAPS K_U] > 'û' - -dk(B8) + [CAPS K_E] > 'Ê' - -dk(B8) + [NCAPS SHIFT K_E] > 'Ê' - -dk(B8) + [SHIFT CAPS K_E] > 'Ê' - -dk(B8) + [CAPS K_I] > 'Î' - -dk(B8) + [NCAPS SHIFT K_I] > 'Î' - -dk(B8) + [SHIFT CAPS K_I] > 'Î' - -dk(B8) + [CAPS K_O] > 'Ô' - -dk(B8) + [NCAPS SHIFT K_O] > 'Ô' - -dk(B8) + [SHIFT CAPS K_O] > 'Ô' - -dk(B8) + [CAPS K_U] > 'Û' - -dk(B8) + [NCAPS SHIFT K_U] > 'Û' - -dk(B8) + [SHIFT CAPS K_U] > 'Û' - -dk(B8) + [NCAPS K_A] > 'â' - -dk(A12) + [CAPS K_U] > dk(B9) -dk(B9) + [NCAPS K_SPACE] > 'ˆ' - -dk(B9) + [CAPS K_SPACE] > 'ˆ' - -dk(B9) + [NCAPS SHIFT K_SPACE] > 'ˆ' - -dk(B9) + [SHIFT CAPS K_SPACE] > 'ˆ' - -dk(B9) + [NCAPS RALT CTRL K_SPACE] > 'ˆ' - -dk(B9) + [NCAPS CTRL K_SPACE] > 'ˆ' - -dk(B9) + [NCAPS SHIFT RALT K_Z] > 'ˆ' - -dk(B9) + [NCAPS SHIFT RALT K_9] > 'ˆ' - -dk(B9) + [NCAPS SHIFT RALT K_COMMA] > 'ˆ' - -dk(B9) + [CAPS K_A] > 'Â' - -dk(B9) + [NCAPS SHIFT K_A] > 'Â' - -dk(B9) + [SHIFT CAPS K_A] > 'Â' - -dk(B9) + [NCAPS K_E] > 'ê' - -dk(B9) + [NCAPS K_I] > 'î' - -dk(B9) + [NCAPS K_O] > 'ô' - -dk(B9) + [NCAPS K_U] > 'û' - -dk(B9) + [CAPS K_E] > 'Ê' - -dk(B9) + [NCAPS SHIFT K_E] > 'Ê' - -dk(B9) + [SHIFT CAPS K_E] > 'Ê' - -dk(B9) + [CAPS K_I] > 'Î' - -dk(B9) + [NCAPS SHIFT K_I] > 'Î' - -dk(B9) + [SHIFT CAPS K_I] > 'Î' - -dk(B9) + [CAPS K_O] > 'Ô' - -dk(B9) + [NCAPS SHIFT K_O] > 'Ô' - -dk(B9) + [SHIFT CAPS K_O] > 'Ô' - -dk(B9) + [CAPS K_U] > 'Û' - -dk(B9) + [NCAPS SHIFT K_U] > 'Û' - -dk(B9) + [SHIFT CAPS K_U] > 'Û' - -dk(B9) + [NCAPS K_A] > 'â' - -c WARNING: ambiguous rule: earlier: [CAPS K_8] > dk(A13) here: + [CAPS K_8] > dk(A13) -dk(A13) + [NCAPS RALT K_U] > dk(B8) - -dk(A13) + [CAPS K_U] > dk(B9) - diff --git a/developer/src/kmc-convert/test/data/Test_differentEncodings.keylayout b/developer/src/kmc-convert/test/data/Test_differentEncodings.keylayout index 1868fce990..b5eb98fc34 100644 --- a/developer/src/kmc-convert/test/data/Test_differentEncodings.keylayout +++ b/developer/src/kmc-convert/test/data/Test_differentEncodings.keylayout @@ -24,6 +24,9 @@ + + + diff --git a/developer/src/kmc-convert/test/data/Test_sameKeyMapAndKeyMapselectAndJisERROR.keylayout b/developer/src/kmc-convert/test/data/Test_sameKeyMapAndKeyMapselectAndJisERROR.keylayout new file mode 100644 index 0000000000..ca02f833f0 --- /dev/null +++ b/developer/src/kmc-convert/test/data/Test_sameKeyMapAndKeyMapselectAndJisERROR.keylayout @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-convert/test/keylayout-file-reader.tests.ts b/developer/src/kmc-convert/test/keylayout-file-reader.tests.ts index c085e019ff..f9abe65d9c 100644 --- a/developer/src/kmc-convert/test/keylayout-file-reader.tests.ts +++ b/developer/src/kmc-convert/test/keylayout-file-reader.tests.ts @@ -12,6 +12,7 @@ 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'; +import { KL_KeyMap, KL_KeyMapSelect } from "../../common/web/utils/src/types/keylayout/keylayout-xml.js"; describe('KeylayoutFileReader', function () { @@ -27,6 +28,50 @@ describe('KeylayoutFileReader', function () { 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/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/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/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/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/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/Test_noActionWhen.keylayout'); + //const result: Keylayout.KeylayoutXMLSourceFile | null = sutR.read(compilerTestCallbacks.loadFile(inputFilename)); + const validated = sutR.validate(undefined, inputFilename); + assert.isFalse(validated); + }); }); describe('validate() should return false on inputfiles with errors ', function () { @@ -86,6 +131,84 @@ describe('KeylayoutFileReader', function () { }); }); + 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/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.equal(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/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.equal(result, values[1]); + }); + }); + }); + + describe('checkForCorrespondingElements ', function () { + const sutR = new KeylayoutFileReader(compilerTestCallbacks); + [ + ['../data/Test.keylayout', true], + ['../data/Test_sameKeyMapAndKeyMapselectAndJisERROR.keylayout', true], + ['../data/Test_moreKeymapSelectThanKeymapERROR.keylayout', false], + ['../data/Test_moreKeyMapThanKeyMapselectERROR.keylayout', false], + ['../data/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.equal(result, values[1]); + }); + }); + }); + describe("read() check structure of returned JSON", function () { it('read() should have the correct JSON structure', async function () { @@ -96,7 +219,7 @@ describe('KeylayoutFileReader', function () { const result: Keylayout.KeylayoutXMLSourceFile = sutR.read(binaryData); assert.isNotNull(result); - assert.isTrue(result.keyboard !== null); + assert.notEqual(result.keyboard, null); for (let i = 0; i < result.keyboard.layouts.length; i++) { assert.isTrue(result.keyboard.layouts[i].layout.length > 0); @@ -108,8 +231,8 @@ describe('KeylayoutFileReader', function () { for (let j = 0; j < result.keyboard.keyMapSet[i].keyMap.length; j++) { assert.isTrue(result.keyboard.keyMapSet[i].keyMap[j].key.length > 0); for (let k = 0; k < result.keyboard.keyMapSet[i].keyMap[j].key.length; k++) { - assert.isTrue(result.keyboard.keyMapSet[i].keyMap[j].key[k]['action'] !== null - || result.keyboard.keyMapSet[i].keyMap[j].key[k]['output'] !== null); + assert.isNotNull(result.keyboard.keyMapSet[i].keyMap[j].key[k]['action']); + assert.isNotNull(result.keyboard.keyMapSet[i].keyMap[j].key[k]['output']); } } } @@ -124,8 +247,8 @@ describe('KeylayoutFileReader', function () { for (let i = 0; i < result.keyboard.modifierMap.length; i++) { assert.isTrue(result.keyboard.modifierMap[i].keyMapSelect.length > 0); for (let j = 0; j < result.keyboard.keyMapSet.length; j++) { - assert.isTrue(result.keyboard.keyMapSet[j].keyMap.length - === result.keyboard.modifierMap[i].keyMapSelect.length); + assert.equal(result.keyboard.keyMapSet[j].keyMap.length, + result.keyboard.modifierMap[i].keyMapSelect.length); } } }); 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 9658d033cd..148f1f5b81 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 @@ -60,14 +60,13 @@ describe('KeylayoutToKmnConverter', function () { ['../data/Test.keylayout'], ].forEach(function (files) { it(files + " should give no errors ", async function () { - sut.run(makePathToFixture(files[0])); - // assert.isTrue(compilerTestCallbacks.messages.length === 1 && compilerTestCallbacks.messages[0].code === 5292037); + await sut.run(makePathToFixture(files[0])); assert.isTrue(compilerTestCallbacks.messages.length === 0); await sut.run(makePathToFixture(files[0])); assert.equal(compilerTestCallbacks.messages.length, 0); - }); - }); - }); + }); + }); + }); describe('RunTestFiles resulting in errors ', function () { const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); [ @@ -97,7 +96,7 @@ describe('KeylayoutToKmnConverter', function () { ['../data/Test_undefinedAction.keylayout'], ].forEach(function (files) { it(files + " should give Error: undefined action detected", async function () { - sut.run(makePathToFixture(files[0])); + await sut.run(makePathToFixture(files[0])); assert.equal(compilerTestCallbacks.messages.length, 1); assert.equal(compilerTestCallbacks.messages[0].code, 5292040); }); 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 8b841b6dad..64f0f3762c 100644 --- a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts +++ b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts @@ -63,7 +63,7 @@ describe('KmnFileWriter', function () { 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)); + assert.equal(writtenCorrectName, (outExpectedFirst + (converted?.keylayoutFilename ?? "") + outExpectedLast)); }); }); @@ -105,57 +105,48 @@ 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'))], [''], [''], - ['c WARNING: unavailable modifier : here: ']], + ['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: ']], + ['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: ']], + ['c WARNING: unavailable modifier here: ']], - [[new Rule("C2", '', '', 0, 0, 'UNAVAILABLE_dk', 'K_EQUAL', 0, 0, 'UNAVAILABLE', 'K_C', new TextEncoder().encode('C'),)], + [[new Rule("C2", '', '', 1, 1, 'UNAVAILABLE_dk', 'K_EQUAL', 2, 2, 'UNAVAILABLE', 'K_C', new TextEncoder().encode('C'),)], [''], - ['c WARNING: unavailable modifier : here: '], - ['c WARNING: unavailable modifier : here: ']], + ['c WARNING: unavailable modifier here: '], + ['c WARNING: unavailable superior rule ( [UNAVAILABLE_dk K_EQUAL] > dk(A2) ) : 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', 1, 1, 'UNAVAILABLE_dk', 'K_EQUAL', 0, 0, 'SHIFT', 'K_C', new TextEncoder().encode('D'),)], + ['c WARNING: unavailable modifier here: '], + ['c WARNING: unavailable superior rule ( [UNAVAILABLE_prev_dk K_D] > dk(A1) ) : 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 superior rule ( [UNAVAILABLE_dk K_EQUAL] > dk(B0) ) : 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", 'CAPS', 'K_D', 1, 1, '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: ']], + [[new Rule("C3", 'X', 'K_X', 1, 1, 'Y', 'K_Y', 0, 0, 'SHIFT', 'K_Z', new TextEncoder().encode('D'),)], + ['c WARNING: unavailable modifier here: '], + ['c WARNING: unavailable superior rule ( [X K_X] > dk(A1) ) : unavailable modifier here: '], + ['c WARNING: unavailable superior rule ( [Y K_Y] > dk(B0) ) : here: ']], ].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.unitTestEndpoints.reviewRules(values[0] as Rule[], 0); + const result: string[] = sutW.unitTestEndpoints.reviewRules(values[0] as Rule[], 0).warningMessages; assert.equal(result[0], values[1][0]); assert.equal(result[1], values[2][0]); assert.equal(result[2], values[3][0]); @@ -163,6 +154,7 @@ describe('KmnFileWriter', function () { }); }); + describe('reviewRules messages duplicate and ambiguous', function () { const sutW = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); [ @@ -170,9 +162,9 @@ describe('KmnFileWriter', function () { [[ 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: "]], + ['c WARNING: duplicate rule: earlier: [LALT K_A] > dk(C0) here: '], + ["c WARNING: duplicate rule: earlier: dk(C0) + [SHIFT K_B] > dk(B0) here: "], + ["c WARNING: duplicate rule: earlier: dk(B0) + [CAPS K_C] > 'X' here: "]], //6-6 dup [[ @@ -180,7 +172,7 @@ describe('KmnFileWriter', function () { 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: "]], + ["c WARNING: duplicate rule: earlier: dk(B0) + [CAPS K_C] > 'X' here: "]], //6-6 amb [[ @@ -188,29 +180,29 @@ describe('KmnFileWriter', function () { 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: "]], + ["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: "], [''], + ['c WARNING: duplicate rule: earlier: [LALT K_A] > dk(C0) here: '], + ["c WARNING: ambiguous rule: earlier: dk(C0) + [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: "], + ['c WARNING: duplicate rule: earlier: [LALT K_A] > dk(C0) here: '], + ["c WARNING: duplicate rule: earlier: dk(C0) + [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: '], + ['c WARNING: ambiguous rule: later: [LALT K_A] > dk(C0) here: '], [''], ['']], @@ -218,7 +210,7 @@ describe('KmnFileWriter', function () { [[ 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: '], + ['c WARNING: ambiguous rule: earlier: [LALT K_A] > dk(C0) here: '], [""], [''],], @@ -226,7 +218,7 @@ describe('KmnFileWriter', function () { [[ 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: '], + ['c WARNING: duplicate rule: earlier: [LALT K_A] > dk(C0) here: '], [''], ['']], @@ -234,7 +226,7 @@ describe('KmnFileWriter', function () { [[ 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: '], + ['c WARNING: ambiguous rule: later: [LALT K_A] > dk(C0) here: '], [''], ['']], @@ -243,7 +235,7 @@ describe('KmnFileWriter', function () { 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: "], + ["c WARNING: duplicate rule: earlier: dk(C0) + [CAPS K_C] > 'X' here: "], [''],], // 6-3 amb @@ -251,14 +243,14 @@ describe('KmnFileWriter', function () { 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: "], + ["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: '], + ['c WARNING: ambiguous rule: earlier: [SHIFT K_B] > dk(A0) here: '], [''], ['']], @@ -267,7 +259,7 @@ describe('KmnFileWriter', function () { 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: '], + ['c WARNING: ambiguous rule: earlier: [SHIFT K_B] > dk(C0) here: '], ['']], // 2-2 dup @@ -275,7 +267,7 @@ describe('KmnFileWriter', function () { 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: '], + ['c WARNING: duplicate rule: earlier: [SHIFT K_B] > dk(C0) here: '], ['']], // 3-3 dup @@ -284,7 +276,7 @@ describe('KmnFileWriter', function () { 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: "]], + ["c WARNING: duplicate rule: earlier: dk(A0) + [CAPS K_C] > 'X' here: "]], // 3-3 amb [[ @@ -292,7 +284,7 @@ describe('KmnFileWriter', function () { 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: "]], + ["c WARNING: ambiguous rule: earlier: dk(A0) + [CAPS K_C] > 'X' here: "]], // 2-1 amb [[ @@ -300,7 +292,7 @@ describe('KmnFileWriter', function () { 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: ']], + ['c WARNING: ambiguous rule: later: [RALT K_B] > dk(A0) here: ']], // 1-1 amb [[ @@ -308,7 +300,7 @@ describe('KmnFileWriter', function () { new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('Y'))], [''], [''], - ["c WARNING: ambiguous rule: earlier: [CAPS K_C] > 'X' here: "]], + ["c WARNING: ambiguous rule: earlier: [CAPS K_C] > 'X' here: "]], // 1-1 amb [[ @@ -316,11 +308,11 @@ describe('KmnFileWriter', function () { new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X'))], [''], [''], - ["c WARNING: duplicate rule: earlier: [CAPS K_C] > 'X' here: "]], + ["c WARNING: duplicate rule: earlier: [CAPS K_C] > 'X' here: "]], ].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.unitTestEndpoints.reviewRules(values[0] as Rule[], 1); + const result: string[] = sutW.unitTestEndpoints.reviewRules(values[0] as Rule[], 1).warningMessages; assert.equal(result[0], values[1][0]); assert.equal(result[1], values[2][0]); assert.equal(result[2], values[3][0]); @@ -337,10 +329,10 @@ 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 ! "]], + ["c WARNING: ambiguous rule: later: [RALT K_B] > dk(A0) ambiguous rule: earlier: [RALT K_B] > 'X' PLEASE CHECK THAT RULE AS IT WILL NOT BE WRITTEN ! here: "]], ].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.unitTestEndpoints.reviewRules(values[0] as Rule[], 2); + const result: string[] = sutW.unitTestEndpoints.reviewRules(values[0] as Rule[], 2).warningMessages; assert.equal(result[0], values[1][0]); assert.equal(result[1], values[2][0]); assert.equal(result[2], values[3][0]); @@ -450,5 +442,42 @@ describe('KmnFileWriter', function () { }); }); }); +describe('writeCharacterOrUnicode and return values', function () { + const sutW = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); + [ + ["A", "A", "Msg "], + ["ሴ", "ሴ", "Msg "], + ["😀", "😀", "Msg "], + ["ẘ", "ẘ", "Msg "], + ["U+0001", "U+0001", "Msg Use of a control character "], + ["U+0061", "a", "Msg "], + ["", "U+0002", "Msg Use of a control character "], + ["ሴ", 'ሴ', "Msg "], + ["", "U+0003", "Msg Use of a control character "], + ["ሺ", "ሺ", "Msg "], + ["", "U+0006", "Msg Use of a control character "], + ['', '', 'Msg empty output or unsupported numerical html entity: '], + ].forEach(function (values) { + it(('should convert "' + values[0] + '"').padEnd(25, " ") + 'to "' + values[1] + '"', async function () { + const result = sutW.writeCharacterOrUnicode(values[0] as string, "Msg "); + assert.isNotNull(result); + assert.equal(result.character, values[1]); + assert.equal(result.message, values[2]); + }); + }); + }); + describe('writeCharacterOrUnicode and return null for result.message and result.character', function () { + const sutW = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); + [ + [null, null], + [undefined, null], + + ].forEach(function (values) { + it(('should convert "' + values[0] + '"').padEnd(25, " ") + 'to "' + values[1] + '"', async function () { + const result = sutW.writeCharacterOrUnicode(values[0], ""); + assert.isNull(result); + }); + }); + }); });