mirror of
https://github.com/keymanapp/keyman.git
synced 2026-10-18 03:47:44 +00:00
Merge pull request #14016 from keymanapp/feat/developer/13941-keys-update-messages
feat(developer): revamp line numbers per design doc
This commit is contained in:
commit
7fb927609b
4 changed files with 59 additions and 54 deletions
|
|
@ -73,7 +73,7 @@ export class KeysCompiler extends SectionCompiler {
|
|||
this.keyboard3.forms?.form?.forEach((form) => {
|
||||
if (!LDMLKeyboard.ImportStatus.isImpliedImport(form)) {
|
||||
// If it's not an implied import, give a warning.
|
||||
this.callbacks.reportMessage(LdmlCompilerMessages.Warn_CustomForm(form));
|
||||
this.callbacks.reportMessage(LdmlCompilerMessages.Warn_CustomForm({ id: form.id }, form));
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -100,7 +100,7 @@ export class KeysCompiler extends SectionCompiler {
|
|||
if (!flickHash.has(flickId)) {
|
||||
valid = false;
|
||||
this.callbacks.reportMessage(
|
||||
LdmlCompilerMessages.Error_MissingFlicks(key)
|
||||
LdmlCompilerMessages.Error_MissingFlicks({ id: key.id, flickId: key.flickId }, key)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -157,16 +157,16 @@ export class KeysCompiler extends SectionCompiler {
|
|||
const form = this.getForm(formId);
|
||||
if (!form) {
|
||||
this.callbacks.reportMessage(
|
||||
LdmlCompilerMessages.Error_InvalidHardware(layers)
|
||||
LdmlCompilerMessages.Error_InvalidHardware({formId}, layers)
|
||||
);
|
||||
return null;
|
||||
}
|
||||
const keymap = KeysCompiler.getKeymapFromScancodes(form, badScans);
|
||||
if (!keymap) {
|
||||
} else if (badScans.size !== 0) {
|
||||
const codes = Array.from(badScans.values()).map(n => Number(n).toString(16)).sort();
|
||||
const codes = Array.from(badScans.values()).map(n => Number(n).toString(16)).sort().join(' ');
|
||||
this.callbacks.reportMessage(
|
||||
LdmlCompilerMessages.Error_InvalidScanCode({ codes }, form)
|
||||
LdmlCompilerMessages.Error_InvalidScanCode({ codes, id: form.id }, form)
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
|
@ -461,7 +461,7 @@ export class KeysCompiler extends SectionCompiler {
|
|||
const { modifiers } = layer;
|
||||
if (!validModifier(modifiers)) {
|
||||
this.callbacks.reportMessage(
|
||||
LdmlCompilerMessages.Error_InvalidModifier(layer)
|
||||
LdmlCompilerMessages.Error_InvalidModifier({ modifiers, id: layer.id }, layer)
|
||||
);
|
||||
valid = false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ export class LayrCompiler extends SectionCompiler {
|
|||
const { modifiers } = layer;
|
||||
totalLayerCount++;
|
||||
if (!validModifier(modifiers)) {
|
||||
this.callbacks.reportMessage(LdmlCompilerMessages.Error_InvalidModifier(layer));
|
||||
this.callbacks.reportMessage(LdmlCompilerMessages.Error_InvalidModifier({ modifiers, id: layer.id }, layer));
|
||||
valid = false;
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import { KMXPlus, util } from "@keymanapp/common-types";
|
||||
import { util } from "@keymanapp/common-types";
|
||||
import { CompilerErrorNamespace, CompilerErrorSeverity, CompilerMessageSpec as m, CompilerMessageDef as def, XML_FILENAME_SYMBOL, CompilerEvent, KeymanXMLReader } from '@keymanapp/developer-utils';
|
||||
import { LDMLKeyboard } from '@keymanapp/developer-utils';
|
||||
// const SevInfo = CompilerErrorSeverity.Info | CompilerErrorNamespace.LdmlKeyboardCompiler;
|
||||
const SevHint = CompilerErrorSeverity.Hint | CompilerErrorNamespace.LdmlKeyboardCompiler;
|
||||
const SevWarn = CompilerErrorSeverity.Warn | CompilerErrorNamespace.LdmlKeyboardCompiler;
|
||||
|
|
@ -19,18 +18,36 @@ const SevErrorTransform = SevError | 0xF00;
|
|||
type ObjectWithMetadata = any;
|
||||
|
||||
/**
|
||||
* Convenience function for constructing CompilerEvents with line numbers
|
||||
* Convenience function for constructing CompilerEvents with line numbers.
|
||||
* Use it as below: (abbreviated as mx())
|
||||
*
|
||||
* ```js
|
||||
* // Note: Indentation makes "InvalidScanCode" line up thrice
|
||||
* static ERROR_InvalidScanCode = SevError | 0x0009;
|
||||
* // Note:
|
||||
* // 1. All parameters are passed in 'o', the context object is only used for context even if
|
||||
* // it contains redundant info.
|
||||
* // 2. No code execution within the arrow function other than the 'mx' call, string interpolation,
|
||||
* // with `${def(o.property)}` as the max complexity of interpolation.
|
||||
* static Error_InvalidScanCode = (o:{id: string, invalidCodeList: string}, x: ObjectWithMetadata) => mx(
|
||||
* this.ERROR_InvalidScanCode, x,
|
||||
* `Form '${def(o.id)}' has invalid/unknown scancodes '${def(o.codes)}'`,
|
||||
* // Note: If detail is omitted, leave the trailing comma on the prior line to leave room for it
|
||||
* `…additional markdown detail…`
|
||||
* );
|
||||
* ```
|
||||
*
|
||||
* @param code Unique numeric value of the event
|
||||
* @param message A short description of the error presented to the user
|
||||
* @param x Object to be used as a source for line number information
|
||||
* @param context Object to be used as a source for line number information
|
||||
* @param detail Detailed Markdown-formatted description of the error
|
||||
* including references to documentation, remediation options.
|
||||
* @see CompilerMessageSpec
|
||||
* @returns
|
||||
*/
|
||||
function CompilerMessageObjectSpec(code: number, message: string, x: ObjectWithMetadata, detail?: string): CompilerEvent {
|
||||
let evt = m(code, message, detail); // raw message
|
||||
evt = LdmlCompilerMessages.offset(evt, x); // with offset
|
||||
function CompilerMessageObjectSpec(code: number, context: ObjectWithMetadata, message: string, detail?: string): CompilerEvent {
|
||||
let evt = m(code, message, detail); // constructs raw message
|
||||
evt = LdmlCompilerMessages.offset(evt, context); // updates with offset from context
|
||||
return evt;
|
||||
};
|
||||
|
||||
|
|
@ -41,34 +58,30 @@ const mx = CompilerMessageObjectSpec;
|
|||
*/
|
||||
export class LdmlCompilerMessages {
|
||||
static HINT_NormalizationDisabled = SevHint | 0x0001;
|
||||
static Hint_NormalizationDisabled = (x?: LDMLKeyboard.LKSettings) => mx(
|
||||
this.HINT_NormalizationDisabled,
|
||||
static Hint_NormalizationDisabled = (x?: ObjectWithMetadata) => mx(
|
||||
this.HINT_NormalizationDisabled, x,
|
||||
`normalization=disabled is not recommended.`,
|
||||
x,
|
||||
);
|
||||
|
||||
static ERROR_InvalidLocale = SevError | 0x0002;
|
||||
static Error_InvalidLocale = (o:{tag: string}) => m(this.ERROR_InvalidLocale, `Invalid BCP 47 locale form '${def(o.tag)}'`);
|
||||
|
||||
static ERROR_HardwareLayerHasTooManyRows = SevError | 0x0003;
|
||||
static Error_HardwareLayerHasTooManyRows = (x: any) => mx(
|
||||
this.ERROR_HardwareLayerHasTooManyRows,
|
||||
static Error_HardwareLayerHasTooManyRows = (x?: ObjectWithMetadata) => mx(
|
||||
this.ERROR_HardwareLayerHasTooManyRows, x,
|
||||
`'hardware' layer has too many rows`,
|
||||
x,
|
||||
);
|
||||
|
||||
static ERROR_RowOnHardwareLayerHasTooManyKeys = SevError | 0x0004;
|
||||
static Error_RowOnHardwareLayerHasTooManyKeys = (o: { row: number, hardware: string, modifiers: string }, x: LDMLKeyboard.LKRow) => mx(
|
||||
this.ERROR_RowOnHardwareLayerHasTooManyKeys,
|
||||
static Error_RowOnHardwareLayerHasTooManyKeys = (o: { row: number, hardware: string, modifiers: string }, x?: ObjectWithMetadata) => mx(
|
||||
this.ERROR_RowOnHardwareLayerHasTooManyKeys, x,
|
||||
`Row #${def(o.row)} on 'hardware' ${def(o.hardware)} layer for modifier ${o.modifiers || 'none'} has too many keys`,
|
||||
x,
|
||||
);
|
||||
|
||||
static ERROR_KeyNotFoundInKeyBag = SevError | 0x0005;
|
||||
static Error_KeyNotFoundInKeyBag = (o: { keyId: string, col: number, row: number, layer: string, form: string }, x: LDMLKeyboard.LKRow | KMXPlus.LayrRow) => mx(
|
||||
this.ERROR_KeyNotFoundInKeyBag,
|
||||
static Error_KeyNotFoundInKeyBag = (o: { keyId: string, col: number, row: number, layer: string, form: string }, x?: ObjectWithMetadata) => mx(
|
||||
this.ERROR_KeyNotFoundInKeyBag, x,
|
||||
`Key '${def(o.keyId)}' in position #${def(o.col)} on row #${def(o.row)} of layer ${def(o.layer)}, form '${def(o.form)}' not found in key bag`,
|
||||
x,
|
||||
);
|
||||
|
||||
static HINT_OneOrMoreRepeatedLocales = SevHint | 0x0006;
|
||||
|
|
@ -84,25 +97,22 @@ export class LdmlCompilerMessages {
|
|||
m(this.HINT_LocaleIsNotMinimalAndClean, `Locale '${def(o.sourceLocale)}' is not minimal or correctly formatted and should be '${def(o.locale)}'`);
|
||||
|
||||
static ERROR_InvalidScanCode = SevError | 0x0009;
|
||||
static Error_InvalidScanCode = (o:{codes?: string[]}, x: LDMLKeyboard.LKForm) => mx(
|
||||
this.ERROR_InvalidScanCode,
|
||||
`Form '${def(x?.id)}' has invalid/unknown scancodes '${def(o.codes?.join(' '))}'`,
|
||||
x,
|
||||
static Error_InvalidScanCode = (o: { codes: string, id: string }, x?: ObjectWithMetadata) => mx(
|
||||
this.ERROR_InvalidScanCode, x,
|
||||
`Form '${def(o.id)}' has invalid/unknown scancodes '${def(o.codes)}'`,
|
||||
);
|
||||
|
||||
static WARN_CustomForm = SevWarn | 0x000A;
|
||||
static Warn_CustomForm = (o: LDMLKeyboard.LKForm) => mx(
|
||||
this.WARN_CustomForm,
|
||||
static Warn_CustomForm = (o: { id: string }, x?: ObjectWithMetadata) => mx(
|
||||
this.WARN_CustomForm, x,
|
||||
`Custom <form id="${def(o.id)}"> element. Key layout may not be as expected.`,
|
||||
o,
|
||||
);
|
||||
|
||||
static ERROR_GestureKeyNotFoundInKeyBag = SevError | 0x000B;
|
||||
static Error_GestureKeyNotFoundInKeyBag = (o:{keyId: string, parentKeyId: string, attribute: string}, x: LDMLKeyboard.LKKey) =>
|
||||
static Error_GestureKeyNotFoundInKeyBag = (o:{keyId: string, parentKeyId: string, attribute: string}, x?: ObjectWithMetadata) =>
|
||||
mx(
|
||||
this.ERROR_GestureKeyNotFoundInKeyBag,
|
||||
this.ERROR_GestureKeyNotFoundInKeyBag, x,
|
||||
`Key '${def(o.keyId)}' not found in key bag, referenced from other '${def(o.parentKeyId)}' in ${def(o.attribute)}`,
|
||||
x,
|
||||
);
|
||||
|
||||
static HINT_NoDisplayForMarker = SevHint | 0x000C;
|
||||
|
|
@ -110,10 +120,9 @@ export class LdmlCompilerMessages {
|
|||
m(this.HINT_NoDisplayForMarker, `Key element with id "${def(o.id)}" has only marker output, but there is no matching display element by output or keyId. Keycap may be blank.`);
|
||||
|
||||
static ERROR_InvalidVersion = SevError | 0x000D;
|
||||
static Error_InvalidVersion = (o: { version: string; }, x?: LDMLKeyboard.LKKeyboard) => mx(
|
||||
this.ERROR_InvalidVersion,
|
||||
static Error_InvalidVersion = (o: { version: string; }, x?: ObjectWithMetadata) => mx(
|
||||
this.ERROR_InvalidVersion, x,
|
||||
`Version number '${def(o.version)}' must be a semantic version format string with 'major.minor.patch' components.`,
|
||||
x,
|
||||
`The version number in the LDML keyboard file must be a [semantic
|
||||
version](https://semver.org) (semver) string. This string has a format of three
|
||||
integers representing major, minor, and patch versions, separated by periods. In
|
||||
|
|
@ -150,10 +159,9 @@ export class LdmlCompilerMessages {
|
|||
m(this.ERROR_DisplayIsRepeated, `display ${LdmlCompilerMessages.outputOrKeyId(o)} has more than one display entry.`);
|
||||
|
||||
static ERROR_KeyMissingToGapOrSwitch = SevError | 0x0011;
|
||||
static Error_KeyMissingToGapOrSwitch = (o:{keyId: string}, x: ObjectWithMetadata) => mx(
|
||||
this.ERROR_KeyMissingToGapOrSwitch,
|
||||
static Error_KeyMissingToGapOrSwitch = (o:{keyId: string}, x?: ObjectWithMetadata) => mx(
|
||||
this.ERROR_KeyMissingToGapOrSwitch, x,
|
||||
`key id='${def(o.keyId)}' must have either output=, gap=, or layerId=.`,
|
||||
x,
|
||||
);
|
||||
|
||||
static ERROR_ExcessHardware = SevError | 0x0012;
|
||||
|
|
@ -161,10 +169,9 @@ export class LdmlCompilerMessages {
|
|||
`layers formId=${def(o.formId)}: Can only have one non-'touch' element`);
|
||||
|
||||
static ERROR_InvalidHardware = SevError | 0x0013;
|
||||
static Error_InvalidHardware = (o:LDMLKeyboard.LKLayers) => mx(
|
||||
this.ERROR_InvalidHardware,
|
||||
static Error_InvalidHardware = (o: { formId: string }, x?: ObjectWithMetadata) => mx(
|
||||
this.ERROR_InvalidHardware, x,
|
||||
`layers has invalid value formId=${def(o.formId)}`,
|
||||
o,
|
||||
);
|
||||
|
||||
private static layerIdOrEmpty(layer : string) {
|
||||
|
|
@ -176,17 +183,15 @@ export class LdmlCompilerMessages {
|
|||
}
|
||||
|
||||
static ERROR_InvalidModifier = SevError | 0x0014;
|
||||
static Error_InvalidModifier = (o:LDMLKeyboard.LKLayer) => mx(
|
||||
this.ERROR_InvalidModifier,
|
||||
static Error_InvalidModifier = (o:{modifiers: string, id: string}, x?: ObjectWithMetadata) => mx(
|
||||
this.ERROR_InvalidModifier, x,
|
||||
`layer has invalid modifiers='${def(o.modifiers)}'` + LdmlCompilerMessages.layerIdOrEmpty(o.id),
|
||||
o,
|
||||
);
|
||||
|
||||
static ERROR_MissingFlicks = SevError | 0x0015;
|
||||
static Error_MissingFlicks = (o: LDMLKeyboard.LKKey) => mx(
|
||||
this.ERROR_MissingFlicks,
|
||||
static Error_MissingFlicks = (o: {id: string, flickId: string}, x?: ObjectWithMetadata) => mx(
|
||||
this.ERROR_MissingFlicks, x,
|
||||
`key id=${def(o.id)} refers to missing flickId=${def(o.flickId)}`,
|
||||
o,
|
||||
);
|
||||
|
||||
static ERROR_DuplicateVariable = SevError | 0x0016;
|
||||
|
|
|
|||
|
|
@ -335,7 +335,7 @@ describe('keys.kmap', function () {
|
|||
// not require maintaining the offset here, which will break if
|
||||
// the XML changes.
|
||||
// However, it's worthwhile having at least one test that verifies in this way.
|
||||
LdmlCompilerMessages.Warn_CustomForm(withOffset(367, {id: "us"}) as LDMLKeyboard.LKForm),
|
||||
LdmlCompilerMessages.Warn_CustomForm({id: "us"}, withOffset(367)),
|
||||
],
|
||||
callback: (sect, subpath, callbacks) => {
|
||||
const keys = sect as Keys;
|
||||
|
|
@ -400,7 +400,7 @@ describe('keys.kmap', function () {
|
|||
LdmlCompilerMessages.Warn_CustomForm({id: "us"}),
|
||||
],
|
||||
errors: [
|
||||
LdmlCompilerMessages.Error_InvalidScanCode({ codes: ['ff'] }, { id: 'us' }),
|
||||
LdmlCompilerMessages.Error_InvalidScanCode({ codes: 'ff', id: 'us' }),
|
||||
],
|
||||
},
|
||||
{
|
||||
|
|
@ -409,7 +409,7 @@ describe('keys.kmap', function () {
|
|||
LdmlCompilerMessages.Warn_CustomForm({id: "zzz"}),
|
||||
],
|
||||
errors: [
|
||||
LdmlCompilerMessages.Error_InvalidScanCode({ codes: ['ff'] }, { id: "zzz" }),
|
||||
LdmlCompilerMessages.Error_InvalidScanCode({ codes: 'ff', id: "zzz" }),
|
||||
],
|
||||
},
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue