feat(developer): kmc-convert seperate write into 3 functions

This commit is contained in:
Sabine 2025-01-06 19:29:23 +01:00
parent a99abc9b06
commit c102d83eed

View file

@ -46,7 +46,7 @@ import boxXmlArray = util.boxXmlArray;*/
// OK no added NCAPS when first modifier in modifierMap does not contain "caps" or"caps?"
// use length to clear array instead of defining evetry time new (modifierMap_ONE_InKeymapSelect.length=0
// naming of for-loop var i,j,k?...
// warning if contrADICTING RULES E:G: [ 'modifier_C0', 'SHIFT NCAPS', 'K_C', 'c', '0', '1' ], vs [ 'modifier_C0', 'SHIFT NCAPS', 'K_C', 'C', '1', '0' ],
// warning if contrADICTING RULES E:G: [ 'modifier_C0', 'SHIFT NCAPS', 'K_C', 'c'], vs [ 'modifier_C0', 'SHIFT NCAPS', 'K_C', 'C' ],
// print NCAPS as the first of the modifiers in create_kmn_modifier
// use boxXmlArray from codebase instead of my own
// where are rules for action+none ( a, e, u, etc)
@ -185,13 +185,12 @@ export class KeylayoutToKmnConverter {
*/
public read(filename: string): convert_object {
const modifierMap_ALL_KeyMapSelects: string[][] = [] // modifier for each keymapselect
const modifierBehaviors: string[][] = [] // modifier for each keymapselect
const kmn_Rules_AllLayers: Uint8Array[][] = []
// TODO remove unneccassary elements
const DataObject: convert_object = {
name: "Ukelele-kmn", // needed?? remove
ArrayOf_Element_ModifierMaps_ALLKeyMapSelect: modifierMap_ALL_KeyMapSelects, // 18 modifiers in 8 KeyMapSelect(behaviors)
ArrayOf_Element_ModifierMaps_ALLKeyMapSelect: modifierBehaviors, // 18 modifiers in 8 KeyMapSelect(behaviors)
ArrayOf_processed_RuleData: kmn_Rules_AllLayers,
};
@ -214,29 +213,23 @@ export class KeylayoutToKmnConverter {
const parser = new XMLParser(options);
const jsonObj = parser.parse(xmlFile); // get plain Object
// const duplicate_layouts_array: string[] = [] // array holding the layouts e.g. ANSI or JIS // needed?? I think no
// jsonObj now contains only arrays; no single fields
boxArrays_S(jsonObj.keyboard);
// in case there always ANSI which is always keyMapSet[0]
// const keyMapSet_ANSI_count = 0
// .........................................................
// MODIFIER MAP: get behaviours(=MapIndex) and modifiers (shift? leftShift caps? )
// .........................................................
for (let j = 0; j < jsonObj.keyboard.modifierMap.keyMapSelect.length; j++) {
const modifierMap_ONE_InKeymapSelect: string[] = []
const singleModifierSet: string[] = []
for (let k = 0; k < jsonObj.keyboard.modifierMap.keyMapSelect[j].modifier.length; k++) {
modifierMap_ONE_InKeymapSelect.push(jsonObj.keyboard.modifierMap.keyMapSelect[j].modifier[k]['@_keys'])
singleModifierSet.push(jsonObj.keyboard.modifierMap.keyMapSelect[j].modifier[k]['@_keys'])
}
modifierMap_ALL_KeyMapSelects.push(modifierMap_ONE_InKeymapSelect)
modifierBehaviors.push(singleModifierSet)
}
// Todo ? move to convert?
// TODO review condition
// start to read other data
return this.createRuleData(DataObject, jsonObj)
}
@ -260,41 +253,10 @@ export class KeylayoutToKmnConverter {
//TODO need to use export const USVirtualKeyCodes here
public write(data_ukelele: convert_object): boolean {
// *************************************************************
// **** write stores *******************************************
// *************************************************************
let data = "\n"
data += "c\n"
data += "c Keyman keyboard generated by kmn-convert\n"
data += "c\n"
data += this.createDataToWrite(data_ukelele)
data += "\n"
data += '\########## OK #################################################################\n'
data += "store(&VERSION) \'...\'\n"
data += "store(&TARGETS) \'any\'\n"
data += "store(&KEYBOARDVERSION) \'...\'\n"
data += "store(&COPYRIGHT) '© 2024 SIL International\n"
// TODO what else ??
data += '\########## OK #################################################################\n'
data += "\n"
data += "begin Unicode > use(main)\n\n"
data += "group(main) using keys\n\n"
data += '\########## OK #################################################################\n'
data += "Tipp: if K_? is replaced by undefined-> no enry in kmn_Key_Name=> add K_? there and it will be shown here\n"
data += "Tipp: keys that are marked with sction do not aoear in ukelele_Array_output->do not appear in kmn\n"
data += "\n"
// *************************************************************
// **** write rules ********************************************
// *************************************************************
// if caps is used in .keylayout-file we need to add NCAPS in the kmn-file
data += this.writeLastPart(data_ukelele) + '\n'
/*writeFileSync("data/MyResult.kmn", data, { flag: "w" })*/
this.callbacks.fs.writeFileSync("data/MyResult.kmn", new TextEncoder().encode(data)) // not usable here since it takes UInt8array data
@ -307,13 +269,9 @@ export class KeylayoutToKmnConverter {
data += '\n'
}
//... helpers .............................................................................................
// TODO move outside of class?
// ToDo keep only uint8array-version
// for more info about mapping and cases C0-C4
// see https://docs.google.com/document/d/1ISjACTA9aUBueTo1AoKnOsI6QR5kXeeD_maI0XUyXqg/edit?tab=t.0
// for more info about mapping and cases C0-C4 see https://docs.google.com/document/d/1ISjACTA9aUBueTo1AoKnOsI6QR5kXeeD_maI0XUyXqg/edit?tab=t.0
public createRuleData(data_ukelele: convert_object, jsonObj: any): convert_object {
const DataArray_U8: Uint8Array[][] = []
@ -323,16 +281,15 @@ export class KeylayoutToKmnConverter {
const used_Keys_count = 51
const isCapsused = this.checkIfCapsUsed(data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect)
// loop keys 0-50 (= all that we use)
//for (let j = 0; j < jsonObj.keyboard.keyMapSet[0].keyMap[i].key.length; j++) {
// loop keys 0-50 (= all keys we use)
for (let j = 0; j < used_Keys_count; j++) {
// loop behaviors
// loop behaviors ( in ukelele it is possible to define multiple modifier combinations that behave the same)
for (let i = 0; i < jsonObj.keyboard.keyMapSet[0].keyMap.length; i++) {
// ......................................................................................................
// case C0: output ......................................................................................
// a key is mapped to a character ( code-> output) ......................................................
// a key is mapped to a character directly ( code-> output) .............................................
// ...............e. g. <key code="1" output="s"/> ......................................................
// ......................................................................................................
// in keys at top for code 1 (K_S) take output ("s") [italian copy]
@ -343,7 +300,7 @@ export class KeylayoutToKmnConverter {
if (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output'] !== undefined) {
output_id = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_output']
// loop modifiers
// loop modifier combinations
for (let l = 0; l < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i].length; l++) {
const DataArraySingleStateC0_U8: Uint8Array[] = []
@ -363,29 +320,26 @@ export class KeylayoutToKmnConverter {
}
// ......................................................................................................
// actions ...............................................................................
// case C1: action + state none + output ................................................................
// a key is mapped to an action and then to an output ...................................................
// code->action->action(none)->action(output) ...........................................................
// ...............e. g. <when state="none" output="a" ...................................................
// ......................................................................................................
// in keys at top for code 0 (K_A) take actions id (a9) [italian copy]
// get modifiers [modifer of Keymap index 0]
// goto id a9
// in action id a9 find "none"
// get output "a"
// write [modifer-of-Keymap-index-0 K_A] > a
// ......................................................................................................
else if (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action'] !== undefined) {
// ......................................................................................................
// case C1: action + state none + output ..............................................................
// a key is mapped to an action and then to an output ...................................................
// code->action->action(none)->action(output) ...........................................................
// ...............e. g. <when state="none" output="a" ...................................................
// ......................................................................................................
// in keys at top for code 0 (K_A) take actions id (a9) [italian copy]
// get modifiers [modifer of Keymap index 0]
// goto id a9
// in action id a9 find "none"
// get output "a"
// write [modifer-of-Keymap-index-0 K_A] > a
// ......................................................................................................
action_id = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['@_action']
const result_C1 = this.lookup_6_ActionNone__To__ActionOutput(jsonObj, action_id)
const result_C1_U8 = new TextEncoder().encode(this.lookup_6_ActionNone__To__ActionOutput(jsonObj, action_id))
// modifiers
// loop modifiers
for (let l = 0; l < data_ukelele.ArrayOf_Element_ModifierMaps_ALLKeyMapSelect[i].length; l++) {
const DataArraySingleStateC1_U8: Uint8Array[] = []
@ -547,7 +501,7 @@ export class KeylayoutToKmnConverter {
}
}
// ......................................................................................................
// case C4: action + state none + Next ............................................................DONE .
// case C4: action + state none + Next ..................................................................
// ...............e. g. <when state="none" next="4"/> ...................................................
// a key is mapped to an action and then to a terminator ................................................
// code->action->action(none)->action(next)->terminator(output) .........................................
@ -596,8 +550,6 @@ export class KeylayoutToKmnConverter {
return data_ukelele
}
// public lookup_2_KeyMapAction__To__ActionAction() { }
public lookup_3_ActionNone__To__ActionNext(data: any, search: string): string {
for (let jj = 0; jj < data.keyboard.actions.action.length; jj++) {
if (data.keyboard.actions.action[jj]['@_id'] === search) {
@ -609,7 +561,6 @@ export class KeylayoutToKmnConverter {
}
return ""
}
//public lookup_4_ActionNext__To__ActionState() { }
public lookup_5_ActionState__To__ActionNext(data: any, action_idName: string): string[] {
const returnarray: string[] = []
// e.g. action_idName = 3
@ -658,17 +609,6 @@ export class KeylayoutToKmnConverter {
}
return OutputValue
}
//public lookup_7_ActionState__To__ActionOutput() { }
//public lookup_8_ActionNext__To__TerminatorState() { }
public lookup_9_TerminatorState__To__TerminatorOutput_ui8(data: any, search: string): Uint8Array {
for (let jj = 0; jj < data.keyboard.terminators.when.length; jj++) {
if (data.keyboard.terminators.when[jj]['@_state'] === search) {
return new TextEncoder().encode(data.keyboard.terminators.when[jj]['@_output']);
}
}
return new TextEncoder().encode("")
}
public lookup_9_TerminatorState__To__TerminatorOutput_str(data: any, search: string): string {
let OutputValue = ""
for (let jj = 0; jj < data.keyboard.terminators.when.length; jj++) {
@ -695,31 +635,6 @@ export class KeylayoutToKmnConverter {
}
return 999
}
public lookup_11_KeyMapAction__To__KeyIndex(data: any, search: string): number {
for (let kk = 0; kk < data.keyboard.keyMapSet[0].keyMap.length; kk++) {
for (let jj = 0; jj < data.keyboard.keyMapSet[0].keyMap[kk].key.length; jj++) {
if (data.keyboard.keyMapSet[0].keyMap[kk].key[jj]['@_action'] === search) {
return data.keyboard.keyMapSet[0].keyMap[kk]['@_index']
}
}
}
return 999
}
// get all entries that result in state 3
public lookup_12_ActionNext__from__ActionState(data: any, search: string): string {
// loop all action
for (let jj = 0; jj < data.keyboard.actions.action.length; jj++) {
// loop all when
for (let kk = 0; kk < data.keyboard.actions.action[jj].when.length; kk++) {
// if next === a´search
if (data.keyboard.actions.action[jj].when[kk]['@_next'] === search) {
// return actionIDName
return data.keyboard.actions.action[jj]['@_id']
}
}
}
return ""
}
public lookup_13_ActionNext__To__ActionID(data: any, search: string) {
for (let ll = 0; ll < data.keyboard.actions.action.length; ll++) {
for (let mm = 0; mm < data.keyboard.actions.action[ll].when.length; mm++) {
@ -747,7 +662,6 @@ export class KeylayoutToKmnConverter {
return mapIndexArray_max
}
/**
* @brief member function to return the unicode value of a character
* @param character the value that will converted
@ -905,85 +819,19 @@ export class KeylayoutToKmnConverter {
else return ""
}
public useElementAsString(u18ArrayElemnent: Uint8Array): string {
return new TextDecoder().decode(u18ArrayElemnent)
}
public useAsString(u18ArrayElemnent: Uint8Array[]): string {
let str = ""
for (let i = 0; i < u18ArrayElemnent.length; i++) {
str = str + " " + new TextDecoder().decode(u18ArrayElemnent[i])
}
return str
}
//----------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------
public writeLastPart(data_ukelele: convert_object): string {
// create a string array .......................................................
const workArray2D: string[][] = []
for (let k = 0; k < data_ukelele.ArrayOf_processed_RuleData.length; k++) {
const array1D: string[] = []
for (let l = 0; l < data_ukelele.ArrayOf_processed_RuleData[k].length; l++) {
const u8data = data_ukelele.ArrayOf_processed_RuleData[k][l]
array1D.push(this.useElementAsString(u8data))
}
workArray2D.push(array1D)
}
console.log("workArray2D ", workArray2D)
public createData_Deadkeys(data_ukelele: convert_object, workArray2D: string[][]): string {
//°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
// FIRST PART RULES °° ( + [NCAPS K_S] > 's') °°°°°°°°°°°°°°°°°°°°°
//°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
let data: string = ""
// select only lines that contain C0 or C1 and no empty fields. Also remove duplicates
const [uniqueDeadkeys_first] = workArray2D.reduce((acc, curr) => {
if ((curr[3] !== "") && ((curr[0] === "first_modifier_C0") || (curr[0] === "first_modifier_C1"))) {
const [uniq, set] = acc;
if (!set.has(curr.join(','))) {
set.add(curr.join(','));
uniq.push(curr);
}
}
return acc;
}, [[], new Set()],
);
let keymarker = ""
for (let kkk = 0; kkk < uniqueDeadkeys_first.length; kkk++) {
// find key nr
let keyNr = 0;
for (let pp = 0; pp < 50; pp++) {
if (this.map_UkeleleKC_To_VK(pp) === uniqueDeadkeys_first[kkk][2])
keyNr = pp
}
// skip keyNr 48 ( TAB )
if (keyNr === 48)
continue
if (keymarker !== uniqueDeadkeys_first[kkk][2])
data += '\n'
data += keyNr + "-(modif:" + "ii" + "-" + "i" + `) + [` + (uniqueDeadkeys_first[kkk][1] + ' ' + uniqueDeadkeys_first[kkk][2]).trim() + `] > \'` + uniqueDeadkeys_first[kkk][3] + '\'\n'
keymarker = uniqueDeadkeys_first[kkk][2]
}
data += '\n'
console.log("data ", data)
//°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
// DEADKEY RULES °° ([RALT K_8] > dk(00B4) °°°°°°°°°°°°°°°°°°°°°°°°
//°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
// filter for dk values
data += '\########## OK #################################################################\n'
data += '\nNOW MY C4 RULES **ccc ********* (only to get 02C6 ect) *********************\n\n'
// select only lines that contain isTerminator and remove duplicates
// select only lines that contain "isTerminator" and remove duplicates
const [uniqueDeadkeys] = workArray2D.reduce((acc, curr) => {
if (curr[4] === "isTerminator") {
const [uniq, set] = acc;
@ -1002,43 +850,42 @@ export class KeylayoutToKmnConverter {
data += line + '\n'
}
//°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
// DEADKEYABLE/DEADKEYED LIST (a,A,e,E) - (â,Â,ê,ê) °°°°°°°°°°°°°°°
//°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
// we have 5 different types:
/*
C0: size: 4 ['first_modifier_C0', 'RIGHTSHIFT ', 'K_S', 'S' ]
C1: size: 4 ['first_modifier_C1', 'CAPS', 'K_N', 'N' ],
C2: size: 5 ['first_modifier_C2', 'CAPS', 'K_E', 'K_9', 'È' ], use 2.(K_E) and 4.('È') to get Name and DEADKEYED
C3: size: 6 ['first_modifier_C3', 'NCAPS RALT', 'K_8', 'NCAPS RALT', 'K_U', 'ˆ' ],
C4: size: 4 ['first_modifier_C4', 'NCAPS 0', 'K_SPACE', '' ],
C4: size: 7 ['first_modifier_C4', 'NCAPS RALT', 'K_N', '˜', 'isTerminator', '˜', '02DC '], use 2.(K_N) , 5. (isTerminator) and 6.('02DC') to get Name and DEADKEY in hex
/*
How to create rules from keylayout data ffrom data_ukelele.ArrayOf_processed_RuleData:
There are 6 different types of data entries (C0-C4) in data_ukelele.ArrayOf_processed_RuleData e.g. that contain all data to retrieve deadkeys, deadkeyables and deadkeyed characters:
C0: (size: 4) ['first_modifier_C0', 'RIGHTSHIFT ', 'K_S', 'S' ]
C1: (size: 4) ['first_modifier_C1', 'CAPS', 'K_A', 'A' ],
C2: (size: 5) ['first_modifier_C2', 'CAPS', 'K_A', 'K_N', 'Ã' ], use 2.(K_A) and 4.('Ã') to get name and DEADKEYED
C3: (size: 6) ['first_modifier_C3', 'NCAPS RALT', 'K_8', 'NCAPS RALT', 'K_U', 'ˆ' ],
C4: (size: 4) ['first_modifier_C4', 'NCAPS 0', 'K_SPACE', '' ],
C4: (size: 7) ['first_modifier_C4', 'NCAPS RALT', 'K_N', '˜', 'isTerminator', '˜', '02DC '], use 2.(K_N) , 5. (isTerminator) and 6.('02DC') to get key name and DEADKEY in hex
Find DEADKEYABLE
1) first_modifier_C1 CAPS K_A A
2) first_modifier_C2 CAPS K_A K_EQUAL Â
3) first_modifier_C2 CAPS K_A K_9 À
- Find C2 rule with Deadkeyed ( n = 5)
- get C1 rule with same second and third entries -> (first_modifier_C1 CAPS K_A)
- get 4th entry ===> DEADKEYABLE (e.g. A)
To Find a DEADKEY e.g. ^
1) look in modifier_C4 with 'isTerminator' included (n = 7)
2) get 7th entry ===> DEADKEY (e.g. 02DC)
To Find a DEADKEYABLE ( a character that can be converted to a deadkey e.g. A (-> Ã) ):
1) first_modifier_C1 CAPS K_A A
2) first_modifier_C2 CAPS K_A K_N Ã
- Find C2 rule with 5 entries (Deadkeyed) (e.g. first_modifier_C2 CAPS K_A K_N Ã)
- get C1 rule with same second and third entries -> (e.g. first_modifier_C1 CAPS K_A)
- get 2nd entry of C1 rule ===> DEADKEYABLE (e.g. A)
Find DEADKEY
1) look in modifier_C4 (n = 7)
2) get 7th entry ===> DEADKEY (e.g. 02DC)
Find DEADKEYED
1) look in modifier_C2
2) get 3rd entry (='K_A')
3) get 5th entry ===> DEADKEYED (='Â')
To Find a DEADKEYED ( a character that has been converted from another character e.g. Ã ):
1) look in modifier_C2 CAPS K_A K_N Ã
2) get 3rd entry (='K_A')
3) get 5th entry ===> DEADKEYED (='Ã')
*/
// create deadkeyables_raw, deadkeyed_raw array
let deadkeyables_raw: string[][] = []
let deadkeyed_raw: string[][] = []
// find deadkeyable [ 'first_modifier_C1', 'CAPS', 'K_A', 'A', '', '', '' ]
deadkeyables_raw = workArray2D.filter(function ([A, B, C, D, E, F, G]) {
// find C1 line for deadkeyable [ 'first_modifier_C1', 'CAPS', 'K_A', 'A' ]
deadkeyables_raw = workArray2D.filter(function ([A, B, C, D]) {
return ((A === "first_modifier_C1") /*&& (B === shiftstate) && (C === key_name)*/
&& ((C !== "K_SPACE") && (D !== ""))
)
@ -1046,8 +893,8 @@ export class KeylayoutToKmnConverter {
console.log("deadkeyables_raw", deadkeyables_raw.length, deadkeyables_raw)
// find deadkeyed [ 'first_modifier_C2', 'CAPS', 'K_A', 'K_N', 'Ã' ]
deadkeyed_raw = workArray2D.filter(function ([A, B, C, D, E, F, G]) {
// find C2 line for deadkeyed [ 'first_modifier_C2', 'CAPS', 'K_A', 'K_N', 'Ã' ]
deadkeyed_raw = workArray2D.filter(function ([A, B, C]) {
return ((A === "first_modifier_C2")/* && (B === shiftstate) && (C === key_name)*/
&& ((C !== "K_SPACE"))
)
@ -1055,27 +902,29 @@ export class KeylayoutToKmnConverter {
console.log("deadkeyed_raw", deadkeyed_raw.length, deadkeyed_raw)
const join_dkable_dked: any[][] = []
// loop dedkeyables, take Keyname
const dk_array_comlpete: any[][] = []
// create 2D array with data of both deadkeyables_raw, deadkeyed_raw and remove possible duplicates
for (let rr = 0; rr < deadkeyables_raw.length; rr++) {
// loop dedkeyed, take Keyname
// loop deadkeyed_raw, take Keyname
for (let ss = 0; ss < deadkeyed_raw.length; ss++) {
const dkable_dked_array: any[] = []
//if available ( shiftstate the same, keyname the same)
if ((deadkeyables_raw[rr][1] === deadkeyed_raw[ss][1])
&& ((deadkeyables_raw[rr][2] === deadkeyed_raw[ss][2]))) {
dkable_dked_array.push(deadkeyables_raw[rr][3]) // deadkeyable e.g. a
dkable_dked_array.push(deadkeyed_raw[ss][3]) // Keyname dk e.g. K_EQUAL
dkable_dked_array.push(deadkeyed_raw[ss][4]) // deadkeyed e.g. â
const dk_array: any[] = []
//if available ( if both have the same shiftstate and keyname)
if ((deadkeyables_raw[rr][1] === deadkeyed_raw[ss][1]) && ((deadkeyables_raw[rr][2] === deadkeyed_raw[ss][2]))) {
dk_array.push(deadkeyables_raw[rr][3]) // deadkeyable e.g. A
dk_array.push(deadkeyed_raw[ss][3]) // Keyname dk e.g. K_N
dk_array.push(deadkeyed_raw[ss][4]) // deadkeyed e.g. Ã
}
if (dkable_dked_array.length > 0)
join_dkable_dked.push(dkable_dked_array)
if (dk_array.length > 0)
dk_array_comlpete.push(dk_array)
}
}
console.log("join_dkable_dked", join_dkable_dked.length, join_dkable_dked)
console.log("dk_array_comlpete", dk_array_comlpete.length, dk_array_comlpete)
// remove duplicates
const [unique_join_dkable_dked] = join_dkable_dked.reduce((acc, curr) => {
const [unique_dk_array_comlpete] = dk_array_comlpete.reduce((acc, curr) => {
const [uniq, set] = acc;
if (!set.has(curr.join(','))) {
set.add(curr.join(','));
@ -1084,21 +933,22 @@ export class KeylayoutToKmnConverter {
return acc;
}, [[], new Set()],
);
console.log("unique_join_dkable_dked", unique_join_dkable_dked.length, unique_join_dkable_dked);
console.log("unique_join_dkable_dked", unique_dk_array_comlpete.length, unique_dk_array_comlpete);
// create 2dArray uniqueDeadkeys.length*unique_join_dkable_dked
const deadkeyedArray: string[][] = Array.from({ length: uniqueDeadkeys.length }, () => new Array(2).fill(''));
const deadkeyablesArray: string[][] = Array.from({ length: uniqueDeadkeys.length }, () => new Array(1).fill(''));
// deadkeyablesArray'a' 'A' 'e' 'E' 'y' 'Y' 'o' 'O' 'u' 'U' 'i' 'I'
// deadkeyedArray 'ä' 'Ä' 'ë' 'Ë' 'ÿ' 'Ÿ' 'ö' 'Ö' 'ü' 'Ü' 'ï' 'Ï'
const deadkeyedElement: string[][] = Array.from({ length: uniqueDeadkeys.length }, () => new Array(2).fill(''));
const deadkeyablesElement: string[][] = Array.from({ length: uniqueDeadkeys.length }, () => new Array(1).fill(''));
for (let i = 0; i < uniqueDeadkeys.length; i++) {
for (let j = 0; j < unique_join_dkable_dked.length; j++) {
for (let j = 0; j < unique_dk_array_comlpete.length; j++) {
if (uniqueDeadkeys[i][2] === unique_join_dkable_dked[j][1]) {
deadkeyablesArray[i][0] = deadkeyablesArray[i][0] + "\'" + unique_join_dkable_dked[j][0] + "\' "
deadkeyedArray[i][0] = deadkeyedArray[i][0] + "\'" + unique_join_dkable_dked[j][2] + "\' "
if (uniqueDeadkeys[i][2] === unique_dk_array_comlpete[j][1]) {
deadkeyablesElement[i][0] = deadkeyablesElement[i][0] + "\'" + unique_dk_array_comlpete[j][0] + "\' "
deadkeyedElement[i][0] = deadkeyedElement[i][0] + "\'" + unique_dk_array_comlpete[j][2] + "\' "
}
}
deadkeyedArray[i][1] = (uniqueDeadkeys[i][6])
deadkeyedElement[i][1] = (uniqueDeadkeys[i][6])
}
data += "\n"
@ -1106,15 +956,153 @@ export class KeylayoutToKmnConverter {
data += '\nmatch > use(deadkeys)\n\n'
data += '\ngroup(deadkeys)\n\n'
// finally write out
for (let i = 0; i < deadkeyablesArray.length; i++) {
data += "\n\ndk: " + deadkeyedArray[i][1]
data += "\ndeadkeyablesArray" + deadkeyablesArray[i][0]
data += "\ndeadkeyedArray " + deadkeyedArray[i][0]
for (let i = 0; i < deadkeyablesElement.length; i++) {
data += "\n\ndk: " + deadkeyedElement[i][1]
data += "\ndeadkeyablesArray" + deadkeyablesElement[i][0]
data += "\ndeadkeyedArray " + deadkeyedElement[i][0]
}
return data
}
public createData_Rules(data_ukelele: convert_object, workArray2D: string[][]): string {
const maxkey = 50
let data: string = ""
let keymarker = ""
// select only lines that contain C0 or C1 and create an output. Also remove duplicates
const [uniqueDeadkeys] = workArray2D.reduce((acc, curr) => {
if ((curr[3] !== "") && ((curr[0] === "first_modifier_C0") || (curr[0] === "first_modifier_C1"))) {
const [uniq, set] = acc;
if (!set.has(curr.join(','))) {
set.add(curr.join(','));
uniq.push(curr);
}
}
return acc;
}, [[], new Set()],
);
for (let kkk = 0; kkk < uniqueDeadkeys.length; kkk++) {
// lookup key nr of the key that is being processed
let keyNr = 0;
for (let pp = 0; pp < maxkey; pp++) {
if (this.map_UkeleleKC_To_VK(pp) === uniqueDeadkeys[kkk][2])
keyNr = pp
}
// skip keyNr 48 ( TAB )
if (keyNr === 48)
continue
// add a line after rules of each key
if (uniqueDeadkeys[kkk][2] !== keymarker)
data += '\n'
data += keyNr + "-(modif:" + "ii" + "-" + "i" + `) + [` + (uniqueDeadkeys[kkk][1] + ' ' + uniqueDeadkeys[kkk][2]).trim() + `] > \'` + uniqueDeadkeys[kkk][3] + '\'\n'
keymarker = uniqueDeadkeys[kkk][2]
}
data += '\n'
console.log("data ", data)
return data
}
public createData_Stores(data_ukelele: convert_object): string {
let data: string = ""
data += "c\n"
data += "c Keyman keyboard generated by kmn-convert\n"
data += "c\n"
data += "\n"
data += '\########## OK #################################################################\n'
data += "store(&VERSION) \'...\'\n"
data += "store(&TARGETS) \'any\'\n"
data += "store(&KEYBOARDVERSION) \'...\'\n"
data += "store(&COPYRIGHT) '© 2024 SIL International\n"
// TODO what else ??
data += '\########## OK #################################################################\n'
data += "\n"
data += "begin Unicode > use(main)\n\n"
data += "group(main) using keys\n\n"
data += '\########## OK #################################################################\n'
data += "Tipp: if K_? is replaced by undefined-> no enry in kmn_Key_Name=> add K_? there and it will be shown here\n"
data += "Tipp: keys that are marked with sction do not aoear in ukelele_Array_output->do not appear in kmn\n"
data += "\n"
return data
}
public createDataToWrite(data_ukelele: convert_object): string {
// create a string array to work with ................................................
const workArray2D: string[][] = []
for (let k = 0; k < data_ukelele.ArrayOf_processed_RuleData.length; k++) {
const array1D: string[] = []
for (let l = 0; l < data_ukelele.ArrayOf_processed_RuleData[k].length; l++) {
const u8data = data_ukelele.ArrayOf_processed_RuleData[k][l]
array1D.push(new TextDecoder().decode(u8data))
}
workArray2D.push(array1D)
}
console.log("workArray2D ", workArray2D)
let data: string = ""
data += this.createData_Stores(data_ukelele)
data += this.createData_Rules(data_ukelele, workArray2D)
data += this.createData_Deadkeys(data_ukelele, workArray2D)
return data
}
// public lookup_2_KeyMapAction__To__ActionAction() { }
//public lookup_4_ActionNext__To__ActionState() { }
//public lookup_7_ActionState__To__ActionOutput() { }
//public lookup_8_ActionNext__To__TerminatorState() { }
/* public lookup_9_TerminatorState__To__TerminatorOutput_ui8(data: any, search: string): Uint8Array {
for (let jj = 0; jj < data.keyboard.terminators.when.length; jj++) {
if (data.keyboard.terminators.when[jj]['@_state'] === search) {
return new TextEncoder().encode(data.keyboard.terminators.when[jj]['@_output']);
}
}
return new TextEncoder().encode("")
}*/
/*public lookup_11_KeyMapAction__To__KeyIndex(data: any, search: string): number {
for (let kk = 0; kk < data.keyboard.keyMapSet[0].keyMap.length; kk++) {
for (let jj = 0; jj < data.keyboard.keyMapSet[0].keyMap[kk].key.length; jj++) {
if (data.keyboard.keyMapSet[0].keyMap[kk].key[jj]['@_action'] === search) {
return data.keyboard.keyMapSet[0].keyMap[kk]['@_index']
}
}
}
return 999
}*/
// get all entries that result in state 3
/*public lookup_12_ActionNext__from__ActionState(data: any, search: string): string {
// loop all action
for (let jj = 0; jj < data.keyboard.actions.action.length; jj++) {
// loop all when
for (let kk = 0; kk < data.keyboard.actions.action[jj].when.length; kk++) {
// if next === a´search
if (data.keyboard.actions.action[jj].when[kk]['@_next'] === search) {
// return actionIDName
return data.keyboard.actions.action[jj]['@_id']
}
}
}
return ""
}*/
/*
public useAsString(u18ArrayElemnent: Uint8Array[]): string {
let str = ""
for (let i = 0; i < u18ArrayElemnent.length; i++) {
str = str + " " + new TextDecoder().decode(u18ArrayElemnent[i])
}
return str
}*/
}