8000 refactor(web): rename `RuleBehavior` → `ProcessorAction` 🎼 by ermshiperete · Pull Request #14001 · keymanapp/keyman · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

refactor(web): rename RuleBehaviorProcessorAction 🎼 #14001

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions web/docs/internal/context-state-management.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ A cache of recent context-state transitions is stored at `keyman.core.contextCac

For JS-keyboard keystroke processing, a `Mock` clone of the context is generated before any actual keyboard rule checks are applied. This provides a clear "before" state (eventually saved at `Transcription.preInput`) useful for determining the scope of the keystroke's changes once processing is completed via `buildTranscriptionFrom`.

Once keystroke processing is completed by a JS-keyboard, the JS-processor constructs a `RuleBehavior` object describing all primary and side effects of the keystroke. Defined at [web/src/engine/js-processor/src/ruleBehavior.ts](https://github.com/keymanapp/keyman/blob/master/web/src/engine/js-processor/src/ruleBehavior.ts), all of its fields aside from `transcription` are specific to JS-keyboard side effects, some of which do need special handling and support outside of the keystroke processor. None of these side effects apply for common-case keystrokes and so have default handling in place within the engine for cases where they are not needed.
Once keystroke processing is completed by a JS-keyboard, the JS-processor constructs a `ProcessorAction` object describing all primary and side effects of the keystroke. Defined at [web/src/engine/keyboard/src/keyboards/processorAction.ts](https://github.com/keymanapp/keyman/blob/master/web/src/engine/keyboard/src/keyboards/processorAction.ts), all of its fields aside from `transcription` are specific to JS-keyboard side effects, some of which do need special handling and support outside of the keystroke processor. None of these side effects apply for common-case keystrokes and so have default handling in place within the engine for cases where they are not needed.

---

In case referenced classes/files have moved: this doc was last updated in 18.0-beta, based upon commit d1e45a0df49f81597887577a8c83af36d4a85283
In case referenced classes/files have moved: this doc was last updated in 19.0-alpha, based upon PR #14001.
12 changes: 6 additions & 6 deletions web/docs/internal/keystroke-lifecycle.md
Original file line number Diff line number Diff line change
Expand Up @@ -212,13 +212,13 @@ host cleanly, as it may have special implications for the site or host app.

With that out of the way, the JS keyboard's main group is then provided with the
`KeyEvent` object in order to evaluate the keyboard's rules against the
keystroke. This involves constructing a `RuleBehavior` object to track any and
keystroke. This involves constructing a `ProcessorAction` object to track any and
all needed side-effects for the keystroke. Such changes are generally not
applied to the engine at large at this time in order to prevent unwanted side
effects that may arise to and from predictive text operations that follow
shortly afterward.

The `KeyboardInterface` class defines the internal API used by keyboards for
The `JSKeyboardInterface` class defines the internal API used by keyboards for
their evaluation of keyboard rules.

Once the keyboard's script returns control to the main engine, the engine then
Expand All @@ -233,7 +233,7 @@ keyboard rules that is applied. (A keyboard's source must _explicitly_ specify
to not emit anything for such keys if such an outcome is desired.) This occurs
regardless of the keystroke's source, as such effects are necessary to
incorporate for predictive-text operations. If no such rule exists, the
processor will add a note to the `RuleBehavior` object that default processing
processor will add a note to the `ProcessorAction` object that default processing
could not be provided and is thus needed from the engine's host.

### KMX keyboards & KMX+ (LDML) keyboards
Expand Down Expand Up @@ -263,12 +263,12 @@ detected.
### Keystroke post-processing

At this stage, the side-effects desired for the original keystroke, as saved to
its `RuleBehavior`, are then applied. Note that this includes changes to the
its `ProcessorAction`, are then applied. Note that this includes changes to the
`&layer` store - this update will also trigger an event that updates the state
of the OSK to match the desired layer.

Once that is done, the engine will then save data relevant to the original
context state, the `KeyEvent`, and the `RuleBehavior` to the "context cache"
context state, the `KeyEvent`, and the `ProcessorAction` to the "context cache"
supporting multitap context reversion. These effects include layer-change
effects that result from JS keyboard rules, which modify the KMN-style keyboard
stores `&oldlayer` and `&newlayer` in preparation for `begin PostKeystroke`
Expand Down Expand Up @@ -298,4 +298,4 @@ whether or not native handling for the keystroke should be triggered - such as
for TAB and ENTER keys, which may have semantic command-like functionality
depending on the state of the Web engine's host - be that a web page or an
Android/iOS app utilizing the keyboard. ENTER keys are often used to submit
forms, and this helps ensure we trigger such functionality when appropriate.
forms, and this helps ensure we trigger such functionality when appropriate.
15 changes: 7 additions & 8 deletions web/docs/internal/keystroke-processing.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ When `true`, the keystroke processor will need to simulate the results of "stand

On-screen keyboard modules and hardware-keyboard event interception modules will produce instances of `KeyEvent` as noted above. Once this is completed, both module types will _signal_ the keystroke event by raising an event with ID `keyevent` and provide the `KeyEvent` instance as its first parameter. The main module of the engine will then forward that `KeyEvent` object to the input processing pipeline via `InputProcessor.processKeyEvent` (see below).

## Output: RuleBehavior
## Output: ProcessorAction

Once keystroke processing is completed, the outward-facing components of the engine expect to receive a `RuleBehavior` object describing all primary and side effects of the keystroke. Defined at [web/src/engine/js-processor/src/ruleBehavior.ts](https://github.com/keymanapp/keyman/blob/master/web/src/engine/js-processor/src/ruleBehavior.ts), all of its fields aside from `transcription` are specific to existing JS-keyboard side effects. (Certain Keyman language features can make permanent side-effect changes to state that should only be persisted for the "true" keystroke - not for any predictive-text 'alternative' keys.)
Once keystroke processing is completed, the outward-facing components of the engine expect to receive a `ProcessorAction` object describing all primary and side effects of the keystroke. Defined at [web/src/engine/keyboard/src/keyboards/processorAction.ts](https://github.com/keymanapp/keyman/blob/master/web/src/engine/keyboard/src/keyboards/processorAction.ts), all of its fields aside from `transcription` are specific to existing JS-keyboard side effects. (Certain Keyman language features can make permanent side-effect changes to state that should only be persisted for the "true" keystroke - not for any predictive-text 'alternative' keys.)

See also: [context-state-management.md](context-state-management.md#js-keyboard-keystroke-processing)

Expand All @@ -31,7 +31,7 @@ See also: [context-state-management.md](context-state-management.md#js-keyboard

The "first stop" for incoming keystrokes is the `InputProcessor`, found at [web/src/engine/main/src/headless/inputProcessor.ts](https://github.com/keymanapp/keyman/blob/master/web/src/engine/main/src/headless/.inputProcessor.ts), through its `processKeyEvent` method. This class manages higher-level functionality triggered by keystroke events while deferring actual interpretation of the incoming keystroke further down the line. Of particular note is that it also handles control-flows that require restoration of previously-occuring contexts.

This class is the connection point for generating prediction requests and receiving corresponding suggestions. In order to facilitate higher-quality predictive-text when enabled, the `InputProcessor` will _also_ generate and trigger processing for nearby keys. This process allows transforms, reorders, and KMN keyboard rules to take effect and be used as alternative context roots for predictions. These are generally run against `Mock`-based clones of the true context source and are additionally prevented from triggering long-term side-effects, such as changes to KMN-keyboard variable stores, by only calling `RuleBehavior.finalize` for the true input keystroke's result object.
This class is the connection point for generating prediction requests and receiving corresponding suggestions. In order to facilitate higher-quality predictive-text when enabled, the `InputProcessor` will _also_ generate and trigger processing for nearby keys. This process allows transforms, reorders, and KMN keyboard rules to take effect and be used as alternative context roots for predictions. These are generally run against `Mock`-based clones of the true context source and are additionally prevented from triggering long-term side-effects, such as changes to KMN-keyboard variable stores, by only calling `KeyboardProcessor.finalizeProcessorAction` for the true input keystroke's result object.

Keys generated by OSK multitap need special handling here as well; they should always be applied to the context state as it existed at the time of the initial tap. To facilitate this, the `InputProcessor` will directly rewind the active context-source to match the corresponding context state before requesting that the `KeyEvent` be processed.

Expand Down Expand Up @@ -64,18 +64,17 @@ The method linked above is the primary entrypoint for rule processing of individ

#### JS-keyboard interfacing

Certain Keyman language features can make permanent side-effect changes to state. In order to prevent these from taking place for every keystroke, the method that interfaces with JS keyboards - `KeyboardInterface.process` - saves the context state (as a `Mock`) and current variable store values, then prepares a fresh `RuleBehavior` instance, before passing control off to the keyboard's backing script. (Note that `KeyboardInterface` itself primarily consists of keyboard-script API called by JS-keyboard script.)
- `epic/web-core` note: renamed to `JSKeyboardInterface`.
Certain Keyman language features can make permanent side-effect changes to state. In order to prevent these from taking place for every keystroke, the method that interfaces with JS keyboards - `JSKeyboardInterface.process` - saves the context state (as a `Mock`) and current variable store values, then prepares a fresh `ProcessorAction` instance, before passing control off to the keyboard's backing script. (Note that `JSKeyboardInterface` itself primarily consists of keyboard-script API called by JS-keyboard script.)

A few of the keyboard-script API methods will mark `RuleBehavior` properties directly when called, but the bulk of its data will be set once the keyboard-script returns control to Keyman Engine for Web. At this time, variable store values will also be reverted to prevent possible cross-contamination effects when predictive text is active - they're reapplied later if `RuleBehavior.finalize` is leveraged on the resulting instance. Components documented in [context-state-management.md](./context-state-management.md) are then leveraged to determine the total change to context caused by the keystroke.
A few of the keyboard-script API methods will mark `ProcessorAction` properties directly when called, but the bulk of its data will be set once the keyboard-script returns control to Keyman Engine for Web. At this time, variable store values will also be reverted to prevent possible cross-contamination effects when predictive text is active - they're reapplied later if `KeyboardProcessor.finalizeProcessorAction` is leveraged on the resulting instance. Components documented in [context-state-management.md](./context-state-management.md) are then leveraged to determine the total change to context caused by the keystroke.

Note that for JS-keyboards, in 18.0 and before the true keystroke is processed against the _true_ context state, not a cloned copy, and thus its changes are applied immediately.

#### Keystroke-default emulation

Note that browser-default keystroke processing is defined within the `DefaultRules` class found at [web/src/engine/keyboard/src/defaultRules.ts](https://github.com/keymanapp/keyman/blob/master/web/src/engine/keyboard/src/defaultRules.ts). It currently produces a (possibly `null`) string output rather than a `RuleBehavior`, but the latter can be easily constructed based on the returned string and the existing context state.
Note that browser-default keystroke processing is defined within the `DefaultRules` class found at [web/src/engine/keyboard/src/defaultRules.ts](https://github.com/keymanapp/keyman/blob/master/web/src/engine/keyboard/src/defaultRules.ts). It currently produces a (possibly `null`) string output rather than a `ProcessorAction`, but the latter can be easily constructed based on the returned string and the existing context state.
- For `epic/web-core`, it may be wise to spin the `DefaultRules` component off as its own processor, serving as a backup for _all_ keystroke processing variants.

----

In case referenced classes/files have moved: this doc was last updated in 18.0-beta, based upon commit d1e45a0df49f81597887577a8c83af36d4a85283
In case referenced classes/files have moved: this doc was last updated in 19.0-alpha, based upon PR #14001.
4 changes: 2 additions & 2 deletions web/src/app/browser/src/configuration.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { EngineConfiguration, InitOptionSpec, InitOptionDefaults } from "keyman/engine/main";

import { OutputTargetElementWrapper as DOMOutputTarget } from 'keyman/engine/element-wrappers';
import { OutputTargetInterface, RuleBehavior } from 'keyman/engine/keyboard';
import { OutputTargetInterface, ProcessorAction } from 'keyman/engine/keyboard';
import { isEmptyTransform } from 'keyman/engine/js-processor';
import { AlertHost } from "./utils/alertHost.js";
import { whenDocumentReady } from "./utils/documentReady.js";
Expand Down Expand Up @@ -66,7 +66,7 @@ export class BrowserConfiguration extends EngineConfiguration {
return baseReport;
}

onRuleFinalization(ruleBehavior: RuleBehavior, outputTarget: OutputTargetInterface) {
onRuleFinalization(ruleBehavior: ProcessorAction, outputTarget: OutputTargetInterface) {
// TODO: Patch up to modularized form. But that doesn't exist yet for some of these...

// If the transform isn't empty, we've changed text - which should produce a 'changed' event in the DOM.
Expand Dow AE8F n
2 changes: 1 addition & 1 deletion web/src/app/browser/src/defaultBrowserRules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export default class DefaultBrowserRules extends DefaultRules {
}

/**
* applyCommand - used when a RuleBehavior represents a non-text "command" within the Engine.
* applyCommand - used when a ProcessorAction represents a non-text "command" within the Engine.
*/
applyCommand(Lkc: KeyEvent, outputTarget: OutputTargetInterface): void {
const code = this.codeForEvent(Lkc);
Expand Down
4 changes: 2 additions & 2 deletions web/src/app/webview/src/keymanEngine.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { DeviceSpec, DefaultRules, RuleBehavior } from 'keyman/engine/keyboard';
import { DeviceSpec, DefaultRules, ProcessorAction } from 'keyman/engine/keyboard';
import { KeymanEngineBase, KeyboardInterfaceBase } from 'keyman/engine/main';
import { AnchoredOSKView, ViewConfiguration, StaticActivator } from 'keyman/engine/osk';
import { getAbsoluteX, getAbsoluteY } from 'keyman/engine/dom-utils';
Expand All @@ -17,7 +17,7 @@ export class KeymanEngine extends KeymanEngineBase<WebviewConfiguration, Context
constructor(workerFactory: WorkerFactory, sourceUri: string) {
const config = new WebviewConfiguration(sourceUri); // currently set to perform device auto-detect.

config.onRuleFi 54F4 nalization = (ruleBehavior: RuleBehavior) => {
config. ProcessorAction) => {
(this.context as ContextHost).updateHost(ruleBehavior.transcription);
}

Expand Down
Loading
0