KeyHandler // Simplify member variable names.

This commit is contained in:
ShikiSuen 2022-06-15 14:02:31 +08:00
parent bb2ffe4c50
commit 4b83af377d
4 changed files with 98 additions and 98 deletions

View File

@ -43,11 +43,11 @@ protocol KeyHandlerDelegate {
class KeyHandler {
let kEpsilon: Double = 0.000001
let kMaxComposingBufferNeedsToWalkSize: Int = 10
var _composer: Tekkon.Composer = .init()
var _languageModel: vChewing.LMInstantiator = .init()
var _userOverrideModel: vChewing.LMUserOverride = .init()
var _builder: Megrez.BlockReadingBuilder
var _walkedNodes: [Megrez.NodeAnchor] = []
var composer: Tekkon.Composer = .init()
var compositor: Megrez.Compositor
var currentLM: vChewing.LMInstantiator = .init()
var currentUOM: vChewing.LMUserOverride = .init()
var walkedAnchors: [Megrez.NodeAnchor] = []
var delegate: KeyHandlerDelegate?
@ -59,29 +59,29 @@ class KeyHandler {
let isCHS: Bool = (newValue == InputMode.imeModeCHS)
// Reinitiate language models if necessary
_languageModel = isCHS ? mgrLangModel.lmCHS : mgrLangModel.lmCHT
_userOverrideModel = isCHS ? mgrLangModel.uomCHS : mgrLangModel.uomCHT
currentLM = isCHS ? mgrLangModel.lmCHS : mgrLangModel.lmCHT
currentUOM = isCHS ? mgrLangModel.uomCHS : mgrLangModel.uomCHT
// Synchronize the sub-languageModel state settings to the new LM.
syncBaseLMPrefs()
// Create new grid builder and clear the composer.
createNewBuilder()
_composer.clear()
composer.clear()
}
}
public init() {
_builder = Megrez.BlockReadingBuilder(lm: _languageModel, separator: "-")
compositor = Megrez.Compositor(lm: currentLM, separator: "-")
ensureParser()
// defer willSet
defer { inputMode = IME.currentInputMode }
}
func clear() {
_composer.clear()
_builder.clear()
_walkedNodes.removeAll()
composer.clear()
compositor.clear()
walkedAnchors.removeAll()
}
// MARK: - Functions dealing with Megrez.
@ -91,11 +91,11 @@ class KeyHandler {
// of the best possible Mandarin characters given the input syllables,
// using the Viterbi algorithm implemented in the Megrez library.
// The walk() traces the grid to the end.
_walkedNodes = _builder.walk()
walkedAnchors = compositor.walk()
// if DEBUG mode is enabled, a GraphViz file is written to kGraphVizOutputfile.
if mgrPrefs.isDebugModeEnabled {
let result = _builder.grid.dumpDOT
let result = compositor.grid.dumpDOT
do {
try result.write(
toFile: "/private/var/tmp/vChewing-visualization.dot",
@ -117,13 +117,13 @@ class KeyHandler {
// (i.e. popped out.)
var poppedText = ""
if _builder.grid.width > mgrPrefs.composingBufferSize {
if !_walkedNodes.isEmpty {
let anchor: Megrez.NodeAnchor = _walkedNodes[0]
if compositor.grid.width > mgrPrefs.composingBufferSize {
if !walkedAnchors.isEmpty {
let anchor: Megrez.NodeAnchor = walkedAnchors[0]
if let theNode = anchor.node {
poppedText = theNode.currentKeyValue.value
}
_builder.removeHeadReadings(count: anchor.spanningLength)
compositor.removeHeadReadings(count: anchor.spanningLength)
}
}
walk()
@ -132,17 +132,17 @@ class KeyHandler {
func buildAssociatePhraseArray(withKey key: String) -> [String] {
var arrResult: [String] = []
if _languageModel.hasAssociatedPhrasesForKey(key) {
arrResult.append(contentsOf: _languageModel.associatedPhrasesForKey(key))
if currentLM.hasAssociatedPhrasesForKey(key) {
arrResult.append(contentsOf: currentLM.associatedPhrasesForKey(key))
}
return arrResult
}
func fixNode(value: String, respectCursorPushing: Bool = true) {
let cursorIndex = min(actualCandidateCursorIndex + (mgrPrefs.useRearCursorMode ? 1 : 0), builderLength)
_builder.grid.fixNodeSelectedCandidate(location: cursorIndex, value: value)
compositor.grid.fixNodeSelectedCandidate(location: cursorIndex, value: value)
// //
// let selectedNode: Megrez.NodeAnchor = _builder.grid.fixNodeSelectedCandidate(
// let selectedNode: Megrez.NodeAnchor = compositor.grid.fixNodeSelectedCandidate(
// location: cursorIndex, value: value
// )
// //
@ -166,8 +166,8 @@ class KeyHandler {
// }
// if addToUserOverrideModel {
// IME.prtDebugIntel("UOM: Start Observation.")
// _userOverrideModel.observe(
// walkedNodes: _walkedNodes, cursorIndex: cursorIndex, candidate: value,
// currentUOM.observe(
// walkedNodes: walkedAnchors, cursorIndex: cursorIndex, candidate: value,
// timestamp: NSDate().timeIntervalSince1970
// )
// }
@ -176,7 +176,7 @@ class KeyHandler {
if mgrPrefs.moveCursorAfterSelectingCandidate, respectCursorPushing {
var nextPosition = 0
for node in _walkedNodes {
for node in walkedAnchors {
if nextPosition >= cursorIndex { break }
nextPosition += node.spanningLength
}
@ -215,15 +215,15 @@ class KeyHandler {
let overrideValue =
mgrPrefs.useSCPCTypingMode
? ""
: _userOverrideModel.suggest(
walkedNodes: _walkedNodes, cursorIndex: builderCursorIndex,
: currentUOM.suggest(
walkedNodes: walkedAnchors, cursorIndex: builderCursorIndex,
timestamp: NSDate().timeIntervalSince1970
)
if !overrideValue.isEmpty {
IME.prtDebugIntel(
"UOM: Suggestion retrieved, overriding the node score of the selected candidate.")
_builder.grid.overrideNodeScoreForSelectedCandidate(
compositor.grid.overrideNodeScoreForSelectedCandidate(
location: min(actualCandidateCursorIndex + (mgrPrefs.useRearCursorMode ? 1 : 0), builderLength),
value: overrideValue,
overridingScore: findHighestScore(nodes: rawNodes, epsilon: kEpsilon)
@ -251,89 +251,89 @@ class KeyHandler {
func ensureParser() {
switch mgrPrefs.mandarinParser {
case MandarinParser.ofStandard.rawValue:
_composer.ensureParser(arrange: .ofDachen)
composer.ensureParser(arrange: .ofDachen)
case MandarinParser.ofDachen26.rawValue:
_composer.ensureParser(arrange: .ofDachen26)
composer.ensureParser(arrange: .ofDachen26)
case MandarinParser.ofETen.rawValue:
_composer.ensureParser(arrange: .ofETen)
composer.ensureParser(arrange: .ofETen)
case MandarinParser.ofHsu.rawValue:
_composer.ensureParser(arrange: .ofHsu)
composer.ensureParser(arrange: .ofHsu)
case MandarinParser.ofETen26.rawValue:
_composer.ensureParser(arrange: .ofETen26)
composer.ensureParser(arrange: .ofETen26)
case MandarinParser.ofIBM.rawValue:
_composer.ensureParser(arrange: .ofIBM)
composer.ensureParser(arrange: .ofIBM)
case MandarinParser.ofMiTAC.rawValue:
_composer.ensureParser(arrange: .ofMiTAC)
composer.ensureParser(arrange: .ofMiTAC)
case MandarinParser.ofFakeSeigyou.rawValue:
_composer.ensureParser(arrange: .ofFakeSeigyou)
composer.ensureParser(arrange: .ofFakeSeigyou)
case MandarinParser.ofHanyuPinyin.rawValue:
_composer.ensureParser(arrange: .ofHanyuPinyin)
composer.ensureParser(arrange: .ofHanyuPinyin)
case MandarinParser.ofSecondaryPinyin.rawValue:
_composer.ensureParser(arrange: .ofSecondaryPinyin)
composer.ensureParser(arrange: .ofSecondaryPinyin)
case MandarinParser.ofYalePinyin.rawValue:
_composer.ensureParser(arrange: .ofYalePinyin)
composer.ensureParser(arrange: .ofYalePinyin)
case MandarinParser.ofHualuoPinyin.rawValue:
_composer.ensureParser(arrange: .ofHualuoPinyin)
composer.ensureParser(arrange: .ofHualuoPinyin)
case MandarinParser.ofUniversalPinyin.rawValue:
_composer.ensureParser(arrange: .ofUniversalPinyin)
composer.ensureParser(arrange: .ofUniversalPinyin)
default:
_composer.ensureParser(arrange: .ofDachen)
composer.ensureParser(arrange: .ofDachen)
mgrPrefs.mandarinParser = MandarinParser.ofStandard.rawValue
}
_composer.clear()
composer.clear()
}
// MARK: - Extracted methods and functions (Megrez).
var isBuilderEmpty: Bool { _builder.grid.width == 0 }
var isBuilderEmpty: Bool { compositor.grid.width == 0 }
var rawNodes: [Megrez.NodeAnchor] {
/// 使 nodesCrossing macOS
/// nodeCrossing
mgrPrefs.useRearCursorMode
? _builder.grid.nodesBeginningAt(location: actualCandidateCursorIndex)
: _builder.grid.nodesEndingAt(location: actualCandidateCursorIndex)
? compositor.grid.nodesBeginningAt(location: actualCandidateCursorIndex)
: compositor.grid.nodesEndingAt(location: actualCandidateCursorIndex)
}
func syncBaseLMPrefs() {
_languageModel.isPhraseReplacementEnabled = mgrPrefs.phraseReplacementEnabled
_languageModel.isCNSEnabled = mgrPrefs.cns11643Enabled
_languageModel.isSymbolEnabled = mgrPrefs.symbolInputEnabled
currentLM.isPhraseReplacementEnabled = mgrPrefs.phraseReplacementEnabled
currentLM.isCNSEnabled = mgrPrefs.cns11643Enabled
currentLM.isSymbolEnabled = mgrPrefs.symbolInputEnabled
}
func createNewBuilder() {
// Each Mandarin syllable is separated by a hyphen.
_builder = Megrez.BlockReadingBuilder(lm: _languageModel, separator: "-")
compositor = Megrez.Compositor(lm: currentLM, separator: "-")
}
var currentReadings: [String] { _builder.readings }
var currentReadings: [String] { compositor.readings }
func ifLangModelHasUnigrams(forKey reading: String) -> Bool {
_languageModel.hasUnigramsFor(key: reading)
currentLM.hasUnigramsFor(key: reading)
}
func insertReadingToBuilderAtCursor(reading: String) {
_builder.insertReadingAtCursor(reading: reading)
compositor.insertReadingAtCursor(reading: reading)
}
var builderCursorIndex: Int {
get { _builder.cursorIndex }
set { _builder.cursorIndex = newValue }
get { compositor.cursorIndex }
set { compositor.cursorIndex = newValue }
}
var builderLength: Int {
_builder.length
compositor.length
}
func deleteBuilderReadingInFrontOfCursor() {
_builder.deleteReadingAtTheRearOfCursor()
compositor.deleteReadingAtTheRearOfCursor()
}
func deleteBuilderReadingToTheFrontOfCursor() {
_builder.deleteReadingToTheFrontOfCursor()
compositor.deleteReadingToTheFrontOfCursor()
}
var keyLengthAtIndexZero: Int {
_walkedNodes[0].node?.currentKeyValue.value.count ?? 0
walkedAnchors[0].node?.currentKeyValue.value.count ?? 0
}
}

View File

@ -350,7 +350,7 @@ extension KeyHandler {
let punctuation: String = arrPunctuations.joined(separator: "")
var shouldAutoSelectCandidate: Bool =
_composer.inputValidityCheck(key: charCode) || ifLangModelHasUnigrams(forKey: customPunctuation)
composer.inputValidityCheck(key: charCode) || ifLangModelHasUnigrams(forKey: customPunctuation)
|| ifLangModelHasUnigrams(forKey: punctuation)
if !shouldAutoSelectCandidate, input.isUpperCaseASCIILetterKey {

View File

@ -146,37 +146,37 @@ extension KeyHandler {
let skipPhoneticHandling = input.isReservedKey || input.isControlHold || input.isOptionHold
// See if Phonetic reading is valid.
if !skipPhoneticHandling && _composer.inputValidityCheck(key: charCode) {
_composer.receiveKey(fromCharCode: charCode)
if !skipPhoneticHandling && composer.inputValidityCheck(key: charCode) {
composer.receiveKey(fromCharCode: charCode)
keyConsumedByReading = true
// If we have a tone marker, we have to insert the reading to the
// builder in other words, if we don't have a tone marker, we just
// update the composing buffer.
let composeReading = _composer.hasToneMarker()
let composeReading = composer.hasToneMarker()
if !composeReading {
stateCallback(buildInputtingState)
return true
}
}
var composeReading = _composer.hasToneMarker() //
var composeReading = composer.hasToneMarker() //
// See if we have composition if Enter/Space is hit and buffer is not empty.
// We use "|=" conditioning so that the tone marker key is also taken into account.
// However, Swift does not support "|=".
composeReading = composeReading || (!_composer.isEmpty && (input.isSpace || input.isEnter))
composeReading = composeReading || (!composer.isEmpty && (input.isSpace || input.isEnter))
if composeReading {
if input.isSpace, !_composer.hasToneMarker() {
_composer.receiveKey(fromString: " ") //
if input.isSpace, !composer.hasToneMarker() {
composer.receiveKey(fromString: " ") //
}
let reading = _composer.getComposition()
let reading = composer.getComposition()
// See whether we have a unigram for this...
if !ifLangModelHasUnigrams(forKey: reading) {
IME.prtDebugIntel("B49C0979語彙庫內無「\(reading)」的匹配記錄。")
errorCallback()
_composer.clear()
composer.clear()
stateCallback((builderLength == 0) ? InputState.EmptyIgnoringPreviousState() : buildInputtingState)
return true
}
@ -191,7 +191,7 @@ extension KeyHandler {
// dealWithOverrideModelSuggestions() // 使
// ... then update the text.
_composer.clear()
composer.clear()
let inputting = buildInputtingState
inputting.poppedText = poppedText
@ -240,7 +240,7 @@ extension KeyHandler {
// MARK: Calling candidate window using Up / Down or PageUp / PageDn.
if let currentState = state as? InputState.NotEmpty, _composer.isEmpty,
if let currentState = state as? InputState.NotEmpty, composer.isEmpty,
input.isExtraChooseCandidateKey || input.isExtraChooseCandidateKeyReverse || input.isSpace
|| input.isPageDown || input.isPageUp || (input.isTab && mgrPrefs.specifyShiftTabKeyBehavior)
|| (input.isTypingVertical && (input.isverticalTypingOnlyChooseCandidateKey))
@ -362,7 +362,7 @@ extension KeyHandler {
if input.isSymbolMenuPhysicalKey && !input.isShiftHold {
if input.isOptionHold {
if ifLangModelHasUnigrams(forKey: "_punctuation_list") {
if _composer.isEmpty {
if composer.isEmpty {
insertReadingToBuilderAtCursor(reading: "_punctuation_list")
let poppedText: String! = popOverflowComposingTextAndWalk
let inputting = buildInputtingState
@ -453,7 +453,7 @@ extension KeyHandler {
// "thinking" that the key is not actually consumed.
// F1-F12
// 便
if (state is InputState.NotEmpty) || !_composer.isEmpty {
if (state is InputState.NotEmpty) || !composer.isEmpty {
IME.prtDebugIntel(
"Blocked data: charCode: \(charCode), keyCode: \(input.keyCode)")
IME.prtDebugIntel("A9BFF20E")

View File

@ -41,7 +41,7 @@ extension KeyHandler {
// We must do some Unicode codepoint counting to find the actual cursor location for the client
// i.e. we need to take UTF-16 into consideration, for which a surrogate pair takes 2 UniChars
// locations. Since we are using Swift, we use .utf16 as the equivalent of NSString.length().
for walkedNode in _walkedNodes {
for walkedNode in walkedAnchors {
if let theNode = walkedNode.node {
let strNodeValue = theNode.currentKeyValue.value
composingBuffer += strNodeValue
@ -78,14 +78,14 @@ extension KeyHandler {
// Example in McBopomofo: Typing (3 readings) gets a tree emoji.
// Example in vChewing: Typing (2 readings) gets a pasta emoji.
switch builderCursorIndex {
case _builder.readings.count...:
tooltipParameterRef[0] = _builder.readings[_builder.readings.count - 1]
case compositor.readings.count...:
tooltipParameterRef[0] = compositor.readings[compositor.readings.count - 1]
case 0:
tooltipParameterRef[1] = _builder.readings[builderCursorIndex]
tooltipParameterRef[1] = compositor.readings[builderCursorIndex]
default:
do {
tooltipParameterRef[0] = _builder.readings[builderCursorIndex - 1]
tooltipParameterRef[1] = _builder.readings[builderCursorIndex]
tooltipParameterRef[0] = compositor.readings[builderCursorIndex - 1]
tooltipParameterRef[1] = compositor.readings[builderCursorIndex]
}
}
}
@ -109,7 +109,7 @@ extension KeyHandler {
}
let head = String(utf16CodeUnits: arrHead, count: arrHead.count)
let reading = _composer.getInlineCompositionForIMK(isHanyuPinyin: mgrPrefs.showHanyuPinyinInCompositionBuffer)
let reading = composer.getInlineCompositionForIMK(isHanyuPinyin: mgrPrefs.showHanyuPinyinInCompositionBuffer)
let tail = String(utf16CodeUnits: arrTail, count: arrTail.count)
let composedText = head + reading + tail
let cursorIndex = composedStringCursorIndex + reading.utf16.count
@ -259,14 +259,14 @@ extension KeyHandler {
return false
}
if _composer.isEmpty {
if composer.isEmpty {
insertReadingToBuilderAtCursor(reading: customPunctuation)
let poppedText = popOverflowComposingTextAndWalk
let inputting = buildInputtingState
inputting.poppedText = poppedText
stateCallback(inputting)
if mgrPrefs.useSCPCTypingMode, _composer.isEmpty {
if mgrPrefs.useSCPCTypingMode, composer.isEmpty {
let candidateState = buildCandidate(
state: inputting,
isTypingVertical: isTypingVertical
@ -345,7 +345,7 @@ extension KeyHandler {
var composed = ""
for theAnchor in _walkedNodes {
for theAnchor in walkedAnchors {
if let node = theAnchor.node {
var key = node.currentKeyValue.key
if mgrPrefs.inlineDumpPinyinInLieuOfZhuyin {
@ -382,9 +382,9 @@ extension KeyHandler {
) -> Bool {
guard state is InputState.Inputting else { return false }
if _composer.hasToneMarker(withNothingElse: true) {
_composer.clear()
} else if _composer.isEmpty {
if composer.hasToneMarker(withNothingElse: true) {
composer.clear()
} else if composer.isEmpty {
if builderCursorIndex >= 0 {
deleteBuilderReadingInFrontOfCursor()
walk()
@ -395,10 +395,10 @@ extension KeyHandler {
return true
}
} else {
_composer.doBackSpace()
composer.doBackSpace()
}
if _composer.isEmpty, builderLength == 0 {
if composer.isEmpty, builderLength == 0 {
stateCallback(InputState.EmptyIgnoringPreviousState())
} else {
stateCallback(buildInputtingState)
@ -415,7 +415,7 @@ extension KeyHandler {
) -> Bool {
guard state is InputState.Inputting else { return false }
if _composer.isEmpty {
if composer.isEmpty {
if builderCursorIndex != builderLength {
deleteBuilderReadingToTheFrontOfCursor()
walk()
@ -448,7 +448,7 @@ extension KeyHandler {
errorCallback: @escaping () -> Void
) -> Bool {
guard state is InputState.Inputting else { return false }
if !_composer.isEmpty {
if !composer.isEmpty {
IME.prtDebugIntel("9B6F908D")
errorCallback()
}
@ -465,7 +465,7 @@ extension KeyHandler {
) -> Bool {
guard state is InputState.Inputting else { return false }
if !_composer.isEmpty {
if !composer.isEmpty {
IME.prtDebugIntel("ABC44080")
errorCallback()
stateCallback(state)
@ -493,7 +493,7 @@ extension KeyHandler {
) -> Bool {
guard state is InputState.Inputting else { return false }
if !_composer.isEmpty {
if !composer.isEmpty {
IME.prtDebugIntel("9B69908D")
errorCallback()
stateCallback(state)
@ -532,8 +532,8 @@ extension KeyHandler {
stateCallback(InputState.EmptyIgnoringPreviousState())
} else {
// If reading is not empty, we cancel the reading.
if !_composer.isEmpty {
_composer.clear()
if !composer.isEmpty {
composer.clear()
if builderLength == 0 {
stateCallback(InputState.EmptyIgnoringPreviousState())
} else {
@ -554,7 +554,7 @@ extension KeyHandler {
) -> Bool {
guard let currentState = state as? InputState.Inputting else { return false }
if !_composer.isEmpty {
if !composer.isEmpty {
IME.prtDebugIntel("B3BA5257")
errorCallback()
stateCallback(state)
@ -603,7 +603,7 @@ extension KeyHandler {
) -> Bool {
guard let currentState = state as? InputState.Inputting else { return false }
if !_composer.isEmpty {
if !composer.isEmpty {
IME.prtDebugIntel("6ED95318")
errorCallback()
stateCallback(state)
@ -660,7 +660,7 @@ extension KeyHandler {
return false
}
guard _composer.isEmpty else {
guard composer.isEmpty else {
IME.prtDebugIntel("A2DAF7BC")
errorCallback()
return true
@ -679,7 +679,7 @@ extension KeyHandler {
let cursorIndex = min(
actualCandidateCursorIndex + (mgrPrefs.useRearCursorMode ? 1 : 0), builderLength
)
for anchor in _walkedNodes {
for anchor in walkedAnchors {
length += anchor.spanningLength
if length >= cursorIndex {
currentAnchor = anchor