diff --git a/cli.ts b/cli.ts index 9de84ee..23b991e 100644 --- a/cli.ts +++ b/cli.ts @@ -3,6 +3,7 @@ import fs from "fs" import path from "path" import { generateKeylayout } from "./generateKeylayout" import { generateKlc } from "./generateKlc" +import { generateXkb } from "./generateXkb" import { fixUnicode } from "./utils" // eslint-disable-next-line @typescript-eslint/no-var-requires @@ -47,6 +48,18 @@ const choices = filenames.map((filename) => ({ const outputFilename = `output/${layoutName}.klc` await generateKlc(jsonInput, outputFilename) + console.log(`Output : ${outputFilename}`) + } catch (e) { + console.error(e) + process.exit(1) + } + + // Xkb + try { + const layoutName = response.input.split(".")[0] + const outputFilename = `output/${layoutName}_xkb` + await generateXkb(jsonInput, outputFilename) + console.log(`Output : ${outputFilename}`) } catch (e) { console.error(e) diff --git a/generateXkb.ts b/generateXkb.ts new file mode 100644 index 0000000..3fa252d --- /dev/null +++ b/generateXkb.ts @@ -0,0 +1,121 @@ +import { plainToClass } from "class-transformer" +import { validate } from "class-validator" +import fs from "fs" +import { Layout, WindowsAttributes } from "./main" + +export async function generateXkb( + content: Record, + outputPath: string +): Promise { + const layout = plainToClass(Layout, content) + const errors = await validate(layout) + + if (errors.length) { + throw new Error(errors.map((e) => e.toString()).join(", ")) + } + + const windowsErrors = await validate( + plainToClass(WindowsAttributes, layout.os.windows) + ) + + if (windowsErrors.length) { + throw new Error(windowsErrors.map((e) => e.toString()).join(", ")) + } + + function toHex(str: string) { + var hex, i; + var result = ""; + for (i=0; i { [", + "2": "key { [", + "3": "key { [", + "4": "key { [", + "5": "key { [", + "6": "key { [", + "7": "key { [", + "8": "key { [", + "9": "key { [", + "0": "key { [", + "-": "key { [", + "=": "key { [", + "`": "key { [", + q: "key { [", + w: "key { [", + e: "key { [", + r: "key { [", + t: "key { [", + y: "key { [", + u: "key { [", + i: "key { [", + o: "key { [", + p: "key { [", + "[": "key { [", + "]": "key { [", + a: "key { [", + s: "key { [", + d: "key { [", + f: "key { [", + g: "key { [", + h: "key { [", + j: "key { [", + k: "key { [", + l: "key { [", + ";": "key { [", + "'": "key { [", + "\\": "key { [", + z: "key { [", + x: "key { [", + c: "key { [", + v: "key { [", + b: "key { [", + n: "key { [", + m: "key { [", + ",": "key { [", + ".": "key { [", + "/": "key { [", + } + + const lines = [ + `partial alphanumeric_keys`, + `xkb_symbols "${layout.os.windows.installerName}" {`, + `\n // COPYRIGHT "MIT"`, + `\n name[Group1]= "${layout.name} v${layout.version}";`, + ] + + const layoutLines = [""] + Object.entries(klfDefaultLayout).forEach(([key, value]) => + { + const extensions = layout.layers.map + ( + (_, idx) => + { + return (toHex(layout.keys[key][idx]) || "voidsymbol")+((idx<3)?",":"") + } + ) + + extensions.push("] };") + layoutLines.push([value,...extensions].join(" ")) + }) + + fs.writeFileSync( + outputPath, + "\ufeff" + + [ + lines.join("\n"), + layoutLines.join("\n "), + " include \"level3(ralt_switch)\"\n};", + ].join("\n\n"), + { + encoding: "utf8", + } + ) +}