feat(developer): remove markers, checkIfCapsIsUsed for upper/lower/mixed case case

This commit is contained in:
Sabine 2025-03-24 15:36:08 +01:00
parent 6505f095e6
commit 647fb0afcf
2 changed files with 193 additions and 313 deletions

View file

@ -8,106 +8,24 @@ import { ConverterToKmnArtifacts } from "../converter-artifacts.js";
// Todo remove these todos
// OK TODO keylayout->kmn
// OK modifiers: The identifier of the <modifierMap> element to use for this range of hardware keyboard types.
// OK defaultIndex: The table number to use for modifier key combinations which are not explicitly specified by any <modifier> element within the <modifierMap>.
// OK write read, convert, write
// OK add data to object
// OK Use filter functions
// OK action/output:use filter etc to shorten func
// OK deadkeyables:use filter etc to shorten func
// OK dk-> for all action:use filter etc to shorten func
// OK remove unnecessary data from data_object
// OK rename symbols
// OK remove part using kmn_key_Name1
// OK remove unnecceaasry map_UkeleleKC_To_kmn_Key_Name_Array_Position_n etc
// OK loop throught ANSI, JIS- at moment only use [keyMapSet_count] (keyMapSet_count=0)
// OK remove funcs at teh end
// OK import { makePathToFixture } from '../../test/helpers/index.js';
// OK Mapping 0->30 or 0->K_A-> missing entries in mapping
// OK Replace any-types
// OK Several steps action-> action-> action->character ( not only action->character)
// OK Usable for all keylayout files
// OK Use callbacks as for writeFileSync
// OK objects contain only used stuff READ in: -- out: only read arrays / CONVERT in: only read arrays out: return only to write arrays
// OK Use catch blocks for file read
// OK read: answer : + [K_A] > 'a' is OK / TODO which format to use in output ? + [K_A] > 'a' (character code) or + [K_A] > U+0061 (virt Keycode)
// OK one entry vs several entry in tags
// OK no added NCAPS when first modifier in modifierMap does not contain "caps" or"caps?"
// OK naming of for-loop var i,j,k?...
// OK warning if contrADICTING RULES E:G: [ 'modifier_C0', 'SHIFT NCAPS', 'K_C', 'c'], vs [ 'modifier_C0', 'SHIFT NCAPS', 'K_C', 'C' ],
// OK print NCAPS as the first of the modifiers in create_kmn_modifier
// OK use boxXmlArray from codebase instead of my own
// OK where are rules for action+none ( a, e, u, etc)
// OK order of object member var
// OK readfilesync with paths better way?
// OK rearrange code to use read, convert, write
// OK TODO rewrite explanantion for object instead of array
// OK remove all any types
// OK public dk: number, //todo remove one
// OK todo use from elsewhere boxXmlArray_S
// OK prev_deadkeys_Ch: Uint8Array, /* Todo needed?*/
// OK Todo remove print_draft
// OK Todo files/path !!!
// OK start Tests v ToDo remove......................................
// OK TODO remove: test files: checkif kmn gets the same output as ukelele file(except for C3 t works well :))
// OK ToDo needed methods
// OK where to put documentation
// OK dk <-> id_deadkey ???
// OK check if we use the same algorithm to get Block1 data
// OK check unique_prev_deadkey, unique_deadkey, dk_prv, dk, id_deadkey
// OK check duplicate rule conditions which do I need; which can go
// OK when I run german with uniqueCAll why will there be [ ] without key anf modifier
// OK add links to HEADLINE of kmc-convert document
// OK TODO more Data stores to add ??
// OK check for keys < 50 whern working with keys
// OK NO OUTPUT FOR SPACE in C0C1 !!!
// OK check code for code styles keyman
// check (string |number) <-> number
// tests for 3 functions read write convert
// Return conditions
// Tests throws
// Conditions NCAPS,OPT;...
// TODO move func outside of class
// Functions as object methods?
// use length to clear array instead of defining new every time (modifierMap_ONE_InKeymapSelect.length=0
// use cmdl parameters -> new issue/PR
// TODO what about using actions twice in a row??? -> error msg if chain >4 -> new issue
// Todo prevent break for output ="" -> new issue
// what if keylayout file is not correct e.g missing '>' -> new issue
// what if nodes in keylayout file do not exist/ diff name keyboard <-> keyboardA -> new issue
// ---------------------------------------------------
// Filter functions use the same type
// TODO need to use export const USVirtualKeyCodes here
// replace unique_prev_deadkey 0, >0 with true, false
// TODO what about using actions twice in a row??? -> error msg if chain >4
// what if keylayout file is not correct e.g missing '>'
// read TODO which stores?
// OK does order of modifier matter ? -> NO
// remove all markers c0, 1-1, #### C2 ###, ...
// OK better function names for get......
// use cmdl parameters
// OK check semicolon everywhere
// OK test run
// OK test read
// OK test convert
// OK test write
// OK test createRuleData
// OK test get_KeyMap_Code_array__From__KeyMap_Action
// OK test get_KeyActionOutput_array__From__ActionStateOutput_array
// OK test get_ActionIndex__From__ActionId
// OK test get_ActionID__From__ActionNext
// OK test get_ActionStateOutput_array__From__ActionState
// OK test get_Output__From__ActionId_None
// OK test get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array
// OK test get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput
// OK test get_KeyModifier_array__From__ActionID
// OK test get_Modifier_array__From__KeyModifier_array
// OK test create_kmn_modifier
// OK test checkIfCapsIsUsed
// OK test isAcceptableKeymanModifier
// test reviewRules
// OK test map_UkeleleKC_To_VK
// test writeData_Rules
// OK test writeData_Stores
// what if nodes in keylayout file do not exist/ diff name keyboard <-> keyboardA
// separate createRuleData and check for duplicates/amb rules
// remove todos
// check warning text
// check (string |number) <-> number
// create NAME.kmn instead Myesult,kmn
// ToDo "undefined" or undefined ????
// separate createRuleData and check for duplicates/amb rules
import { XMLParser } from 'fast-xml-parser'; // for reading an xml file
import { readFileSync } from 'fs';
@ -128,7 +46,6 @@ function boxArrays(source: any) {
boxXmlArray(source?.actions, 'action');
for (const action of source?.actions?.action) {
boxXmlArray(action, 'when');
}
return source;
}
@ -179,30 +96,25 @@ export class KeylayoutToKmnConverter {
if (!inputFilename || !outputFilename) {
throw new Error('Invalid parameters');
}
console.log(' _S2 first READ file ........................................in:', inputFilename);
const jsonO: object = this.read(inputFilename);
if (!jsonO) {
throw new Error('read() not OK');
throw new Error('Error while processing read()');
return null;
}
console.log(' _S2 then CONVERT ........................................');
const outArray: convert_object = await this.convert(jsonO);
if (!outArray) {
throw new Error('convert() not OK');
throw new Error('Error while processing convert()');
return null;
}
console.log(' _S2 then WRITE to kmn .....................................');
const out_text: boolean = this.write(outArray);
if (!out_text) {
throw new Error('write() not OK');
throw new Error('Error while processing write()');
return null;
}
return null;
}
@ -228,8 +140,7 @@ export class KeylayoutToKmnConverter {
boxArrays(jsonObj.keyboard); // jsonObj now contains only arrays; no single fields
}
catch (err) {
// Todo how to break correctly; return what??
console.log(" FILE NOT FOUND");
console.log(err.message);
}
return jsonObj;
}
@ -254,7 +165,7 @@ export class KeylayoutToKmnConverter {
arrayOf_Rules: []
};
// todo check for tags
// todo check tags
if (jsonObj_any.hasOwnProperty("keyboard")) {
data_object.keylayout_filename = jsonObj_any.keyboard['@_name'] + ".keylayout";
@ -304,7 +215,7 @@ export class KeylayoutToKmnConverter {
public createRuleData(data_ukelele: convert_object, jsonObj: any): convert_object {
const object_array: rule_object[] = [];
let dk_counter_C3_A: number = 0;
let dk_counter_C3: number = 0;
let dk_counter_C2: number = 0;
let action_id: string;
@ -350,6 +261,8 @@ export class KeylayoutToKmnConverter {
/* key */ this.map_UkeleleKC_To_VK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_code'])),
/* output */ new TextEncoder().encode(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output']),
);
// ToDo "undefined" or undefined ????
if (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] !== "") {
object_array.push(rule_obj);
}
@ -545,7 +458,7 @@ export class KeylayoutToKmnConverter {
/* rule_type */ "C3",
/* modifier_prev_deadkey*/ this.create_kmn_modifier(b2_prev_deadkeyModifier_arr[n1][n2], isCapsused),
/* prev_deadkey */ this.map_UkeleleKC_To_VK(Number(b2_prev_deadkey_arr[n3][0])),
/* id_prev_deadkey */ dk_counter_C3_A++,
/* id_prev_deadkey */ dk_counter_C3++,
/* unique A */ 0,
/* modifier_deadkey */ this.create_kmn_modifier(b4_deadkeyModifier_arr[n4][n5], isCapsused),
@ -573,6 +486,9 @@ export class KeylayoutToKmnConverter {
}
} else {
console.log("ERROR : some entries are not available");
// Todo prevent break for output =""
console.log(" ", jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]);
}
}
}
@ -675,8 +591,6 @@ export class KeylayoutToKmnConverter {
return data_ukelele;
}
// ---------------------------------------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------------------------------------
/**
@ -1018,9 +932,8 @@ export class KeylayoutToKmnConverter {
* @param keylayout_modifier the modifier value used in the .keylayout-file
* @return kmn_modifier the modifier value used in the .kmn-file
*/
// TODO caps <-> Caps <-> cAPs,...
public checkIfCapsIsUsed(keylayout_modifier: string[][]): boolean {
return JSON.stringify(keylayout_modifier).includes("caps");
return JSON.stringify(keylayout_modifier).toUpperCase().includes("CAPS");
}
/**
@ -1065,7 +978,6 @@ export class KeylayoutToKmnConverter {
* @param index the index of a rule in array[rule]
* @return a string[] containing possible warnings for a rule
*/
// todo remove comments in filters after check of several keylayout files
public reviewRules(rule: rule_object[], index: number): string[] {
const warningTextArray: string[] = Array(3).fill("");
@ -1075,28 +987,28 @@ export class KeylayoutToKmnConverter {
// Todo remoce C1-C3's and other markers
if ((rule[index].rule_type === "C0") || (rule[index].rule_type === "C1")) {
if (!this.isAcceptableKeymanModifier(rule[index].modifier_key)) {
warningTextArray[2] = "C1 unavailable modifier : ";
warningTextArray[2] = "unavailable modifier : ";
}
}
else if (rule[index].rule_type === "C2") {
if (!this.isAcceptableKeymanModifier(rule[index].modifier_deadkey)) {
warningTextArray[1] = "C2 unavailable modifier : ";
warningTextArray[1] = "unavailable modifier : ";
}
if (!this.isAcceptableKeymanModifier(rule[index].modifier_key)) {
warningTextArray[2] = "C2 unavailable modifier : ";
warningTextArray[2] = "unavailable modifier : ";
}
}
else if (rule[index].rule_type === "C3") {
if (!this.isAcceptableKeymanModifier(rule[index].modifier_prev_deadkey)) {
warningTextArray[2] = "C3 unavailable modifier : ";
warningTextArray[2] = "unavailable modifier : ";
}
if (!this.isAcceptableKeymanModifier(rule[index].modifier_deadkey)) {
warningTextArray[1] = "C3 unavailable modifier : ";
warningTextArray[1] = "unavailable modifier : ";
}
if (!this.isAcceptableKeymanModifier(rule[index].modifier_key)) {
warningTextArray[0] = "C3 unavailable modifier : ";
warningTextArray[0] = "unavailable modifier : ";
}
}
@ -1146,46 +1058,46 @@ export class KeylayoutToKmnConverter {
if (amb_4_1.length > 0) {
warningTextArray[2] = warningTextArray[2]
+ ("ambiguous 4-1 rule: later: ["
+ ("ambiguous rule: later: ["
+ amb_4_1[0].modifier_prev_deadkey
+ " "
+ amb_4_1[0].prev_deadkey
+ "] > dk(C"
+ amb_4_1[0].unique_prev_deadkey
+ ") here: ");
+ ") ");
}
if (amb_2_1.length > 0) {
if (amb_2_1.length > 0) {
warningTextArray[2] = warningTextArray[2]
+ ("ambiguous 2-1 rule: later: ["
+ ("ambiguous rule: later: ["
+ amb_2_1[0].modifier_deadkey
+ " "
+ amb_2_1[0].deadkey
+ "] > dk(A"
+ amb_2_1[0].unique_deadkey
+ ") here: ");
+ ") ");
}
if (amb_1_1.length > 0) {
if (amb_1_1.length > 0) {
warningTextArray[2] = warningTextArray[2]
+ ("C1 ambiguous 1-1 rule: earlier: ["
+ ("ambiguous rule: earlier: ["
+ amb_1_1[0].modifier_key
+ " "
+ amb_1_1[0].key
+ "] > \'"
+ new TextDecoder().decode(amb_1_1[0].output)
+ "\' here: ");
+ "\' ");
}
if (dup_1_1.length > 0) {
if (dup_1_1.length > 0) {
warningTextArray[2] = warningTextArray[2]
+ ("C1 duplicate 1-1 rule: earlier: ["
+ ("duplicate rule: earlier: ["
+ dup_1_1[0].modifier_key
+ " "
+ dup_1_1[0].key
+ "] > \'"
+ new TextDecoder().decode(dup_1_1[0].output)
+ "\' here: ");
+ "\' ");
}
}
@ -1240,28 +1152,29 @@ export class KeylayoutToKmnConverter {
if (amb_2_2.length > 0) {
warningTextArray[1] = warningTextArray[1]
+ ("ambiguous 2-2 rule: earlier: ["
+ ("ambiguous rule: earlier: ["
+ amb_2_2[0].modifier_deadkey
+ " "
+ amb_2_2[0].deadkey
+ "] > dk(C"
+ amb_2_2[0].id_deadkey
+ ") here: ");
+ ") ");
}
if (dup_2_2.length > 0) {
warningTextArray[1] = warningTextArray[1]
+ ("duplicate 2-2 rule: earlier: ["
+ ("duplicate rule: earlier: ["
+ dup_2_2[0].modifier_deadkey
+ " "
+ dup_2_2[0].deadkey
+ "] > dk(C"
+ dup_2_2[0].id_deadkey
+ ") here: ");
+ ") ");
}
if (amb_3_3.length > 0) {
warningTextArray[2] = warningTextArray[2]
+ ("ambiguous 3-3 rule: earlier: dk(C"
+ ("ambiguous rule: earlier: dk(C"
+ amb_3_3[0].id_deadkey
+ ") + ["
+ amb_3_3[0].modifier_key
@ -1269,11 +1182,12 @@ export class KeylayoutToKmnConverter {
+ amb_3_3[0].key
+ "] > \'"
+ new TextDecoder().decode(amb_3_3[0].output)
+ "\' here: ");
+ "\' ");
}
if (dup_3_3.length > 0) {
warningTextArray[2] = warningTextArray[2]
+ ("duplicate 3-3 rule: earlier: dk(C"
+ ("duplicate rule: earlier: dk(C"
+ dup_3_3[0].id_deadkey
+ ") + ["
+ dup_3_3[0].modifier_key
@ -1281,18 +1195,18 @@ export class KeylayoutToKmnConverter {
+ dup_3_3[0].key
+ "] > \'"
+ new TextDecoder().decode(dup_3_3[0].output)
+ "\' here: ");
+ "\' ");
}
if (amb_4_2.length > 0) {
warningTextArray[0] = warningTextArray[0]
+ ("ambiguous 4-2 rule: later: ["
+ ("ambiguous rule: later: ["
+ amb_4_2[0].modifier_prev_deadkey
+ " "
+ amb_4_2[0].prev_deadkey
+ "] > dk(C"
+ amb_4_2[0].id_prev_deadkey
+ ") here: ");
+ ") ");
}
}
@ -1386,18 +1300,18 @@ export class KeylayoutToKmnConverter {
if (amb_2_4.length > 0) {
warningTextArray[0] = warningTextArray[0]
+ ("ambiguous 2-4 rule: earlier(Todo check if print out or not): ["
+ ("ambiguous rule: earlier: ["
+ amb_2_4[0].modifier_deadkey
+ " "
+ amb_2_4[0].deadkey
+ "] > dk(C"
+ "] > dk(A"
+ amb_2_4[0].id_deadkey
+ ") here: ");
+ ") ");
}
if (amb_6_3.length > 0) {
warningTextArray[1] = warningTextArray[1]
+ ("ambiguous 6-3 rule: earlier: dk(C"
+ ("ambiguous rule: earlier: dk(C"
+ amb_6_3[0].id_deadkey
+ ") + ["
+ amb_6_3[0].modifier_key
@ -1405,12 +1319,12 @@ export class KeylayoutToKmnConverter {
+ amb_6_3[0].key
+ "] > \'"
+ new TextDecoder().decode(amb_6_3[0].output)
+ "\' here: ");
+ "\' ");
}
if (dup_6_3.length > 0) {
warningTextArray[1] = warningTextArray[1]
+ ("duplicate 6-3 rule: earlier: dk(C"
+ ("duplicate rule: earlier: dk(C"
+ dup_6_3[0].id_deadkey
+ ") + ["
+ dup_6_3[0].modifier_key
@ -1418,34 +1332,34 @@ export class KeylayoutToKmnConverter {
+ dup_6_3[0].key
+ "] > \'"
+ new TextDecoder().decode(dup_6_3[0].output)
+ "\' here: ");
+ "\' ");
}
if (amb_4_4.length > 0) {
warningTextArray[0] = warningTextArray[0]
+ ("ambiguous 4-4 rule: earlier: ["
+ ("ambiguous rule: earlier: ["
+ amb_4_4[0].modifier_prev_deadkey
+ " "
+ amb_4_4[0].prev_deadkey
+ "] > dk(C"
+ amb_4_4[0].id_prev_deadkey
+ ") here: ");
+ ") ");
}
if (dup_4_4.length > 0) {
warningTextArray[0] = warningTextArray[0]
+ ("duplicate 4-4 rule: earlier: ["
+ ("duplicate rule: earlier: ["
+ dup_4_4[0].modifier_prev_deadkey
+ " "
+ dup_4_4[0].prev_deadkey
+ "] > dk(C"
+ dup_4_4[0].id_prev_deadkey
+ ") here: ");
+ ") ");
}
if (amb_5_5.length > 0) {
warningTextArray[1] = warningTextArray[1]
+ ("ambiguous 5-5 rule: earlier: dk(B"
+ ("ambiguous rule: earlier: dk(B"
+ amb_5_5[0].id_prev_deadkey
+ ") + ["
+ amb_5_5[0].modifier_deadkey
@ -1453,12 +1367,12 @@ export class KeylayoutToKmnConverter {
+ amb_5_5[0].deadkey
+ "] > dk(B"
+ amb_5_5[0].id_deadkey
+ ") here: ");
+ ") ");
}
if (dup_5_5.length > 0) {
warningTextArray[1] = warningTextArray[1]
+ ("duplicate 5-5 rule: earlier: dk(B"
+ ("duplicate rule: earlier: dk(B"
+ dup_5_5[0].id_prev_deadkey
+ ") + ["
+ dup_5_5[0].modifier_deadkey
@ -1466,12 +1380,12 @@ export class KeylayoutToKmnConverter {
+ dup_5_5[0].deadkey
+ "] > dk(B"
+ dup_5_5[0].id_deadkey
+ ") here: ");
+ ") ");
}
if (amb_6_6.length > 0) {
warningTextArray[2] = warningTextArray[2]
+ ("ambiguous 6-6 rule: earlier: dk(B"
+ ("ambiguous rule: earlier: dk(B"
+ amb_6_6[0].id_deadkey
+ ") + ["
+ amb_6_6[0].modifier_key
@ -1479,12 +1393,12 @@ export class KeylayoutToKmnConverter {
+ amb_6_6[0].key
+ "] > \'"
+ new TextDecoder().decode(amb_6_6[0].output)
+ "\' here: ");
+ "\' ");
}
if (dup_6_6.length > 0) {
warningTextArray[2] = warningTextArray[2]
+ ("duplicate 6-6x rule: earlier: dk(B"
+ ("duplicate rule: earlier: dk(B"
+ dup_6_6[0].id_deadkey
+ ") + ["
+ dup_6_6[0].modifier_key
@ -1492,18 +1406,18 @@ export class KeylayoutToKmnConverter {
+ dup_6_6[0].key
+ "] > \'"
+ new TextDecoder().decode(dup_6_6[0].output)
+ "\' here: ");
+ "\' ");
}
}
if (warningTextArray[0] !== "") {
warningTextArray[0] = "c WARNING: " + warningTextArray[0];
warningTextArray[0] = "c WARNING: " + warningTextArray[0]+"here: ";
}
if (warningTextArray[1] !== "") {
warningTextArray[1] = "c WARNING: " + warningTextArray[1];
warningTextArray[1] = "c WARNING: " + warningTextArray[1]+"here: ";
}
if (warningTextArray[2] !== "") {
warningTextArray[2] = "c WARNING: " + warningTextArray[2];
warningTextArray[2] = "c WARNING: " + warningTextArray[2]+"here: ";
}
return warningTextArray;
@ -1590,7 +1504,7 @@ export class KeylayoutToKmnConverter {
* @return a unicode codepoint if instr is a numeric character reference
* else instr if instr is not a numeric character reference
*/
public checkOutputChar(instr: string): string {
public convertToUnicodeCodePoint(instr: string): string {
if (instr.substring(0, 3) === "&#x") {
const num_length = instr.length - instr.indexOf("x") - 1;
@ -1608,10 +1522,6 @@ export class KeylayoutToKmnConverter {
else
return instr;
}
//----------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------
/**
* @brief member function to create a list of rule that will be printed to the resulting kmn file
@ -1626,12 +1536,10 @@ export class KeylayoutToKmnConverter {
const unique_data_Rules: rule_object[] = data_ukelele.arrayOf_Rules.filter((curr) => {
return ((curr.output !== new TextEncoder().encode("") || curr.output !== undefined)
&& (curr.key !== "")
// && ((curr.rule_type === "C0") || (curr.rule_type === "C1") || (curr.rule_type === "C2" && (curr.deadkey !== "")) || (curr.rule_type === "C3" && (curr.prev_deadkey !== "")))
&& ((curr.rule_type === "C0")
|| (curr.rule_type === "C1")
|| (curr.rule_type === "C2" && (curr.deadkey !== ""))
|| (curr.rule_type === "C3" && (curr.deadkey !== "") && (curr.prev_deadkey !== "")))
);
}).reduce((unique, o) => {
if (!unique.some((obj: {
@ -1658,8 +1566,6 @@ export class KeylayoutToKmnConverter {
return unique;
}, []);
//................................................ C0 C1 ................................................................
//................................................ C0 C1 ................................................................
//................................................ C0 C1 ................................................................
for (let k = 0; k < unique_data_Rules.length; k++) {
@ -1690,7 +1596,7 @@ export class KeylayoutToKmnConverter {
const warn_text = this.reviewRules(unique_data_Rules, k);
const output_character = new TextDecoder().decode(unique_data_Rules[k].output);
const output_character_unicode = this.checkOutputChar(output_character);
const output_character_unicode = this.convertToUnicodeCodePoint(output_character);
// if we are about to print a unicode codepoint instead of a single character we need to check if it is a control character
if ((output_character_unicode.length > 1)
@ -1703,10 +1609,10 @@ export class KeylayoutToKmnConverter {
// add a warning in front of rules in case unavailable modifiers or ambiguous rules are used
// if warning contains duplicate rules we do not write out this rule (even if there are other warnings for the same rule) since that rule had been written before
// if warning contains duplicate rules we do not write out this rule
// (even if there are other warnings for the same rule) since that rule had been written before
if ((warn_text[2].indexOf("duplicate") < 0)) {
data +=
warn_text[2]
data += warn_text[2]
+ "+ ["
+ (unique_data_Rules[k].modifier_key + ' ' + unique_data_Rules[k].key).trim()
+ `] > \'`
@ -1716,11 +1622,6 @@ export class KeylayoutToKmnConverter {
}
}
// Todo remove this marker
data += "\n c ########## C2 #################################################################\n";
//................................................ C2 ...................................................................
//................................................ C2 ...................................................................
//................................................ C2 ...................................................................
for (let k = 0; k < unique_data_Rules.length; k++) {
@ -1729,7 +1630,7 @@ export class KeylayoutToKmnConverter {
const warn_text = this.reviewRules(unique_data_Rules, k);
const output_character = new TextDecoder().decode(unique_data_Rules[k].output);
const output_character_unicode = this.checkOutputChar(output_character);
const output_character_unicode = this.convertToUnicodeCodePoint(output_character);
// if we are about to print a unicode codepoint instead of a single character we need to check if it is a control character
if ((output_character_unicode.length > 1)
@ -1741,21 +1642,21 @@ export class KeylayoutToKmnConverter {
}
// add a warning in front of rules in case unavailable modifiers or ambiguous rules are used
// if warning contains duplicate rules we do not write out this rule (even if there are other warnings for the same rule) since that rule had been written before
// if warning contains duplicate rules we do not write out this rule
// (even if there are other warnings for the same rule) since that rule had been written before
if ((warn_text[1].indexOf("duplicate") < 0)) {
data += warn_text[1]
+ "+ ["
+ (unique_data_Rules[k].modifier_deadkey + " " + unique_data_Rules[k].deadkey).trim()
+ "] > dk(A"
+ String(unique_data_Rules[k].id_deadkey)
+ "+ [" + (unique_data_Rules[k].modifier_deadkey + " "
+ unique_data_Rules[k].deadkey).trim()
+ "] > dk(A" + String(unique_data_Rules[k].id_deadkey)
+ ")\n";
}
if ((warn_text[2].indexOf("duplicate") < 0)) {
data +=
warn_text[2]
data += warn_text[2]
+ "dk(A"
+ (String(unique_data_Rules[k].id_deadkey) + ") + [" + unique_data_Rules[k].modifier_key).trim()
+ (String(unique_data_Rules[k].id_deadkey) + ") + ["
+ unique_data_Rules[k].modifier_key).trim()
+ " "
+ unique_data_Rules[k].key + "] > \'"
+ output_character_unicode
@ -1767,10 +1668,6 @@ export class KeylayoutToKmnConverter {
}
//................................................ C3 ...................................................................
//................................................ C3 ...................................................................
//................................................ C3 ...................................................................
data += "\nc ########## C3 #################################################################\n";
for (let k = 0; k < unique_data_Rules.length; k++) {
if (unique_data_Rules[k].rule_type === "C3") {
@ -1778,7 +1675,7 @@ export class KeylayoutToKmnConverter {
const warn_text = this.reviewRules(unique_data_Rules, k);
const output_character = new TextDecoder().decode(unique_data_Rules[k].output);
const output_character_unicode = this.checkOutputChar(output_character);
const output_character_unicode = this.convertToUnicodeCodePoint(output_character);
// if we are about to print a unicode codepoint instead of a single character we need to check if a control character is to be used
if ((output_character_unicode.length > 1)
@ -1790,23 +1687,23 @@ export class KeylayoutToKmnConverter {
}
// add a warning in front of rules in case unavailable modifiers or ambiguous rules are used
// if warning contains duplicate rules we do not write out this rule (even if there are other warnings for the same rule) since that rule had been written before
// if warning contains duplicate rules we do not write out this rule
// (even if there are other warnings for the same rule) since that rule had been written before
if ((warn_text[0].indexOf("duplicate") < 0)
) {
data +=
warn_text[0]
data += warn_text[0]
+ "+ ["
+ (unique_data_Rules[k].modifier_prev_deadkey + " " + unique_data_Rules[k].prev_deadkey).trim()
+ (unique_data_Rules[k].modifier_prev_deadkey + " "
+ unique_data_Rules[k].prev_deadkey).trim()
+ "] > dk(C"
+ String(unique_data_Rules[k].id_prev_deadkey) + ")\n";
}
if ((warn_text[1].indexOf("duplicate") < 0)
) {
data +=
warn_text[1]
+ "dk(C"
+ (String(unique_data_Rules[k].id_prev_deadkey) + ") + [" + unique_data_Rules[k].modifier_deadkey).trim()
data += warn_text[1]
+ "dk(C" + (String(unique_data_Rules[k].id_prev_deadkey) + ") + ["
+ unique_data_Rules[k].modifier_deadkey).trim()
+ " "
+ unique_data_Rules[k].deadkey
+ "] > dk(B"
@ -1816,9 +1713,10 @@ export class KeylayoutToKmnConverter {
if ((warn_text[2].indexOf("duplicate") < 0)
) {
data +=
warn_text[2] + "dk(B"
+ (String(unique_data_Rules[k].id_deadkey) + ") + [" + unique_data_Rules[k].modifier_key).trim()
data += warn_text[2] + "dk(B"
+ (String(unique_data_Rules[k].id_deadkey)
+ ") + ["
+ unique_data_Rules[k].modifier_key).trim()
+ " "
+ unique_data_Rules[k].key
+ "] > \'"
@ -1829,10 +1727,8 @@ export class KeylayoutToKmnConverter {
if ((warn_text[0].indexOf("duplicate") < 0) || (warn_text[1].indexOf("duplicate") < 0) || (warn_text[2].indexOf("duplicate") < 0)) {
data += "\n";
}
}
}
return data;
}
@ -1864,73 +1760,11 @@ export class KeylayoutToKmnConverter {
data += "\n";
return data;
}
/// console log all entries C3 TODO remove
public writeDataset(dataRules: rule_object[]) {
for (let i = 0; i < dataRules.length; i++) {
//if (dataRules[i].key === "") {
if (1 === 1) {
console.log("dataRules[i].key ", "..", dataRules[i].key, "..", dataRules[i].key === "");
console.log("dataRules ", i,
dataRules[i].rule_type !== "" ? dataRules[i].rule_type : "--".padEnd(4, " "),
"| ", (dataRules[i].modifier_prev_deadkey !== "" ? dataRules[i].modifier_prev_deadkey.padEnd(33, " ") : "--".padEnd(33, " ")),
(dataRules[i].prev_deadkey !== "" ? dataRules[i].prev_deadkey.padEnd(8, " ") : "--".padEnd(8, " ")),
(dataRules[i].id_prev_deadkey !== 0 ? ("dk(A" + String(dataRules[i].id_prev_deadkey) + ")").padEnd(11, " ") : "--".padEnd(11, " ")),
(dataRules[i].unique_prev_deadkey !== 0 ? ("unique(A" + String(dataRules[i].unique_prev_deadkey) + ")").padEnd(11, " ") : "--".padEnd(11, " ")),
(dataRules[i].modifier_deadkey !== "" ? dataRules[i].modifier_deadkey.padEnd(30, " ") : "--".padEnd(30, " ")),
(dataRules[i].deadkey !== "" ? dataRules[i].deadkey.padEnd(8, " ") : "--".padEnd(8, " ")),
dataRules[i].rule_type === "C2" ? (dataRules[i].unique_deadkey !== 0 ? ("unique(C" + String(dataRules[i].unique_deadkey) + ")").padEnd(9, " ") : "--".padEnd(9, " ")) : ((dataRules[i].unique_prev_deadkey !== 0 ? ("unique(B" + dataRules[i].id_deadkey + ")").padEnd(9, " ") : "--".padEnd(9, " "))),
dataRules[i].id_prev_deadkey,
dataRules[i].id_deadkey,
"| ", (dataRules[i].modifier_key !== "" ? dataRules[i].modifier_key.padEnd(40, " ") : "--".padEnd(40, " ")),
(dataRules[i].key !== "" ? dataRules[i].key.padEnd(8, " ") : "--".padEnd(8, " ")),
(new TextDecoder().decode(dataRules[i].output) !== "" ? new TextDecoder().decode(dataRules[i].output).padEnd(10, " ") : ("--" + dataRules[i].output) + "--"),
"| °°");
}
}
}
// TODO remove
public writeDatasetSingle(dataRules: rule_object) {
console.log("dataRules[i].key ", "..", dataRules.key, "..", dataRules.key === "");
console.log("dataRules ",
dataRules.rule_type !== "" ? dataRules.rule_type : "--".padEnd(4, " "),
"| ", (dataRules.modifier_prev_deadkey !== "" ? dataRules.modifier_prev_deadkey.padEnd(33, " ") : "--".padEnd(33, " ")),
(dataRules.prev_deadkey !== "" ? dataRules.prev_deadkey.padEnd(8, " ") : "--".padEnd(8, " ")),
(dataRules.id_prev_deadkey !== 0 ? ("dk(A" + String(dataRules.id_prev_deadkey) + ")").padEnd(11, " ") : "--".padEnd(11, " ")),
(dataRules.unique_prev_deadkey !== 0 ? ("unique(A" + String(dataRules.unique_prev_deadkey) + ")").padEnd(11, " ") : "--".padEnd(11, " ")),
(dataRules.modifier_deadkey !== "" ? dataRules.modifier_deadkey.padEnd(30, " ") : "--".padEnd(30, " ")),
(dataRules.deadkey !== "" ? dataRules.deadkey.padEnd(8, " ") : "--".padEnd(8, " ")),
dataRules.rule_type === "C2" ? (dataRules.unique_deadkey !== 0 ? ("unique(C" + String(dataRules.unique_deadkey) + ")").padEnd(9, " ") : "--".padEnd(9, " ")) : ((dataRules.unique_prev_deadkey !== 0 ? ("unique(B" + dataRules.id_deadkey + ")").padEnd(9, " ") : "--".padEnd(9, " "))),
dataRules.id_prev_deadkey,
dataRules.id_deadkey,
"| ", (dataRules.modifier_key !== "" ? dataRules.modifier_key.padEnd(40, " ") : "--".padEnd(40, " ")),
(dataRules.key !== "" ? dataRules.key.padEnd(8, " ") : "--".padEnd(8, " ")),
(new TextDecoder().decode(dataRules.output) !== "" ? new TextDecoder().decode(dataRules.output).padEnd(10, " ") : ("--" + dataRules.output) + "--"),
"| °°");
}
}
/**
* @brief class for all storing a rule containing data for key, deadkey, previous deadkey, output)
*/
* @brief class for all storing a rule containing data for key, deadkey, previous deadkey, output)
*/
class Rules {
constructor(
public rule_type: string, /* C0, C1, C2, C3, or C4 */

View file

@ -2,12 +2,6 @@
* Keyman is copyright (C) SIL International. MIT License.
*/
/*run with
cd developer/src/kmc-convert/
./build.sh test*/
import 'mocha';
import { assert } from 'chai';
import { compilerTestCallbacks, compilerTestOptions } from './helpers/index.js';
@ -22,39 +16,19 @@ describe('KeylayoutToKmnConverter', function () {
compilerTestCallbacks.clear();
});
// convert_object
const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions);
// convert_object from usable file name
//copy into C:\Projects\keyman\keyman\developer\src\kmc-convert\test\DATA then they run OK
//const inputFilename = makePathToFixture('../data/US_complete.keylayout'); // OKOK
const inputFilename = makePathToFixture('../data/Italian_copy.keylayout'); // OKOK
const inputFilename = makePathToFixture('../data/Italian_copy.keylayout'); // OKOK
//const inputFilename = makePathToFixture('../data/German_complete.keylayout'); // OK NO NCAPS SHIFT <-> SHIFT NCAPS
//const inputFilename = makePathToFixture('../data/German_Standard_copy.keylayout'); // OK NO NCAPS SHIFT <-> SHIFT NCAPS
//const inputFilename = makePathToFixture('../data/German_Standard2.keylayout'); // OKOK small
//const inputFilename = makePathToFixture('../data/Spanish_copy.keylayout'); // OKOK
//const inputFilename = makePathToFixture('../data/Latin_American_copy.keylayout'); // OKOK
//const inputFilename = makePathToFixture('../data/Swiss_French_copy.keylayout'); // OKOK
//const inputFilename = makePathToFixture('../data/Swiss_German_copy.keylayout'); // OKOK
//const inputFilename = makePathToFixture('../data/US_copy.keylayout'); // OKOK
//const inputFilename = makePathToFixture('../data/Polish_copy.keylayout'); // OKOK
//const inputFilename = makePathToFixture('../data/My_dk_Keyboard.keylayout'); // No
//const inputFilename = makePathToFixture('../data/German_StandardTweaked.keylayout'); // NO C3
const read = sut.read(inputFilename);
const converted = sut.convert(read);
// empty convert_object from unavailable file name
const inputFilename_unavailable = makePathToFixture('X.keylayout');
const read_unavailable = sut.read(inputFilename_unavailable);
const converted_unavailable = sut.convert(read_unavailable);
// empty convert_object from empty filename
const inputFilename_empty = makePathToFixture('');
const read_empty = sut.read(inputFilename_empty);
const converted_empty = sut.convert(read_empty);
describe("run() ", function () {
const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions);
it('run() should throw on null inputs', async function () {
// note, could use 'chai as promised' library to make this more fluent:
@ -105,6 +79,9 @@ describe('KeylayoutToKmnConverter', function () {
});
describe("read() ", function () {
const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions);
const inputFilename_unavailable = makePathToFixture('X.keylayout');
it('read() should return filled array on correct input', async function () {
const result = sut.read(inputFilename);
assert.isNotEmpty(result);
@ -137,6 +114,15 @@ describe('KeylayoutToKmnConverter', function () {
});
describe("write() ", function () {
const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions);
const read = sut.read(inputFilename);
const converted = sut.convert(read);
// empty convert_object from unavailable file name
const inputFilename_unavailable = makePathToFixture('X.keylayout');
const read_unavailable = sut.read(inputFilename_unavailable);
const converted_unavailable = sut.convert(read_unavailable);
it('write() should return true (no error) if no inputfile', async function () {
const result = sut.write(converted_unavailable);
assert.isTrue(result);
@ -149,6 +135,19 @@ describe('KeylayoutToKmnConverter', function () {
});
describe("convert() ", function () {
const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions);
const read = sut.read(inputFilename);
const converted = sut.convert(read);
// empty convert_object from unavailable file name
const inputFilename_unavailable = makePathToFixture('X.keylayout');
const read_unavailable = sut.read(inputFilename_unavailable);
const converted_unavailable = sut.convert(read_unavailable);
// empty convert_object from empty filename
const inputFilename_empty = makePathToFixture('');
const read_empty = sut.read(inputFilename_empty);
const converted_empty = sut.convert(read_empty);
it('should return converted array on correct input', async function () {
// we use 'converted' from above
@ -193,6 +192,8 @@ describe('KeylayoutToKmnConverter', function () {
});
describe('create_kmn_modifier ', function () {
const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions);
[
['anycontrol', true, 'NCAPS CTRL'],
['shift?', true, 'NCAPS'],
@ -221,6 +222,8 @@ describe('KeylayoutToKmnConverter', function () {
});
describe('getHexFromString ', function () {
const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions);
[
['0009', '0009'],
['000027', '001B'],
@ -243,7 +246,9 @@ describe('KeylayoutToKmnConverter', function () {
});
});
describe('checkOutputChar ', function () {
describe('convertToUnicodeCodePoint ', function () {
const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions);
[
["&#x10F601;", 'U+10F601'],
["&#x1F601;", 'U+1F601'],
@ -266,13 +271,15 @@ describe('KeylayoutToKmnConverter', function () {
[' ;', ' ;']
].forEach(function (values) {
it(('should convert "' + values[0] + '"').padEnd(25, " ") + 'to "' + values[1] + '"', async function () {
const result = sut.checkOutputChar(values[0] as string);
const result = sut.convertToUnicodeCodePoint(values[0] as string);
assert.equal(result, values[1]);
});
});
});
describe("isAcceptableKeymanModifier ", function () {
const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions);
[
["NCAPS", true],
["NxCAPS", false],
@ -296,6 +303,8 @@ describe('KeylayoutToKmnConverter', function () {
});
describe("map_UkeleleKC_To_VK ", function () {
const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions);
[
[0x00, "K_A"],
[0x31, "K_SPACE"],
@ -315,6 +324,7 @@ describe('KeylayoutToKmnConverter', function () {
});
describe("checkIfCapsIsUsed ", function () {
const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions);
it(("checkIfCapsIsUsed([['caps', 'xxx'], ['yyy']])").padEnd(45, " ") + " should return true", async function () {
const result = sut.checkIfCapsIsUsed([["caps", "xxx"], ["yyy"]]);
@ -336,6 +346,10 @@ describe('KeylayoutToKmnConverter', function () {
});
describe("get_Modifier_array__From__KeyModifier_array ", function () {
const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions);
const read = sut.read(inputFilename);
const converted = sut.convert(read);
[[[['0', 0]], [['', 'shift? caps? ']]],
[[['0', 1]], [['anyShift caps?', 'shift? rightShift caps? ', 'shift? leftShift caps? ', 'shift leftShift caps ']]],
[[['0', 999]], [null]],
@ -363,6 +377,9 @@ describe('KeylayoutToKmnConverter', function () {
});
describe("get_KeyModifier_array__From__ActionID ", function () {
const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions);
const read = sut.read(inputFilename);
[
["a16", [['32', 3]]],
["a19", [['45', 3]]],
@ -387,6 +404,9 @@ describe('KeylayoutToKmnConverter', function () {
});
describe("get_ActionID__From__ActionNext ", function () {
const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions);
const read = sut.read(inputFilename);
[
["none", ""],
["a18", ""],
@ -409,6 +429,9 @@ describe('KeylayoutToKmnConverter', function () {
});
describe("get_ActionIndex__From__ActionId ", function () {
const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions);
const read = sut.read(inputFilename);
[
["none", 0],
["a16", 8],
@ -429,6 +452,9 @@ describe('KeylayoutToKmnConverter', function () {
});
describe("get_Output__From__ActionId_None ", function () {
const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions);
const read = sut.read(inputFilename);
[["a14", "u"],
["", ""],
[" ", ""],
@ -454,6 +480,8 @@ describe('KeylayoutToKmnConverter', function () {
});
describe("get_KeyMBehaviourModOutputArray__from__KeyActionBehaviourOutput_array ", function () {
const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions);
const read = sut.read(inputFilename);
const b1_keycode_arr = [
['49', 'K_SPACE', 'a0', '0', 'ˆ'],
@ -565,6 +593,19 @@ describe('KeylayoutToKmnConverter', function () {
});
describe("writeData_Stores() ", function () {
const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions);
const read = sut.read(inputFilename);
const converted = sut.convert(read);
// empty convert_object from unavailable file name
const inputFilename_unavailable = makePathToFixture('X.keylayout');
const read_unavailable = sut.read(inputFilename_unavailable);
const converted_unavailable = sut.convert(read_unavailable);
// empty convert_object from empty filename
const inputFilename_empty = makePathToFixture('');
const read_empty = sut.read(inputFilename_empty);
const converted_empty = sut.convert(read_empty);
const out_expected_first: string =
"c ......................................................................\n"
@ -603,6 +644,10 @@ describe('KeylayoutToKmnConverter', function () {
});
describe("get_ActionStateOutput_array__From__ActionState ", function () {
const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions);
const read = sut.read(inputFilename);
[["1", [
['a0', '1', 'ˆ'],
['a1', '1', 'Â'],
@ -644,6 +689,11 @@ describe('KeylayoutToKmnConverter', function () {
});
describe("get_ActionOutputBehaviourKeyModi_From__ActionIDStateOutput ", function () {
const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions);
const read = sut.read(inputFilename);
const converted = sut.convert(read);
[
["a1", "A", true, [
['a1', 'A', 'a1', '1', 'K_A', 'SHIFT NCAPS'],
@ -675,6 +725,8 @@ describe('KeylayoutToKmnConverter', function () {
});
describe("get_KeyActionOutput_array__From__ActionStateOutput_array ", function () {
const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions);
const read = sut.read(inputFilename);
const b6_actionId_arr = [
['a0', '1', 'ˆ'],
@ -775,10 +827,4 @@ describe('KeylayoutToKmnConverter', function () {
});
});
// Todo remove
after(function () {
console.log("\nTESTS OK ##########################################################################");
});
});