mirror of
https://github.com/keymanapp/keyman.git
synced 2026-08-19 14:57:42 +00:00
133 lines
No EOL
4.8 KiB
TypeScript
133 lines
No EOL
4.8 KiB
TypeScript
namespace com.keyman.text {
|
|
/**
|
|
* Represents the commands and state changes that result from a matched keyboard rule.
|
|
*/
|
|
export class RuleBehavior {
|
|
/**
|
|
* The before-and-after Transform from matching a keyboard rule. May be `null`
|
|
* if no keyboard rules were matched for the keystroke.
|
|
*/
|
|
transcription: Transcription = null;
|
|
|
|
/**
|
|
* Indicates whether or not a BEEP command was issued by the matched keyboard rule.
|
|
*/
|
|
beep?: boolean;
|
|
|
|
/**
|
|
* A set of changed store values triggered by the matched keyboard rule.
|
|
*/
|
|
setStore: {[id: number]: string} = {};
|
|
|
|
/**
|
|
* A set of variable stores with save requests triggered by the matched keyboard rule
|
|
*/
|
|
saveStore: {[name: string]: VariableStore} = {};
|
|
|
|
/**
|
|
* A set of variable stores with possible changes to be applied during finalization.
|
|
*/
|
|
variableStores: keyboards.VariableStoreDictionary = {};
|
|
|
|
/**
|
|
* Denotes a non-output default behavior; this should be evaluated later, against the true keystroke.
|
|
*/
|
|
triggersDefaultCommand: boolean = false;
|
|
|
|
/**
|
|
* Denotes error log messages generated when attempting to generate this behavior.
|
|
*/
|
|
errorLog?: string;
|
|
|
|
/**
|
|
* Denotes warning log messages generated when attempting to generate this behavior.
|
|
*/
|
|
warningLog?: string;
|
|
|
|
/**
|
|
* If predictive text is active, contains a Promise returning predictive Suggestions.
|
|
*/
|
|
predictionPromise?: Promise<Suggestion[]>;
|
|
|
|
/**
|
|
* In reference to https://github.com/keymanapp/keyman/pull/4350#issuecomment-768753852:
|
|
*
|
|
* If the final group processed is a context and keystroke group (using keys),
|
|
* and there is no nomatch rule, and the keystroke is not matched in the group,
|
|
* the keystroke's default behavior should trigger, regardless of whether or not any
|
|
* rules in prior groups matched.
|
|
*/
|
|
triggerKeyDefault?: boolean;
|
|
|
|
finalize(processor: KeyboardProcessor, outputTarget: OutputTarget, readonly: boolean) {
|
|
if(!this.transcription) {
|
|
throw "Cannot finalize a RuleBehavior with no transcription.";
|
|
}
|
|
|
|
if(processor.beepHandler && this.beep) {
|
|
processor.beepHandler(outputTarget);
|
|
}
|
|
|
|
for(let storeID in this.setStore) {
|
|
let sysStore = processor.keyboardInterface.systemStores[storeID];
|
|
if(sysStore) {
|
|
try {
|
|
sysStore.set(this.setStore[storeID]);
|
|
} catch (error) {
|
|
if(processor.errorLogger) {
|
|
processor.errorLogger("Rule attempted to perform illegal operation - 'platform' may not be changed.");
|
|
}
|
|
}
|
|
} else if(processor.warningLogger) {
|
|
processor.warningLogger("Unknown store affected by keyboard rule: " + storeID);
|
|
}
|
|
}
|
|
|
|
processor.keyboardInterface.applyVariableStores(this.variableStores);
|
|
|
|
if(processor.keyboardInterface.variableStoreSerializer) {
|
|
for(let storeID in this.saveStore) {
|
|
processor.keyboardInterface.variableStoreSerializer.saveStore(processor.activeKeyboard.id, storeID, this.saveStore[storeID]);
|
|
}
|
|
}
|
|
|
|
if(this.triggersDefaultCommand) {
|
|
let keyEvent = this.transcription.keystroke;
|
|
DefaultOutput.applyCommand(keyEvent, outputTarget);
|
|
}
|
|
|
|
if(processor.warningLogger && this.warningLog) {
|
|
processor.warningLogger(this.warningLog);
|
|
} else if(processor.errorLogger && this.errorLog) {
|
|
processor.errorLogger(this.errorLog);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Merges default-related behaviors from another RuleBehavior into this one. Assumes that the current instance
|
|
* "came first" chronologically. Both RuleBehaviors must be sourced from the same keystroke.
|
|
*
|
|
* Intended use: merging rule-based behavior with default key behavior during scenarios like those described
|
|
* at https://github.com/keymanapp/keyman/pull/4350#issuecomment-768753852.
|
|
*
|
|
* This function does not attempt a "complete" merge for two fully-constructed RuleBehaviors! Things
|
|
* WILL break for unintended uses.
|
|
* @param other
|
|
*/
|
|
mergeInDefaults(other: RuleBehavior) {
|
|
let keystroke = this.transcription.keystroke;
|
|
let keyFromOther = other.transcription.keystroke;
|
|
if(keystroke.Lcode != keyFromOther.Lcode || keystroke.Lmodifiers != keyFromOther.Lmodifiers) {
|
|
throw "RuleBehavior default-merge not supported unless keystrokes are identical!";
|
|
}
|
|
|
|
this.triggersDefaultCommand = this.triggersDefaultCommand || other.triggersDefaultCommand;
|
|
|
|
let mergingMock = Mock.from(this.transcription.preInput, false);
|
|
mergingMock.apply(this.transcription.transform);
|
|
mergingMock.apply(other.transcription.transform);
|
|
|
|
this.transcription = mergingMock.buildTranscriptionFrom(this.transcription.preInput, keystroke, false, this.transcription.alternates);
|
|
}
|
|
}
|
|
} |