diff --git a/Source/Modules/InputHandler_Core.swift b/Source/Modules/InputHandler_Core.swift index c4cb8250..6ac00fe4 100644 --- a/Source/Modules/InputHandler_Core.swift +++ b/Source/Modules/InputHandler_Core.swift @@ -320,7 +320,7 @@ public class InputHandler: InputHandlerProtocol { key: newestSuggestedCandidate.0, value: newestSuggestedCandidate.1.value ) vCLog( - "UOM: Suggestion retrieved, overriding the node score of the selected candidate: \(suggestedPair.toNGramKey)") + "UOM: Suggestion received, overriding the node score of the selected candidate: \(suggestedPair.toNGramKey)") if !compositor.overrideCandidate(suggestedPair, at: cursorForCandidate, overrideType: overrideBehavior) { compositor.overrideCandidateLiteral( newestSuggestedCandidate.1.value, at: cursorForCandidate, overrideType: overrideBehavior @@ -336,13 +336,8 @@ public class InputHandler: InputHandlerProtocol { // MARK: - Extracted methods and functions (Tekkon). /// 獲取與當前注音排列或拼音輸入種類有關的標點索引鍵,以英數下畫線「_」結尾。 - var currentKeyboardParser: String { - currentKeyboardParserType.name + "_" - } - - var currentKeyboardParserType: KeyboardParser { - .init(rawValue: prefs.keyboardParser) ?? .ofStandard - } + var currentKeyboardParser: String { currentKeyboardParserType.name + "_" } + var currentKeyboardParserType: KeyboardParser { .init(rawValue: prefs.keyboardParser) ?? .ofStandard } /// 給注拼槽指定注音排列或拼音輸入種類之後,將注拼槽內容清空。 public func ensureKeyboardParser() { @@ -400,9 +395,7 @@ public class InputHandler: InputHandlerProtocol { /// - Parameter input: 輸入的按鍵訊號。 /// - Returns: 生成的標點符號索引鍵。 func generatePunctuationNamePrefix(withKeyCondition input: InputSignalProtocol) -> String { - if prefs.halfWidthPunctuationEnabled { - return "_half_punctuation_" - } + if prefs.halfWidthPunctuationEnabled { return "_half_punctuation_" } switch (input.isControlHold, input.isOptionHold) { case (true, true): return "_alt_ctrl_punctuation_" case (true, false): return "_ctrl_punctuation_" @@ -430,9 +423,7 @@ extension InputHandler { compositor.width > compositorWidthLimit, let identifier = delegate?.clientBundleIdentifier, prefs.clientsIMKTextInputIncapable.contains(identifier) - else { - return "" - } + else { return "" } // 回頭在這裡插上對 Steam 的 Client Identifier 的要求。 var textToCommit = "" while compositor.width > compositorWidthLimit { @@ -447,13 +438,9 @@ extension InputHandler { } let newCursor = max(compositor.cursor - delta, 0) compositor.cursor = 0 - if !node.isReadingMismatched { - consolidateCursorContext(with: node.currentPair) - } + if !node.isReadingMismatched { consolidateCursorContext(with: node.currentPair) } // 威注音不支援 Bigram,所以無須考慮前後節點「是否需要鞏固」。 - for _ in 0.. Bool? { + handlePhonabetComposition(input: input) + } + + /// 用來處理 InputHandler.HandleInput() 當中的與注音输入有關的組字行為。 + /// - Parameters: + /// - input: 輸入訊號。 + /// - Returns: 告知 IMK「該按鍵是否已經被輸入法攔截處理」。 + private func handlePhonabetComposition(input: InputSignalProtocol) -> Bool? { guard let delegate = delegate else { return nil } // MARK: 注音按鍵輸入處理 (Handle BPMF Keys) diff --git a/Source/Modules/InputHandler_HandleInput.swift b/Source/Modules/InputHandler_HandleInput.swift index f2091cfd..3661f1ad 100644 --- a/Source/Modules/InputHandler_HandleInput.swift +++ b/Source/Modules/InputHandler_HandleInput.swift @@ -68,7 +68,6 @@ extension InputHandler { // 將整個組字區的內容遞交給客體應用。 delegate.switchState(IMEState.ofCommitting(textToCommit: inputText.lowercased())) - delegate.switchState(IMEState.ofEmpty()) return true } @@ -79,21 +78,15 @@ extension InputHandler { // 不然、使用 Cocoa 內建的 flags 的話,會誤傷到在主鍵盤區域的功能鍵。 // 我們先規定允許小鍵盤區域操縱選字窗,其餘場合一律直接放行。 if input.isNumericPadKey { - if !(state.type == .ofCandidates || state.type == .ofAssociates - || state.type == .ofSymbolTable) - { - delegate.switchState(IMEState.ofEmpty()) + if ![.ofCandidates, .ofAssociates, .ofSymbolTable].contains(state.type) { delegate.switchState(IMEState.ofCommitting(textToCommit: inputText.lowercased())) - delegate.switchState(IMEState.ofEmpty()) return true } } // MARK: 處理候選字詞 (Handle Candidates) - if [.ofCandidates, .ofSymbolTable].contains(state.type) { - return handleCandidate(input: input) - } + if [.ofCandidates, .ofSymbolTable].contains(state.type) { return handleCandidate(input: input) } // MARK: 處理聯想詞 (Handle Associated Phrases) @@ -132,7 +125,6 @@ extension InputHandler { delegate.switchState(IMEState.ofCommitting(textToCommit: displayedText)) } delegate.switchState(IMEState.ofCommitting(textToCommit: " ")) - delegate.switchState(IMEState.ofEmpty()) } else if currentLM.hasUnigramsFor(key: " ") { compositor.insertKey(" ") walk() @@ -147,12 +139,9 @@ extension InputHandler { return handleInlineCandidateRotation(reverseOrder: input.isCommandHold) } } + // 開始決定是否切換至選字狀態。 let candidateState: IMEStateProtocol = generateStateOfCandidates() - if candidateState.candidates.isEmpty { - delegate.callError("3572F238") - } else { - delegate.switchState(candidateState) - } + _ = candidateState.candidates.isEmpty ? delegate.callError("3572F238") : delegate.switchState(candidateState) return true } @@ -199,12 +188,9 @@ extension InputHandler { var inputting = generateStateOfInputting() inputting.textToCommit = textToCommit delegate.switchState(inputting) - let candidateState = generateStateOfCandidates() - if candidateState.candidates.isEmpty { - delegate.callError("B5127D8A") - } else { - delegate.switchState(candidateState) - } + // 開始決定是否切換至選字狀態。 + let newState = generateStateOfCandidates() + _ = newState.candidates.isEmpty ? delegate.callError("B5127D8A") : delegate.switchState(newState) } else { // 不要在注音沒敲完整的情況下叫出統合符號選單。 delegate.callError("17446655") } @@ -212,9 +198,7 @@ extension InputHandler { } } else { // 得在這裡先 commit buffer,不然會導致「在摁 ESC 離開符號選單時會重複輸入上一次的組字區的內容」的不當行為。 - // 於是這裡用「模擬一次 Enter 鍵的操作」使其代為執行這個 commit buffer 的動作。 - // 這裡不需要該函式所傳回的 bool 結果,所以用「_ =」解消掉。 - _ = handleEnter() + delegate.switchState(IMEState.ofCommitting(textToCommit: state.displayedText)) delegate.switchState(IMEState.ofSymbolTable(node: CandidateNode.root)) return true } @@ -224,13 +208,10 @@ extension InputHandler { if state.type == .ofEmpty { if input.isMainAreaNumKey, input.modifierFlags == [.shift, .option] { - guard let stringRAW = input.mainAreaNumKeyChar else { return false } - let newStringFW = stringRAW.applyingTransform(.fullwidthToHalfwidth, reverse: true) ?? stringRAW - let newStringHW = stringRAW.applyingTransform(.fullwidthToHalfwidth, reverse: false) ?? stringRAW - delegate.switchState( - IMEState.ofCommitting(textToCommit: prefs.halfWidthPunctuationEnabled ? newStringHW : newStringFW) - ) - delegate.switchState(IMEState.ofEmpty()) + guard let strRAW = input.mainAreaNumKeyChar else { return false } + let newString = + strRAW.applyingTransform(.fullwidthToHalfwidth, reverse: !prefs.halfWidthPunctuationEnabled) ?? strRAW + delegate.switchState(IMEState.ofCommitting(textToCommit: newString)) return true } } @@ -240,23 +221,15 @@ extension InputHandler { /// 如果仍無匹配結果的話,先看一下: /// - 是否是針對當前注音排列/拼音輸入種類專門提供的標點符號。 /// - 是否是需要摁修飾鍵才可以輸入的那種標點符號。 - let punctuationNamePrefix: String = generatePunctuationNamePrefix(withKeyCondition: input) let parser = currentKeyboardParser let arrCustomPunctuations: [String] = [punctuationNamePrefix, parser, input.text] let customPunctuation: String = arrCustomPunctuations.joined() - if handlePunctuation(customPunctuation) { - return true - } - + if handlePunctuation(customPunctuation) { return true } /// 如果仍無匹配結果的話,看看這個輸入是否是不需要修飾鍵的那種標點鍵輸入。 - let arrPunctuations: [String] = [punctuationNamePrefix, input.text] let punctuation: String = arrPunctuations.joined() - - if handlePunctuation(punctuation) { - return true - } + if handlePunctuation(punctuation) { return true } // MARK: 全形/半形空白 (Full-Width / Half-Width Space) @@ -264,7 +237,6 @@ extension InputHandler { if state.type == .ofEmpty { if input.isSpace, !input.isOptionHold, !input.isControlHold, !input.isCommandHold { delegate.switchState(IMEState.ofCommitting(textToCommit: input.isShiftHold ? " " : " ")) - delegate.switchState(IMEState.ofEmpty()) return true } } @@ -275,15 +247,10 @@ extension InputHandler { if input.isShiftHold { // 這裡先不要判斷 isOptionHold。 switch prefs.upperCaseLetterKeyBehavior { case 1: - delegate.switchState(IMEState.ofEmpty()) delegate.switchState(IMEState.ofCommitting(textToCommit: inputText.lowercased())) - delegate.switchState(IMEState.ofEmpty()) return true - case 2: - delegate.switchState(IMEState.ofEmpty()) delegate.switchState(IMEState.ofCommitting(textToCommit: inputText.uppercased())) - delegate.switchState(IMEState.ofEmpty()) return true default: // 包括 case 0,直接塞給組字區。 let letter = "_letter_\(inputText)" @@ -301,8 +268,7 @@ extension InputHandler { /// 砍掉這一段會導致「F1-F12 按鍵干擾組字區」的問題。 /// 暫時只能先恢復這段,且補上偵錯彙報機制,方便今後排查故障。 if state.hasComposition || !composer.isEmpty { - delegate.callError( - "Blocked data: charCode: \(input.charCode), keyCode: \(input.keyCode)") + delegate.callError("Blocked data: charCode: \(input.charCode), keyCode: \(input.keyCode)") delegate.callError("A9BFF20E") delegate.switchState(state) return true diff --git a/Source/Modules/InputHandler_States.swift b/Source/Modules/InputHandler_States.swift index 31fb5e27..95e4793c 100644 --- a/Source/Modules/InputHandler_States.swift +++ b/Source/Modules/InputHandler_States.swift @@ -252,7 +252,6 @@ extension InputHandler { clear() // 這句不要砍,因為下文可能會回呼 candidateState。 if let candidateToCommit: (String, String) = candidateState.candidates.first, !candidateToCommit.1.isEmpty { delegate.switchState(IMEState.ofCommitting(textToCommit: candidateToCommit.1)) - delegate.switchState(IMEState.ofEmpty()) } else { delegate.switchState(candidateState) } @@ -265,13 +264,12 @@ extension InputHandler { /// Enter 鍵的處理。 /// - Returns: 將按鍵行為「是否有處理掉」藉由 SessionCtl 回報給 IMK。 - func handleEnter() -> Bool { + @discardableResult func handleEnter() -> Bool { guard let delegate = delegate else { return false } let state = delegate.state guard state.type == .ofInputting else { return false } delegate.switchState(IMEState.ofCommitting(textToCommit: state.displayedText)) - delegate.switchState(IMEState.ofEmpty()) return true } @@ -295,7 +293,6 @@ extension InputHandler { } delegate.switchState(IMEState.ofCommitting(textToCommit: displayedText)) - delegate.switchState(IMEState.ofEmpty()) return true } @@ -327,7 +324,6 @@ extension InputHandler { } delegate.switchState(IMEState.ofCommitting(textToCommit: composed)) - delegate.switchState(IMEState.ofEmpty()) return true } @@ -432,9 +428,7 @@ extension InputHandler { guard let delegate = delegate else { return false } let state = delegate.state guard state.type == .ofInputting else { return false } - if !composer.isEmpty { - delegate.callError("9B6F908D") - } + if !composer.isEmpty { delegate.callError("9B6F908D") } delegate.switchState(state) return true } @@ -616,9 +610,7 @@ extension InputHandler { delegate.switchState(state) } } else if input.isOptionHold { - if input.isControlHold { - return handleHome() - } + if input.isControlHold { return handleHome() } // 游標跳轉動作無論怎樣都會執行,但如果出了執行失敗的結果的話則觸發報錯流程。 if !compositor.jumpCursorBySpan(to: .rear) { delegate.callError("8D50DD9E")