mirror of
https://github.com/keymanapp/keyman.git
synced 2026-10-15 02:17:32 +00:00
feat(developer): kmc-convert seperate write into 3 functions
This commit is contained in:
parent
a99abc9b06
commit
c102d83eed
1 changed files with 227 additions and 239 deletions
|
|
@ -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(©RIGHT) '© 2024 SIL International\n"
|
||||
// TODO what else ??
|
||||
|
||||
data += '\########## OK #################################################################\n'
|
||||
data += "\n"
|
||||
data += "begin Unicode > use(main)\n\n"
|
||||
data += "group(main) using keys\n\n"
|
||||
|
||||
data += '\########## OK #################################################################\n'
|
||||
data += "Tipp: if K_? is replaced by undefined-> no enry in kmn_Key_Name=> add K_? there and it will be shown here\n"
|
||||
data += "Tipp: keys that are marked with sction do not aoear in ukelele_Array_output->do not appear in kmn\n"
|
||||
data += "\n"
|
||||
|
||||
// *************************************************************
|
||||
// **** 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(©RIGHT) '© 2024 SIL International\n"
|
||||
// TODO what else ??
|
||||
|
||||
data += '\########## OK #################################################################\n'
|
||||
data += "\n"
|
||||
data += "begin Unicode > use(main)\n\n"
|
||||
data += "group(main) using keys\n\n"
|
||||
|
||||
data += '\########## OK #################################################################\n'
|
||||
data += "Tipp: if K_? is replaced by undefined-> no enry in kmn_Key_Name=> add K_? there and it will be shown here\n"
|
||||
data += "Tipp: keys that are marked with sction do not aoear in ukelele_Array_output->do not appear in kmn\n"
|
||||
data += "\n"
|
||||
|
||||
return data
|
||||
}
|
||||
|
||||
public createDataToWrite(data_ukelele: convert_object): string {
|
||||
|
||||
// create a string array to work with ................................................
|
||||
const workArray2D: string[][] = []
|
||||
for (let k = 0; k < data_ukelele.ArrayOf_processed_RuleData.length; k++) {
|
||||
const array1D: string[] = []
|
||||
for (let l = 0; l < data_ukelele.ArrayOf_processed_RuleData[k].length; l++) {
|
||||
const u8data = data_ukelele.ArrayOf_processed_RuleData[k][l]
|
||||
array1D.push(new TextDecoder().decode(u8data))
|
||||
}
|
||||
workArray2D.push(array1D)
|
||||
}
|
||||
console.log("workArray2D ", workArray2D)
|
||||
|
||||
|
||||
let data: string = ""
|
||||
data += this.createData_Stores(data_ukelele)
|
||||
data += this.createData_Rules(data_ukelele, workArray2D)
|
||||
data += this.createData_Deadkeys(data_ukelele, workArray2D)
|
||||
return data
|
||||
}
|
||||
|
||||
// public lookup_2_KeyMapAction__To__ActionAction() { }
|
||||
//public lookup_4_ActionNext__To__ActionState() { }
|
||||
//public lookup_7_ActionState__To__ActionOutput() { }
|
||||
//public lookup_8_ActionNext__To__TerminatorState() { }
|
||||
/* public lookup_9_TerminatorState__To__TerminatorOutput_ui8(data: any, search: string): Uint8Array {
|
||||
for (let jj = 0; jj < data.keyboard.terminators.when.length; jj++) {
|
||||
if (data.keyboard.terminators.when[jj]['@_state'] === search) {
|
||||
return new TextEncoder().encode(data.keyboard.terminators.when[jj]['@_output']);
|
||||
}
|
||||
}
|
||||
return new TextEncoder().encode("")
|
||||
}*/
|
||||
/*public lookup_11_KeyMapAction__To__KeyIndex(data: any, search: string): number {
|
||||
for (let kk = 0; kk < data.keyboard.keyMapSet[0].keyMap.length; kk++) {
|
||||
for (let jj = 0; jj < data.keyboard.keyMapSet[0].keyMap[kk].key.length; jj++) {
|
||||
if (data.keyboard.keyMapSet[0].keyMap[kk].key[jj]['@_action'] === search) {
|
||||
return data.keyboard.keyMapSet[0].keyMap[kk]['@_index']
|
||||
}
|
||||
}
|
||||
}
|
||||
return 999
|
||||
}*/
|
||||
// get all entries that result in state 3
|
||||
/*public lookup_12_ActionNext__from__ActionState(data: any, search: string): string {
|
||||
// loop all action
|
||||
for (let jj = 0; jj < data.keyboard.actions.action.length; jj++) {
|
||||
// loop all when
|
||||
for (let kk = 0; kk < data.keyboard.actions.action[jj].when.length; kk++) {
|
||||
// if next === a´search
|
||||
if (data.keyboard.actions.action[jj].when[kk]['@_next'] === search) {
|
||||
// return actionIDName
|
||||
return data.keyboard.actions.action[jj]['@_id']
|
||||
}
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}*/
|
||||
/*
|
||||
public useAsString(u18ArrayElemnent: Uint8Array[]): string {
|
||||
let str = ""
|
||||
for (let i = 0; i < u18ArrayElemnent.length; i++) {
|
||||
str = str + " " + new TextDecoder().decode(u18ArrayElemnent[i])
|
||||
}
|
||||
return str
|
||||
}*/
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue