From ffe00c06b546f0a858ae65ebe461e40a49395a98 Mon Sep 17 00:00:00 2001 From: "Steven R. Loomis" Date: Sat, 30 Sep 2023 18:54:37 -0500 Subject: [PATCH] =?UTF-8?q?feat(common):=20scancode=20-=20move=20vkey=20ma?= =?UTF-8?q?p=20generation=20into=20KeysCompiler=20=F0=9F=99=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - also fix visual keyboard compiler to use same code For: #9403 --- common/web/types/src/kvk/kvk-file.ts | 3 +- .../test-ldml-keyboard-xml-reader.ts | 168 ------------------ developer/src/kmc-ldml/src/compiler/keys.ts | 25 ++- .../src/compiler/visual-keyboard-compiler.ts | 19 +- 4 files changed, 37 insertions(+), 178 deletions(-) diff --git a/common/web/types/src/kvk/kvk-file.ts b/common/web/types/src/kvk/kvk-file.ts index ca3f522e72d..ff99adca5df 100644 --- a/common/web/types/src/kvk/kvk-file.ts +++ b/common/web/types/src/kvk/kvk-file.ts @@ -49,6 +49,7 @@ export interface BUILDER_KVK_KEY { export const BUILDER_KVK_KEY_Size = 9; // size of fixed elements of BUILDER_KVK_KEY export const enum BUILDER_KVK_HEADER_FLAGS { + kvkhNone = 0x00, // no flags kvkh102 = 0x01, kvkhDisplayUnderlying = 0x02, kvkhUseUnderlying = 0x04, @@ -122,4 +123,4 @@ export default class KVKFile { }); } -}; \ No newline at end of file +}; diff --git a/common/web/types/test/ldml-keyboard/test-ldml-keyboard-xml-reader.ts b/common/web/types/test/ldml-keyboard/test-ldml-keyboard-xml-reader.ts index 667b817328c..296e36a8cc7 100644 --- a/common/web/types/test/ldml-keyboard/test-ldml-keyboard-xml-reader.ts +++ b/common/web/types/test/ldml-keyboard/test-ldml-keyboard-xml-reader.ts @@ -3,8 +3,6 @@ import 'mocha'; import {assert} from 'chai'; import { CommonTypesMessages } from '../../src/util/common-events.js'; import { testReaderCases } from '../helpers/reader-callback-test.js'; -import { KeyMap, USVirtualKeyCodes } from '../../src/consts/virtual-key-constants.js'; -import fs from 'node:fs'; function pluckKeysFromKeybag(keys: LKKey[], ids: string[]) { return keys.filter(({id}) => ids.indexOf(id) !== -1); @@ -143,169 +141,3 @@ describe('ldml keyboard xml reader tests', function () { }, ]); }); - -describe('verify scancodes', function () { - // TODO-LDML: Temporarily, the old maps are here to double check round trips. - const k = USVirtualKeyCodes; - - const USVirtualKeyMap: KeyMap = [ - // ` 1 2 3 4 5 6 7 8 9 0 - = [bksp] - [ k.K_BKQUOTE, k.K_1, k.K_2, k.K_3, k.K_4, k.K_5, k.K_6, k.K_7, k.K_8, k.K_9, k.K_0, k.K_HYPHEN, k.K_EQUAL ], - // [tab] Q W E R T Y U I O P [ ] \ - [ k.K_Q, k.K_W, k.K_E, k.K_R, k.K_T, k.K_Y, k.K_U, k.K_I, k.K_O, k.K_P, k.K_LBRKT, k.K_RBRKT, k.K_BKSLASH ], - // [caps] A S D F G H J K L ; ' [enter] - [ k.K_A, k.K_S, k.K_D, k.K_F, k.K_G, k.K_H, k.K_J, k.K_K, k.K_L, k.K_COLON, k.K_QUOTE ], - // [shift] Z X C V B N M , . / [shift] *=oE2 - [ k.K_Z, k.K_X, k.K_C, k.K_V, k.K_B, k.K_N, k.K_M, k.K_COMMA, k.K_PERIOD, k.K_SLASH ], - // space - [ k.K_SPACE ], - ]; - - const KSVirtualKeyMap: KeyMap = [ - // ` 1 2 3 4 5 6 7 8 9 0 - = YEN [bksp] - [ k.K_BKQUOTE, k.K_1, k.K_2, k.K_3, k.K_4, k.K_5, k.K_6, k.K_7, k.K_8, k.K_9, k.K_0, k.K_HYPHEN, k.K_EQUAL, k.K_BKSLASH /* YEN */ ], - // [tab] Q W E R T Y U I O P [ ] \ - [ k.K_Q, k.K_W, k.K_E, k.K_R, k.K_T, k.K_Y, k.K_U, k.K_I, k.K_O, k.K_P, k.K_LBRKT, k.K_RBRKT ], - // [caps] A S D F G H J K L ; ' [enter] - [ k.K_A, k.K_S, k.K_D, k.K_F, k.K_G, k.K_H, k.K_J, k.K_K, k.K_L, k.K_COLON, k.K_QUOTE ], - // [shift] Z X C V B N M , . / [shift] - [ k.K_Z, k.K_X, k.K_C, k.K_V, k.K_B, k.K_N, k.K_M, k.K_COMMA, k.K_PERIOD, k.K_SLASH ], - // space - [ k.K_SPACE ], - ]; - - const ISOVirtualKeyMap: KeyMap = [ - // ` 1 2 3 4 5 6 7 8 9 0 - = [bksp] - [ k.K_BKQUOTE, k.K_1, k.K_2, k.K_3, k.K_4, k.K_5, k.K_6, k.K_7, k.K_8, k.K_9, k.K_0, k.K_HYPHEN, k.K_EQUAL ], - // [tab] Q W E R T Y U I O P [ ] - [ k.K_Q, k.K_W, k.K_E, k.K_R, k.K_T, k.K_Y, k.K_U, k.K_I, k.K_O, k.K_P, k.K_LBRKT, k.K_RBRKT ], - // [caps] A S D F G H J K L ; ' \ [enter] - [ k.K_A, k.K_S, k.K_D, k.K_F, k.K_G, k.K_H, k.K_J, k.K_K, k.K_L, k.K_COLON, k.K_QUOTE, k.K_BKSLASH ], - // [shift] * Z X C V B N M , . / [shift] *=oE2 - [ k.K_oE2, k.K_Z, k.K_X, k.K_C, k.K_V, k.K_B, k.K_N, k.K_M, k.K_COMMA, k.K_PERIOD, k.K_SLASH ], - // space - [ k.K_SPACE ], - ]; - - const JISVirtualKeyMap: KeyMap = [ - // [Hankaku/Zenkaku] 1 2 3 4 5 6 7 8 9 0 - ^ ¥ [bksp] - [ k.K_BKQUOTE, k.K_1, k.K_2, k.K_3, k.K_4, k.K_5, k.K_6, k.K_7, k.K_8, k.K_9, k.K_0, k.K_HYPHEN, k.K_EQUAL, k.K_oE2 /* YEN */ ], - // [tab] Q W E R T Y U I O P @ [ [enter] - [ k.K_Q, k.K_W, k.K_E, k.K_R, k.K_T, k.K_Y, k.K_U, k.K_I, k.K_O, k.K_P, k.K_LBRKT, k.K_RBRKT ], - // [caps] A S D F G H J K L ; : ] [enter] - [ k.K_A, k.K_S, k.K_D, k.K_F, k.K_G, k.K_H, k.K_J, k.K_K, k.K_L, k.K_COLON, k.K_QUOTE, k.K_BKSLASH ], - // [shift] Z X C V B N M , . / _ [shift] - [ k.K_Z, k.K_X, k.K_C, k.K_V, k.K_B, k.K_N, k.K_M, k.K_COMMA, k.K_PERIOD, k.K_SLASH, k.k_oC1 /* ろ */ ], - // space - [ k.K_SPACE ], - ]; - - const ABNT2VirtualKeyMap: KeyMap = [ - // ' 1 2 3 4 5 6 7 8 9 0 - = [bksp] - [ k.K_BKQUOTE, k.K_1, k.K_2, k.K_3, k.K_4, k.K_5, k.K_6, k.K_7, k.K_8, k.K_9, k.K_0, k.K_HYPHEN, k.K_EQUAL ], - // [tab] Q W E R T Y U I O P ´ [ - [ k.K_Q, k.K_W, k.K_E, k.K_R, k.K_T, k.K_Y, k.K_U, k.K_I, k.K_O, k.K_P, k.K_LBRKT, k.K_RBRKT ], - // [caps] A S D F G H J K L ç ~ ] [enter] - [ k.K_A, k.K_S, k.K_D, k.K_F, k.K_G, k.K_H, k.K_J, k.K_K, k.K_L, k.K_COLON, k.K_QUOTE, k.K_BKSLASH ], - // [shift] \ Z X C V B N M , . ; / [shift] - [ k.K_oE2, k.K_Z, k.K_X, k.K_C, k.K_V, k.K_B, k.K_N, k.K_M, k.K_COMMA, k.K_PERIOD, k.K_SLASH, k.k_oC1 /* ABNT2 */ ], - // space - [ k.K_SPACE ], - ]; - - /** - * Map from a hardware constant to a keymap - * For the 'key' see constants.layr_list_hardware_map - */ - const HardwareToKeymap: Map = new Map( - [ - ["us", USVirtualKeyMap], - ["iso", ISOVirtualKeyMap], - ["jis", JISVirtualKeyMap], - ["abnt2", ABNT2VirtualKeyMap], - ["ks", KSVirtualKeyMap], - ] - ); - - this.slow(500); // 0.5 sec -- json schema validation takes a while - - // for err, convert a vkey name to a number - function findVkeyName(n : Number) : string { - for (const [k, v] of Object.entries(USVirtualKeyCodes)) { - if (v === n) { - return k; - } - } - return n.toString(); // punt - } - - testReaderCases([ - { - // We've read this above, but we're going to test for scancodes here - subpath: 'import-minimal.xml', - callback: (data, source, subpath, callbacks) => { - assert.ok(source?.keyboard3?.forms?.form); - - const ldmlFormIds = source?.keyboard3?.forms?.form.map(f => f.id); - const kmcFormIds = Array.from(HardwareToKeymap.keys()); // comes from static data above. - - assert.sameDeepMembers(ldmlFormIds, kmcFormIds, "LDML and kmc form ids"); - - const scanToVkey = new Map(); - - source?.keyboard3?.forms?.form.forEach((form) => { - const {id, scanCodes} = form; - const km = HardwareToKeymap.get(id); - assert.ok(km, `kmc's ${id}`); - const ldmlRowCounts = scanCodes.map(o => o.codes.split(" ").length); - const kmcRowCounts = km.map(o => o.length); - assert.deepEqual(ldmlRowCounts, kmcRowCounts, `ldml/kmc counts for form ${id}`); - - // Now, at least check to see if we're being consistent. - const ldmlRows = scanCodes.map(o => o.codes.split(" ")); - for (let r=0;r comp.compare(a.scan, b.scan)); - fs.writeFileSync('build/test/ldml-keyboard/scancodes.json', JSON.stringify(outMap, null, ' '), 'utf-8'); - fs.writeFileSync('build/test/ldml-keyboard/scancodes.ts', - `export const scanToVkey = {\n` + - outMap.map(o => ` 0x${o.scan}: k.${o.vname},`).join('\n') + - `\n};\n`, - 'utf-8'); - - - }, - }, - ]); -}); diff --git a/developer/src/kmc-ldml/src/compiler/keys.ts b/developer/src/kmc-ldml/src/compiler/keys.ts index 652b584d0ff..56ce8012389 100644 --- a/developer/src/kmc-ldml/src/compiler/keys.ts +++ b/developer/src/kmc-ldml/src/compiler/keys.ts @@ -196,6 +196,25 @@ export class KeysCompiler extends SectionCompiler { } } + private getKeymapFromForm(hardware : string) : Constants.KeyMap { + return KeysCompiler.getKeymapFromForms(this.keyboard3?.forms.form, hardware); + } + + public static getKeymapFromForms(forms: LDMLKeyboard.LKForm[], hardware: string): Constants.KeyMap { + const ldmlForm = forms.find((f) => f.id === hardware); + if (!ldmlForm) { + return undefined; + } + return KeysCompiler.getKeymapFromScancodes(ldmlForm); + } + + public static getKeymapFromScancodes(ldmlForm: LDMLKeyboard.LKForm) { + const { scanCodes } = ldmlForm; + const ldmlScan = scanCodes.map(o => o.codes.split(" ").map(n => Number.parseInt(n, 16))); + const ldmlVkey = Constants.CLDRScanToKeyMap(ldmlScan); + return ldmlVkey; + } + /** * TODO-LDML: from old 'keys' * Validate for purpose of kmap @@ -217,10 +236,8 @@ export class KeysCompiler extends SectionCompiler { valid = false; } - const keymap = Constants.HardwareToKeymap.get(hardware); - /* c8 ignore next 5 */ + const keymap = this.getKeymapFromForm(hardware); if (!keymap) { - // not reached due to XML validation this.callbacks.reportMessage( CompilerMessages.Error_InvalidHardware({ form: hardware }) ); @@ -287,7 +304,7 @@ export class KeysCompiler extends SectionCompiler { hardware: string ): Keys { const mod = translateLayerAttrToModifier(layer); - const keymap = Constants.HardwareToKeymap.get(hardware); + const keymap = this.getKeymapFromForm(hardware); let y = -1; for (let row of layer.row) { diff --git a/developer/src/kmc-ldml/src/compiler/visual-keyboard-compiler.ts b/developer/src/kmc-ldml/src/compiler/visual-keyboard-compiler.ts index c45326ff984..1ad0a4ea1c5 100644 --- a/developer/src/kmc-ldml/src/compiler/visual-keyboard-compiler.ts +++ b/developer/src/kmc-ldml/src/compiler/visual-keyboard-compiler.ts @@ -1,4 +1,5 @@ -import { Constants, VisualKeyboard, LDMLKeyboard } from "@keymanapp/common-types"; +import { VisualKeyboard, LDMLKeyboard } from "@keymanapp/common-types"; +import { KeysCompiler } from "./keys.js"; export class LdmlKeyboardVisualKeyboardCompiler { public compile(source: LDMLKeyboard.LDMLKeyboardXMLSourceFile): VisualKeyboard.VisualKeyboard { @@ -14,8 +15,9 @@ export class LdmlKeyboardVisualKeyboardCompiler { result.header.unicodeFont = {...VisualKeyboard.DEFAULT_KVK_FONT}; for(let layers of source.keyboard3.layers) { + const hardware = layers.form; for(let layer of layers.layer) { - this.compileHardwareLayer(source, result, layer); + this.compileHardwareLayer(source, result, layer, hardware); } } return result; @@ -24,9 +26,16 @@ export class LdmlKeyboardVisualKeyboardCompiler { private compileHardwareLayer( source: LDMLKeyboard.LDMLKeyboardXMLSourceFile, vk: VisualKeyboard.VisualKeyboard, - layer: LDMLKeyboard.LKLayer + layer: LDMLKeyboard.LKLayer, + hardware: string, ) { - // TODO-LDML: consider consolidation with keys.ts? + if (hardware === 'touch') { + hardware = 'us'; // TODO-LDML: US Only. Do something different here? + } + const keymap = KeysCompiler.getKeymapFromForms(source.keyboard3?.forms?.form, hardware); + if (!keymap) { + throw Error(`Internal error: could not find keymap for form ${hardware}`); + } const shift = this.translateLayerIdToVisualKeyboardShift(layer.id); let y = -1; @@ -48,7 +57,7 @@ export class LdmlKeyboardVisualKeyboardCompiler { flags: VisualKeyboard.VisualKeyboardKeyFlags.kvkkUnicode, shift: shift, text: keydef.to, // TODO-LDML: displays - vkey: Constants.USVirtualKeyMap[y][x] // TODO-LDML: #7965 US-only + vkey: keymap[y][x], }); } }