mirror of
https://github.com/keymanapp/keyman.git
synced 2026-08-12 03:45:34 +00:00
feat(developer): solve merge conflicts
This commit is contained in:
parent
12b17e45ee
commit
ff4e7c98f3
5 changed files with 84 additions and 136 deletions
|
|
@ -6,7 +6,7 @@
|
|||
import { CompilerErrorNamespace, CompilerErrorSeverity, CompilerMessageSpec as m, CompilerMessageDef as def } from '@keymanapp/developer-utils';
|
||||
|
||||
const Namespace = CompilerErrorNamespace.Converter;
|
||||
const SevInfo = CompilerErrorSeverity.Info | Namespace;
|
||||
const SevInfo = CompilerErrorSeverity.Info | Namespace;
|
||||
// const SevHint = CompilerErrorSeverity.Hint | Namespace;
|
||||
// const SevWarn = CompilerErrorSeverity.Warn | Namespace;
|
||||
const SevError = CompilerErrorSeverity.Error | Namespace;
|
||||
|
|
@ -53,8 +53,11 @@ export class ConverterMessages {
|
|||
);
|
||||
|
||||
static INFO_UnsupportedCharactersDetected = SevInfo | 0x0007;
|
||||
static Info_UnsupportedCharactersDetected = (o: { inputFilename: string, keymap_index: string, key: string,KeyName:string, output: string; }) => m(
|
||||
this.INFO_UnsupportedCharactersDetected, `INFO: Input file ${def(o.inputFilename)} contains unsupported character '${def(o.output)}' at keyMap index ${def(o.keymap_index)} on Keycode ${def(o.key)} (${def(o.KeyName)})`
|
||||
static Info_UnsupportedCharactersDetected = (o: { inputFilename: string, keymap_index: string, key: string, KeyName: string, output: string; }) => m(
|
||||
this.INFO_UnsupportedCharactersDetected, `INFO: Input file ${def(o.inputFilename)}
|
||||
contains unsupported character '${def(o.output)}
|
||||
' at keyMap index ${def(o.keymap_index)}
|
||||
on Keycode ${def(o.key)} (${def(o.KeyName)})`
|
||||
);
|
||||
|
||||
static ERROR_InvalidFile = SevError | 0x0008;
|
||||
|
|
|
|||
|
|
@ -81,9 +81,9 @@ export class Converter implements KeymanCompiler {
|
|||
}
|
||||
|
||||
const converter = new ConverterClass(this.callbacks, converterOptions);
|
||||
const artifacts = await converter.run(inputFilename, outputFilename);
|
||||
const result = await converter.run(inputFilename, outputFilename);
|
||||
// Note: any subsequent errors in conversion will have been reported by the converter
|
||||
return artifacts ? { artifacts } : null;
|
||||
return result ? result : null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -7,19 +7,34 @@
|
|||
*
|
||||
*/
|
||||
|
||||
import { CompilerCallbacks, CompilerOptions } from "@keymanapp/developer-utils";
|
||||
import { ConverterToKmnArtifacts } from "../converter-artifacts.js";
|
||||
import { CompilerCallbacks, CompilerOptions, KeymanCompilerResult, } from "@keymanapp/developer-utils";
|
||||
import { KmnFileWriter } from './kmn-file-writer.js';
|
||||
import { KeylayoutFileReader } from './keylayout-file-reader.js';
|
||||
import { ConverterMessages } from '../converter-messages.js';
|
||||
import { KeylayoutXMLSourceFile } from '@keymanapp/developer-utils';
|
||||
import { ConverterArtifacts } from "../converter-artifacts.js";
|
||||
import { ConverterToKmnArtifacts } from "../converter-artifacts.js";
|
||||
import { KeylayoutXMLSourceFile } from '../../../common/web/utils/src/types/keylayout/keylayout-xml.js';
|
||||
|
||||
|
||||
export interface ConverterResult extends KeymanCompilerResult {
|
||||
/**
|
||||
* Internal in-memory build artifacts from a successful compilation. Caller
|
||||
* can write these to disk with {@link Converter.write}
|
||||
*/
|
||||
artifacts: ConverterArtifacts;
|
||||
};
|
||||
|
||||
export interface ConverterToKmnResult extends ConverterResult {
|
||||
/**
|
||||
* Internal in-memory build artifacts from a successful compilation. Caller
|
||||
* can write these to disk with {@link Converter.write}
|
||||
*/
|
||||
artifacts: ConverterToKmnArtifacts;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Object holding all important data for the conversion between
|
||||
* input (*.keylayout) format and output (*.kmn) format.
|
||||
* It contains input and output filenames, an array of all used modifiers
|
||||
* and all preprocessed key rules for up to 3 key/modifier combinations.
|
||||
*/
|
||||
export interface ProcesData {
|
||||
keylayout_filename: string,
|
||||
kmn_filename: string,
|
||||
|
|
@ -51,12 +66,12 @@ export interface ActionStateOutput {
|
|||
*/
|
||||
export function find_usedKeysCount(data: any, pos: number): number {
|
||||
|
||||
let usedKeyCount = KeylayoutToKmnConverter.MAX_KEY_COUNT;
|
||||
if (data.keyboard.keyMapSet[0].keyMap[pos].key.length < usedKeyCount ) {
|
||||
// set the max to n-1 (keys are zero indexed )
|
||||
usedKeyCount = data.keyboard.keyMapSet[0].keyMap[pos].key.length - 1;
|
||||
let usedKeyCount = KeylayoutToKmnConverter.MAX_KEY_COUNT;
|
||||
if (data.keyboard.keyMapSet[0].keyMap[pos].key.length < usedKeyCount) {
|
||||
// set max to n-1 (keys are zero indexed )
|
||||
usedKeyCount = data.keyboard.keyMapSet[0].keyMap[pos].key.length - 1;
|
||||
}
|
||||
return usedKeyCount ;
|
||||
return usedKeyCount;
|
||||
}
|
||||
|
||||
export class KeylayoutToKmnConverter {
|
||||
|
|
@ -83,8 +98,7 @@ export class KeylayoutToKmnConverter {
|
|||
* @param outputFilename the resulting keyman .kmn-file
|
||||
* @return null on success
|
||||
*/
|
||||
async run(inputFilename: string, outputFilename?: string): Promise<ConverterToKmnArtifacts> {
|
||||
|
||||
async run(inputFilename: string, outputFilename?: string): Promise<ConverterToKmnResult> {
|
||||
|
||||
if (!inputFilename) {
|
||||
this.callbacks.reportMessage(ConverterMessages.Error_FileNotFound({ inputFilename }));
|
||||
|
|
@ -123,16 +137,21 @@ export class KeylayoutToKmnConverter {
|
|||
|
||||
const kmnFileWriter = new KmnFileWriter(this.callbacks, this.options);
|
||||
|
||||
const out_text_ok: boolean = kmnFileWriter.write(outArray);
|
||||
if (!out_text_ok) {
|
||||
// write to object/ConverterToKmnResult
|
||||
const out_Uint8: Uint8Array = kmnFileWriter.write(outArray);
|
||||
const Result_toBeReturned: ConverterToKmnResult = {
|
||||
artifacts: {
|
||||
kmn: { data: out_Uint8, filename: outputFilename }
|
||||
}
|
||||
};
|
||||
|
||||
if (!out_Uint8) {
|
||||
this.callbacks.reportMessage(ConverterMessages.Error_UnableToWrite({ outputFilename }));
|
||||
return null;
|
||||
}
|
||||
|
||||
return null;
|
||||
return Result_toBeReturned;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief member function to read filename and behaviour of a json object into a ProcesData
|
||||
* @param jsonObj containing filename, behaviour and rules of a json object
|
||||
|
|
@ -148,10 +167,8 @@ export class KeylayoutToKmnConverter {
|
|||
arrayOf_Modifiers: [],
|
||||
arrayOf_Rules: []
|
||||
};
|
||||
//_S2 do I need to "validate again here?"
|
||||
if ((jsonObj !== null) && (jsonObj.hasOwnProperty("keyboard"))) {
|
||||
//if ((jsonObj !== null) ) {
|
||||
|
||||
if ((jsonObj !== null) && (jsonObj.hasOwnProperty("keyboard"))) {
|
||||
data_object.keylayout_filename = outputfilename.replace(/\.kmn$/, '.keylayout');
|
||||
data_object.kmn_filename = outputfilename;
|
||||
data_object.arrayOf_Modifiers = modifierBehavior; // ukelele uses behaviours e.g. 18 modifiersCombinations in 8 KeyMapSelect(behaviors)
|
||||
|
|
|
|||
|
|
@ -23,12 +23,12 @@ export class KmnFileWriter {
|
|||
* @param outputfilename the file that will be written; if no outputfilename is given an outputfilename will be created from data_ukelele.keylayout_filename
|
||||
* @return true if data has been written; false if not
|
||||
*/
|
||||
public write(data_ukelele: ProcesData): boolean {
|
||||
public writeToFile(data_ukelele: ProcesData): boolean {
|
||||
|
||||
let data: string = "\n";
|
||||
|
||||
// add top part of kmn file: STORES
|
||||
data += this.writeData_Stores(data_ukelele);
|
||||
data += this.write_KmnFileHeader(data_ukelele);
|
||||
|
||||
// add bottom part of kmn file: RULES
|
||||
data += this.writeData_Rules(data_ukelele);
|
||||
|
|
@ -37,33 +37,21 @@ export class KmnFileWriter {
|
|||
this.callbacks.fs.writeFileSync(data_ukelele.kmn_filename, new TextEncoder().encode(data));
|
||||
return true;
|
||||
} catch (err) {
|
||||
this.callbacks.reportMessage(ConverterMessages.Error_OutputFilenameIsRequired());
|
||||
this.callbacks.reportMessage(ConverterMessages.Error_UnableToWrite({outputFilename: data_ukelele.kmn_filename}));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public writeToString(data_ukelele: ProcesData): string {
|
||||
/**
|
||||
* @brief member function to write data from object to a Uint8Array
|
||||
* @param data_ukelele the array holding all keyboard data
|
||||
* @return a Uint8Array holding data
|
||||
*/
|
||||
public write(data_ukelele: ProcesData): Uint8Array {
|
||||
let data: string = "\n";
|
||||
|
||||
// add top part of kmn file: STORES
|
||||
data += this.writeData_Stores(data_ukelele);
|
||||
|
||||
// add bottom part of kmn file: RULES
|
||||
data += this.writeData_Rules(data_ukelele);
|
||||
|
||||
try {
|
||||
return data;
|
||||
} catch (err) {
|
||||
this.callbacks.reportMessage(ConverterMessages.Error_OutputFilenameIsRequired());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public writeToUint8Array(data_ukelele: ProcesData): Uint8Array {
|
||||
let data: string = "\n";
|
||||
|
||||
// add top part of kmn file: STORES
|
||||
data += this.writeData_Stores(data_ukelele);
|
||||
data += this.write_KmnFileHeader(data_ukelele);
|
||||
|
||||
// add bottom part of kmn file: RULES
|
||||
data += this.writeData_Rules(data_ukelele);
|
||||
|
|
@ -71,17 +59,17 @@ export class KmnFileWriter {
|
|||
try {
|
||||
return new TextEncoder().encode(data);
|
||||
} catch (err) {
|
||||
this.callbacks.reportMessage(ConverterMessages.Error_OutputFilenameIsRequired());
|
||||
this.callbacks.reportMessage(ConverterMessages.Error_UnableToWrite({outputFilename: data_ukelele.kmn_filename}));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief member function to create data for stores that will be printed to the resulting kmn file
|
||||
* @brief member function to create data for the header (stores) that will be printed to the resulting kmn file
|
||||
* @param data_ukelele an object containing all data read from a .keylayout file
|
||||
* @return string - all stores to be printed
|
||||
*/
|
||||
public writeData_Stores(data_ukelele: ProcesData): string {
|
||||
public write_KmnFileHeader(data_ukelele: ProcesData): string {
|
||||
|
||||
let data: string = "";
|
||||
|
||||
|
|
@ -114,6 +102,9 @@ export class KmnFileWriter {
|
|||
let data: string = "";
|
||||
|
||||
// filter array of all rules and remove duplicates
|
||||
// during the process of creating Rule[], duplicate rules might occur
|
||||
// (e.g. when in a keylayout file the same modifiers occur in several behaviors thus producing the same rules).
|
||||
// This is to filter out those duplicate Rule objects
|
||||
const unique_data_Rules: Rule[] = data_ukelele.arrayOf_Rules.filter((curr) => {
|
||||
return (!(curr.output === new TextEncoder().encode("") || curr.output === undefined)
|
||||
&& (curr.key !== "")
|
||||
|
|
@ -416,7 +407,8 @@ export class KmnFileWriter {
|
|||
|
||||
/**
|
||||
* @brief member function to review rules for acceptable modifiers, duplicate or ambiguous rules and return an array containing possible warnings.
|
||||
* Definition of comparisons e.g. 1-1, 2-4, 6-6
|
||||
* Keyman can not handle duplicate rules so we need to make sure a rule is written only once by either omitting a duplicate rule or commenting out an ambiguous rule.
|
||||
* Omitting rules and definition of comparisons e.g. 1-1, 2-4, 6-6
|
||||
* see https://docs.google.com/document/d/12J3NGO6RxIthCpZDTR8FYSRjiMgXJDLwPY2z9xqKzJ0/edit?tab=t.0#heading=h.pcz8rjyrl5ug
|
||||
* @param rule : Rule[] - an array of all rules
|
||||
* @param index the index of a rule in array[rule]
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ describe('KmnFileWriter', function () {
|
|||
compilerTestCallbacks.clear();
|
||||
});
|
||||
|
||||
|
||||
describe("write() ", function () {
|
||||
const inputFilename = makePathToFixture('../data/Test.keylayout');
|
||||
const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions);
|
||||
|
|
@ -30,77 +31,12 @@ describe('KmnFileWriter', function () {
|
|||
const read = sut_r.read(inputFilename);
|
||||
const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn'));
|
||||
|
||||
// empty ProcesData from unavailable file name
|
||||
const inputFilename_unavailable = makePathToFixture('../data/X.keylayout');
|
||||
const read_unavailable = sut_r.read(inputFilename_unavailable);
|
||||
const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn'));
|
||||
|
||||
it('write() should return true (no error) if written', async function () {
|
||||
const result = sut_w.write(converted);
|
||||
assert.isTrue(result);
|
||||
});
|
||||
|
||||
it('write() should return false if no inputfile', async function () {
|
||||
const result = sut_w.write(converted_unavailable);
|
||||
assert.isFalse(result);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe("writeToString() ", function () {
|
||||
const inputFilename = makePathToFixture('../data/Test.keylayout');
|
||||
const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions);
|
||||
const sut_r = new KeylayoutFileReader(compilerTestCallbacks);
|
||||
const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions);
|
||||
const read = sut_r.read(inputFilename);
|
||||
const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn'));
|
||||
|
||||
const out_expected_first: string = "c ..................................................................................................................\n"
|
||||
+ "c ..................................................................................................................\n"
|
||||
+ "c Keyman keyboard generated by kmn-convert version: " + KEYMAN_VERSION.VERSION + "\n"
|
||||
+ "c from Ukelele file: ";
|
||||
|
||||
const out_expected_last: string = "\n"
|
||||
+ "c ..................................................................................................................\n"
|
||||
+ "c ..................................................................................................................\n"
|
||||
+ "\n"
|
||||
+ "store(&TARGETS) 'desktop'\n"
|
||||
+ "\n"
|
||||
+ "begin Unicode > use(main)\n\n"
|
||||
+ "group(main) using keys\n\n"
|
||||
+ "\n";
|
||||
|
||||
// empty ProcesData from unavailable file name
|
||||
const inputFilename_unavailable = makePathToFixture('../data/X.keylayout');
|
||||
const read_unavailable = sut_r.read(inputFilename_unavailable);
|
||||
const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn'));
|
||||
|
||||
it('writeToString() should return result', async function () {
|
||||
const result = sut_w.writeToString(converted);
|
||||
assert.isNotNull(result);
|
||||
});
|
||||
|
||||
it('writeToString() should return header in case of missing inputfile', async function () {
|
||||
const result = sut_w.writeToString(converted_unavailable);
|
||||
assert.equal(result, ("\n" + out_expected_first + out_expected_last));
|
||||
});
|
||||
});
|
||||
|
||||
describe("writeToUint8Array() ", function () {
|
||||
const inputFilename = makePathToFixture('../data/Test.keylayout');
|
||||
const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions);
|
||||
const sut_r = new KeylayoutFileReader(compilerTestCallbacks);
|
||||
const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions);
|
||||
const read = sut_r.read(inputFilename);
|
||||
const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn'));
|
||||
|
||||
const out_expected_first: string =
|
||||
const out_expected: string =
|
||||
"c ..................................................................................................................\n"
|
||||
+ "c ..................................................................................................................\n"
|
||||
+ "c Keyman keyboard generated by kmn-convert version: " + KEYMAN_VERSION.VERSION + "\n"
|
||||
+ "c from Ukelele file: ";
|
||||
|
||||
const out_expected_last: string = "\n"
|
||||
+ "c from Ukelele file: "
|
||||
+ "\n"
|
||||
+ "c ..................................................................................................................\n"
|
||||
+ "c ..................................................................................................................\n"
|
||||
+ "\n"
|
||||
|
|
@ -115,13 +51,13 @@ describe('KmnFileWriter', function () {
|
|||
const inputFilename_unavailable = makePathToFixture('../data/X.keylayout');
|
||||
const read_unavailable = sut_r.read(inputFilename_unavailable);
|
||||
const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn'));
|
||||
it('writeToUint8Array() should return header in case of missing inputfile', async function () {
|
||||
const result = sut_w.writeToUint8Array(converted_unavailable);
|
||||
assert.equal(new TextDecoder().decode(result), ("\n" + out_expected_first + out_expected_last));
|
||||
it('write() should return header in case of missing inputfile', async function () {
|
||||
const result = sut_w.write(converted_unavailable);
|
||||
assert.equal(new TextDecoder().decode(result), ("\n" + out_expected));
|
||||
});
|
||||
|
||||
it('writeToUint8Array() should return result', async function () {
|
||||
const result = sut_w.writeToUint8Array(converted);
|
||||
it('write() should return result', async function () {
|
||||
const result = sut_w.write(converted);
|
||||
assert.isNotNull(result);
|
||||
});
|
||||
});
|
||||
|
|
@ -151,7 +87,7 @@ describe('KmnFileWriter', function () {
|
|||
|
||||
});
|
||||
|
||||
describe("writeData_Stores() ", function () {
|
||||
describe("write_KmnFileHeader() ", function () {
|
||||
const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions);
|
||||
const sut_r = new KeylayoutFileReader(compilerTestCallbacks);
|
||||
const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions);
|
||||
|
|
@ -186,18 +122,18 @@ describe('KmnFileWriter', function () {
|
|||
+ "group(main) using keys\n\n"
|
||||
+ "\n";
|
||||
|
||||
it(('writeData_Stores should return store text with filename ').padEnd(62, " ") + 'on correct input', async function () {
|
||||
const written_correctName = sut_w.writeData_Stores(converted);
|
||||
it(('write_KmnFileHeader should return store text with filename ').padEnd(62, " ") + 'on correct input', async function () {
|
||||
const written_correctName = sut_w.write_KmnFileHeader(converted);
|
||||
assert.equal(written_correctName, (out_expected_first + converted.keylayout_filename + out_expected_last));
|
||||
});
|
||||
|
||||
it(('writeData_Stores should return store text without filename ').padEnd(62, " ") + 'on empty input', async function () {
|
||||
const written_emptyName = sut_w.writeData_Stores(converted_empty);
|
||||
it(('write_KmnFileHeader should return store text without filename ').padEnd(62, " ") + 'on empty input', async function () {
|
||||
const written_emptyName = sut_w.write_KmnFileHeader(converted_empty);
|
||||
assert.equal(written_emptyName, (out_expected_first + out_expected_last));
|
||||
});
|
||||
|
||||
it(('writeData_Stores should return store text without filename ').padEnd(62, " ") + 'on only filename as input', async function () {
|
||||
const written_onlyName = sut_w.writeData_Stores(converted_unavailable);
|
||||
it(('write_KmnFileHeader should return store text without filename ').padEnd(62, " ") + 'on only filename as input', async function () {
|
||||
const written_onlyName = sut_w.write_KmnFileHeader(converted_unavailable);
|
||||
assert.equal(written_onlyName, (out_expected_first + converted_unavailable.keylayout_filename + out_expected_last));
|
||||
});
|
||||
});
|
||||
|
|
@ -502,7 +438,7 @@ describe('KmnFileWriter', function () {
|
|||
});
|
||||
});
|
||||
|
||||
describe('write form intermediate data array', function () {
|
||||
describe('write from intermediate data array', function () {
|
||||
const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions);
|
||||
[
|
||||
[
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue