mirror of
https://github.com/keymanapp/keyman.git
synced 2026-09-24 08:37:42 +00:00
Fixes backspace handling and duplicated suggestions.
This commit is contained in:
parent
0a0cfd0e97
commit
bb3a83b7c8
3 changed files with 60 additions and 12 deletions
|
|
@ -9,10 +9,21 @@ class ModelCompositor {
|
|||
predict(transformDistribution: Transform | Distribution<Transform>, context: Context): Suggestion[] {
|
||||
let suggestionDistribution: Distribution<Suggestion> = [];
|
||||
|
||||
// Assumption: Duplicated 'displayAs' properties indicate duplicated Suggestions.
|
||||
// When true, we can use an associated array to de-duplicate everything.
|
||||
let suggestionDistribMap: {[key: string]: ProbabilityMass<Suggestion>} = {};
|
||||
|
||||
if(!(transformDistribution instanceof Array)) {
|
||||
transformDistribution = [ {sample: transformDistribution, p: 1.0} ];
|
||||
}
|
||||
|
||||
// Find the transform for the actual keypress.
|
||||
let inputTransform = transformDistribution.sort(function(a, b) {
|
||||
return b.p - a.p;
|
||||
})[0].sample;
|
||||
|
||||
let inputResult = [];
|
||||
|
||||
for(let alt of transformDistribution) {
|
||||
let transform = alt.sample;
|
||||
let distribution = this.lexicalModel.predict(transform, context);
|
||||
|
|
@ -24,15 +35,24 @@ class ModelCompositor {
|
|||
pair.sample.transformId = transform.id;
|
||||
}
|
||||
|
||||
let compositedPair = {sample: pair.sample, p: pair.p * alt.p};
|
||||
suggestionDistribution.push(compositedPair);
|
||||
// Combine duplicate samples.
|
||||
let s = suggestionDistribMap[pair.sample.displayAs];
|
||||
if(s) {
|
||||
s.p += pair.p * alt.p;
|
||||
} else {
|
||||
let compositedPair = {sample: pair.sample, p: pair.p * alt.p};
|
||||
//suggestionDistribution.push(compositedPair);
|
||||
suggestionDistribMap[pair.sample.displayAs] = compositedPair;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Now that we've calculated the set of probability masses, time to join 'em together
|
||||
// and return the most likely candidates.
|
||||
|
||||
// TODO: What if the model emits duplicate samples, each with their own mass?
|
||||
// Now that we've calculated a unique set of probability masses, time to make them into a proper
|
||||
// distribution and prep for return.
|
||||
for(let key in suggestionDistribMap) {
|
||||
let pair = suggestionDistribMap[key];
|
||||
suggestionDistribution.push(pair);
|
||||
}
|
||||
|
||||
suggestionDistribution = suggestionDistribution.sort(function(a, b) {
|
||||
return b.p - a.p; // Use descending order - we want the largest probabilty suggestions first!
|
||||
|
|
|
|||
25
common/predictive-text/worker/models/common.ts
Normal file
25
common/predictive-text/worker/models/common.ts
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
namespace models {
|
||||
export class Common {
|
||||
static applyTransform(transform: Transform, context: Context): Context {
|
||||
// First, get the current context
|
||||
let fullLeftContext = context.left || '';
|
||||
let lLen = fullLeftContext.length;
|
||||
let lDel = lLen < transform.deleteLeft ? lLen : transform.deleteLeft;
|
||||
|
||||
let leftContext = fullLeftContext.substr(0, lLen - lDel) + (transform.insert || '');
|
||||
|
||||
let fullRightContext = context.right || '';
|
||||
let rLen = fullRightContext.length;
|
||||
let rDel = rLen < transform.deleteRight ? rLen : transform.deleteRight;
|
||||
|
||||
let rightContext = fullRightContext.substr(rDel);
|
||||
|
||||
return {
|
||||
left: leftContext,
|
||||
right: rightContext,
|
||||
startOfBuffer: context.startOfBuffer,
|
||||
endOfBuffer: context.endOfBuffer
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -23,6 +23,7 @@
|
|||
*/
|
||||
|
||||
/// <reference path="../word_breaking/placeholder-word-breaker.ts" />
|
||||
/// <reference path="common.ts" />
|
||||
|
||||
/**
|
||||
* @file trie-model.ts
|
||||
|
|
@ -101,13 +102,15 @@
|
|||
})));
|
||||
}
|
||||
|
||||
// EVERYTHING to the left of the cursor:
|
||||
let fullLeftContext = context.left || '';
|
||||
// Stuff to the left of the cursor in the current word.
|
||||
let leftContext = this.getLastWord(fullLeftContext);
|
||||
// Compute the results of the keystroke:
|
||||
let newContext = Common.applyTransform(transform, context);
|
||||
|
||||
// Computes the different in word length after applying the transform above.
|
||||
let leftDelOffset = transform.deleteLeft - transform.insert.length;
|
||||
|
||||
// All text to the left of the cursor INCLUDING anything that has
|
||||
// just been typed.
|
||||
let prefix = leftContext + (transform.insert || '');
|
||||
let prefix = this.getLastWord(newContext.left);
|
||||
|
||||
// Return suggestions from the trie.
|
||||
return makeDistribution(this._trie.lookup(prefix).map(({text, p}) => ({
|
||||
|
|
@ -117,7 +120,7 @@
|
|||
// Delete whatever the prefix that the user wrote.
|
||||
// Note: a separate capitalization/orthography engine can take this
|
||||
// result and transform it as needed.
|
||||
deleteLeft: leftContext.length,
|
||||
deleteLeft: leftDelOffset + prefix.length,
|
||||
},
|
||||
displayAs: text,
|
||||
p: p
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue