From a2f5606579675c52df43be7ab1f26c26c5184eec Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Wed, 8 Mar 2023 23:44:24 +0800 Subject: [PATCH] Repo // Add parameter names for ([String], String). --- .../CandidateWindow/CandidatePool.swift | 4 +- .../VwrCandidateTDK_SwiftUI.swift | 2 +- .../CandidatePoolTests.swift | 2 +- .../Protocols/CtlCandidateProtocol.swift | 2 +- Source/Modules/IMEState.swift | 4 +- Source/Modules/IMEStateData.swift | 2 +- Source/Modules/InputHandler_Core.swift | 16 +++---- .../InputHandler_HandleComposition.swift | 8 ++-- .../Modules/InputHandler_HandleStates.swift | 6 +-- Source/Modules/SessionCtl_Delegates.swift | 25 ++++++----- .../SessionCtl_IMKCandidatesData.swift | 42 +++++++++++-------- 11 files changed, 60 insertions(+), 53 deletions(-) diff --git a/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/CandidatePool.swift b/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/CandidatePool.swift index e5ddc816..57510f4e 100644 --- a/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/CandidatePool.swift +++ b/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/CandidatePool.swift @@ -77,7 +77,7 @@ public struct CandidatePool { /// - direction: 橫向排列還是縱向排列(預設情況下是縱向)。 /// - locale: 區域編碼。例:「zh-Hans」或「zh-Hant」。 public init( - candidates: [([String], String)], lines: Int = 3, selectionKeys: String = "123456789", + candidates: [(keyArray: [String], value: String)], lines: Int = 3, selectionKeys: String = "123456789", layout: LayoutOrientation = .vertical, locale: String = "" ) { self.layout = layout @@ -87,7 +87,7 @@ public struct CandidatePool { blankCell.locale = locale self.selectionKeys = selectionKeys.isEmpty ? "123456789" : selectionKeys var allCandidates = candidates.map { - CandidateCellData(key: " ", displayedText: $0.1, spanLength: $0.0.count) + CandidateCellData(key: " ", displayedText: $0.value, spanLength: $0.keyArray.count) } if allCandidates.isEmpty { allCandidates.append(blankCell) } candidateDataAll = allCandidates diff --git a/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/TDKCandidates/VwrCandidateTDK_SwiftUI.swift b/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/TDKCandidates/VwrCandidateTDK_SwiftUI.swift index 15c14ded..7ff1a548 100644 --- a/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/TDKCandidates/VwrCandidateTDK_SwiftUI.swift +++ b/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/TDKCandidates/VwrCandidateTDK_SwiftUI.swift @@ -375,7 +375,7 @@ struct VwrCandidateTDK_Previews: PreviewProvider { @State static var tooltip = "📼" @State static var oldOS: Bool = true - static var testCandidatesConverted: [([String], String)] { + static var testCandidatesConverted: [(keyArray: [String], value: String)] { testCandidates.map { candidate in let firstValue: [String] = .init(repeating: "", count: candidate.count) return (firstValue, candidate) diff --git a/Packages/vChewing_CandidateWindow/Tests/CandidateWindowTests/CandidatePoolTests.swift b/Packages/vChewing_CandidateWindow/Tests/CandidateWindowTests/CandidatePoolTests.swift index 7b8f3b64..7521006d 100644 --- a/Packages/vChewing_CandidateWindow/Tests/CandidateWindowTests/CandidatePoolTests.swift +++ b/Packages/vChewing_CandidateWindow/Tests/CandidateWindowTests/CandidatePoolTests.swift @@ -19,7 +19,7 @@ final class CandidatePoolTests: XCTestCase { "嗯", "哼", "啊", ] - var testCandidatesConverted: [([String], String)] { + var testCandidatesConverted: [(keyArray: [String], value: String)] { testCandidates.map { candidate in let firstValue: [String] = .init(repeating: "", count: candidate.count) return (firstValue, candidate) diff --git a/Packages/vChewing_Shared/Sources/Shared/Protocols/CtlCandidateProtocol.swift b/Packages/vChewing_Shared/Sources/Shared/Protocols/CtlCandidateProtocol.swift index 07317c78..8a86522d 100644 --- a/Packages/vChewing_Shared/Sources/Shared/Protocols/CtlCandidateProtocol.swift +++ b/Packages/vChewing_Shared/Sources/Shared/Protocols/CtlCandidateProtocol.swift @@ -9,7 +9,7 @@ import Cocoa public protocol CtlCandidateDelegate { - func candidatePairs(conv: Bool) -> [([String], String)] + func candidatePairs(conv: Bool) -> [(keyArray: [String], value: String)] func candidatePairSelected(at index: Int) func candidatePairRightClicked(at index: Int, action: CandidateContextMenuAction) func candidates(_ sender: Any!) -> [Any]! diff --git a/Source/Modules/IMEState.swift b/Source/Modules/IMEState.swift index 3b6175f2..fc2c4085 100644 --- a/Source/Modules/IMEState.swift +++ b/Source/Modules/IMEState.swift @@ -104,7 +104,7 @@ public extension IMEState { return result } - static func ofAssociates(candidates: [([String], String)]) -> IMEState { + static func ofAssociates(candidates: [(keyArray: [String], value: String)]) -> IMEState { var result = IMEState(type: .ofAssociates) result.candidates = candidates return result @@ -129,7 +129,7 @@ public extension IMEState { return result } - static func ofCandidates(candidates: [([String], String)], displayTextSegments: [String], cursor: Int) + static func ofCandidates(candidates: [(keyArray: [String], value: String)], displayTextSegments: [String], cursor: Int) -> IMEState { var result = IMEState(displayTextSegments: displayTextSegments, cursor: cursor) diff --git a/Source/Modules/IMEStateData.swift b/Source/Modules/IMEStateData.swift index b8c456f3..a4618756 100644 --- a/Source/Modules/IMEStateData.swift +++ b/Source/Modules/IMEStateData.swift @@ -216,7 +216,7 @@ public extension IMEStateData { return "" } - let text = pair.1 + let text = pair.value let readingDisplay = readingThreadForDisplay if markedRange.count < Self.allowedMarkLengthRange.lowerBound { tooltipColorState = .denialInsufficiency diff --git a/Source/Modules/InputHandler_Core.swift b/Source/Modules/InputHandler_Core.swift index 2241ceb6..c3675e4d 100644 --- a/Source/Modules/InputHandler_Core.swift +++ b/Source/Modules/InputHandler_Core.swift @@ -34,7 +34,7 @@ public protocol InputHandlerProtocol { func generateStateOfInputting(sansReading: Bool) -> IMEStateProtocol func generateStateOfAssociates(withPair pair: Megrez.Compositor.KeyValuePaired) -> IMEStateProtocol func consolidateNode( - candidate: ([String], String), respectCursorPushing: Bool, preConsolidate: Bool, skipObservation: Bool + candidate: (keyArray: [String], value: String), respectCursorPushing: Bool, preConsolidate: Bool, skipObservation: Bool ) func updateUnigramData() -> Bool } @@ -44,7 +44,7 @@ extension InputHandlerProtocol { generateStateOfInputting(sansReading: sansReading) } - func consolidateNode(candidate: ([String], String), respectCursorPushing: Bool, preConsolidate: Bool) { + func consolidateNode(candidate: (keyArray: [String], value: String), respectCursorPushing: Bool, preConsolidate: Bool) { consolidateNode( candidate: candidate, respectCursorPushing: respectCursorPushing, preConsolidate: preConsolidate, skipObservation: false @@ -196,8 +196,8 @@ public class InputHandler: InputHandlerProtocol { /// - Parameter key: 給定的聯想詞的開頭字。 /// - Returns: 抓取到的聯想詞陣列。 /// 不會是 nil,但那些負責接收結果的函式會對空白陣列結果做出正確的處理。 - func generateArrayOfAssociates(withPair pair: Megrez.Compositor.KeyValuePaired) -> [([String], String)] { - var arrResult: [([String], String)] = [] + func generateArrayOfAssociates(withPair pair: Megrez.Compositor.KeyValuePaired) -> [(keyArray: [String], value: String)] { + var arrResult: [(keyArray: [String], value: String)] = [] if currentLM.hasAssociatedPhrasesFor(pair: pair) { arrResult = currentLM.associatedPhrasesFor(pair: pair).map { ([""], $0) } } @@ -299,10 +299,12 @@ public class InputHandler: InputHandlerProtocol { /// - preConsolidate: 在固化節點之前,先鞏固上下文。該選項可能會破壞在內文組字區內就地輪替候選字詞時的體驗。 /// - skipObservation: 不要讓半衰記憶模組對此做出觀察。 public func consolidateNode( - candidate: ([String], String), respectCursorPushing: Bool = true, + candidate: (keyArray: [String], value: String), respectCursorPushing: Bool = true, preConsolidate: Bool = false, skipObservation: Bool = false ) { - let theCandidate: Megrez.Compositor.KeyValuePaired = .init(keyArray: candidate.0, value: candidate.1) + let theCandidate: Megrez.Compositor.KeyValuePaired = .init( + keyArray: candidate.keyArray, value: candidate.value + ) /// 必須先鞏固當前組字器游標上下文、以消滅意料之外的影響,但在內文組字區內就地輪替候選字詞時除外。 if preConsolidate { consolidateCursorContext(with: theCandidate) } @@ -344,7 +346,7 @@ public class InputHandler: InputHandlerProtocol { } /// 獲取候選字詞(包含讀音)陣列資料內容。 - func generateArrayOfCandidates(fixOrder: Bool = true) -> [([String], String)] { + func generateArrayOfCandidates(fixOrder: Bool = true) -> [(keyArray: [String], value: String)] { /// 警告:不要對游標前置風格使用 nodesCrossing,否則會導致游標行為與 macOS 內建注音輸入法不一致。 /// 微軟新注音輸入法的游標後置風格也是不允許 nodeCrossing 的。 var arrCandidates: [Megrez.Compositor.KeyValuePaired] = { diff --git a/Source/Modules/InputHandler_HandleComposition.swift b/Source/Modules/InputHandler_HandleComposition.swift index a82e3eb9..5c150541 100644 --- a/Source/Modules/InputHandler_HandleComposition.swift +++ b/Source/Modules/InputHandler_HandleComposition.swift @@ -143,12 +143,12 @@ extension InputHandler { case 2...: delegate.switchState(candidateState) case 1: let firstCandidate = candidateState.candidates.first! // 一定會有,所以強制拆包也無妨。 - let reading: String = firstCandidate.0.joined(separator: compositor.separator) - let text: String = firstCandidate.1 + let reading: [String] = firstCandidate.keyArray + let text: String = firstCandidate.value delegate.switchState(IMEState.ofCommitting(textToCommit: text)) if prefs.associatedPhrasesEnabled { - let associatedPhrases = generateStateOfAssociates(withPair: .init(keyArray: [reading], value: text)) + let associatedPhrases = generateStateOfAssociates(withPair: .init(keyArray: reading, value: text)) delegate.switchState(associatedPhrases.candidates.isEmpty ? IMEState.ofEmpty() : associatedPhrases) } default: break @@ -285,7 +285,7 @@ extension InputHandler { case 1: let firstCandidate = candidateState.candidates.first! // 一定會有,所以強制拆包也無妨。 let reading: String = firstCandidate.0.joined(separator: compositor.separator) - let text: String = firstCandidate.1 + let text: String = firstCandidate.value delegate.switchState(IMEState.ofCommitting(textToCommit: text)) if prefs.associatedPhrasesEnabled { diff --git a/Source/Modules/InputHandler_HandleStates.swift b/Source/Modules/InputHandler_HandleStates.swift index 387e24bb..b6ecea8c 100644 --- a/Source/Modules/InputHandler_HandleStates.swift +++ b/Source/Modules/InputHandler_HandleStates.swift @@ -275,8 +275,8 @@ extension InputHandler { case 2...: delegate.switchState(candidateState) case 1: clear() // 這句不要砍,因為下文可能會回呼 candidateState。 - if let candidateToCommit: ([String], String) = candidateState.candidates.first, !candidateToCommit.1.isEmpty { - delegate.switchState(IMEState.ofCommitting(textToCommit: candidateToCommit.1)) + if let strToCommit = candidateState.candidates.first?.value, !strToCommit.isEmpty { + delegate.switchState(IMEState.ofCommitting(textToCommit: strToCommit)) } else { delegate.switchState(candidateState) } @@ -813,7 +813,7 @@ extension InputHandler { var newState = generateStateOfInputting() let locID = Bundle.main.preferredLocalizations[0] let newTooltip = NSMutableString() - newTooltip.insert(" " + candidates[newIndex].1, at: 0) + newTooltip.insert(" " + candidates[newIndex].value, at: 0) if #available(macOS 10.13, *), isContextVertical(), locID != "en" { newTooltip.insert((newIndex + 1).i18n(loc: locID) + "・" + candidates.count.i18n(loc: locID), at: 0) } else { diff --git a/Source/Modules/SessionCtl_Delegates.swift b/Source/Modules/SessionCtl_Delegates.swift index e55f9419..3f19d6f6 100644 --- a/Source/Modules/SessionCtl_Delegates.swift +++ b/Source/Modules/SessionCtl_Delegates.swift @@ -95,16 +95,15 @@ extension SessionCtl: CtlCandidateDelegate { PrefMgr.shared.useIMKCandidateWindow ? "123456789" : PrefMgr.shared.candidateKeys } - public func candidatePairs(conv: Bool = false) -> [([String], String)] { + public func candidatePairs(conv: Bool = false) -> [(keyArray: [String], value: String)] { if !state.isCandidateContainer || state.candidates.isEmpty { return [] } - if !conv || PrefMgr.shared.cns11643Enabled || state.candidates[0].0.joined().contains("_punctuation") { + if !conv || PrefMgr.shared.cns11643Enabled || state.candidates[0].keyArray.joined().contains("_punctuation") { return state.candidates } - let convertedCandidates: [([String], String)] = state.candidates.map { theCandidatePair -> ([String], String) in - let theCandidate = theCandidatePair.1 - let theConverted = ChineseConverter.kanjiConversionIfRequired(theCandidate) - let result = (theCandidate == theConverted) ? theCandidate : "\(theConverted)(\(theCandidate))" - return (theCandidatePair.0, result) + let convertedCandidates = state.candidates.map { theCandidatePair -> (keyArray: [String], value: String) in + var theCandidatePair = theCandidatePair + theCandidatePair.value = ChineseConverter.kanjiConversionIfRequired(theCandidatePair.value) + return theCandidatePair } return convertedCandidates } @@ -136,10 +135,10 @@ extension SessionCtl: CtlCandidateDelegate { if PrefMgr.shared.useSCPCTypingMode { switchState(IMEState.ofCommitting(textToCommit: inputting.displayedText)) - // 此時是逐字選字模式,所以「selectedValue.1」是單個字、不用追加處理。 + // 此時是逐字選字模式,所以「selectedValue.value」是單個字、不用追加處理。 if PrefMgr.shared.associatedPhrasesEnabled { let associates = inputHandler.generateStateOfAssociates( - withPair: .init(keyArray: selectedValue.0, value: selectedValue.1) + withPair: .init(keyArray: selectedValue.keyArray, value: selectedValue.value) ) switchState(associates.candidates.isEmpty ? IMEState.ofEmpty() : associates) } else { @@ -153,16 +152,16 @@ extension SessionCtl: CtlCandidateDelegate { if state.type == .ofAssociates { let selectedValue = state.candidates[index] - switchState(IMEState.ofCommitting(textToCommit: selectedValue.1)) - // 此時是聯想詞選字模式,所以「selectedValue.1」必須只保留最後一個字。 + switchState(IMEState.ofCommitting(textToCommit: selectedValue.value)) + // 此時是聯想詞選字模式,所以「selectedValue.value」必須只保留最後一個字。 // 不然的話,一旦你選中了由多個字組成的聯想候選詞,則連續聯想會被打斷。 - guard let valueKept = selectedValue.1.last else { + guard let valueKept = selectedValue.value.last else { switchState(IMEState.ofEmpty()) return } if PrefMgr.shared.associatedPhrasesEnabled { let associates = inputHandler.generateStateOfAssociates( - withPair: .init(keyArray: selectedValue.0, value: String(valueKept)) + withPair: .init(keyArray: selectedValue.keyArray, value: String(valueKept)) ) if !associates.candidates.isEmpty { switchState(associates) diff --git a/Source/Modules/SessionCtl_IMKCandidatesData.swift b/Source/Modules/SessionCtl_IMKCandidatesData.swift index 8f560807..1b39945d 100644 --- a/Source/Modules/SessionCtl_IMKCandidatesData.swift +++ b/Source/Modules/SessionCtl_IMKCandidatesData.swift @@ -21,26 +21,28 @@ public extension SessionCtl { var arrResult = [String]() // 注意:下文中的不可列印字元是用來方便在 IMEState 當中用來分割資料的。 - func handleIMKCandidatesPrepared(_ candidates: [([String], String)], prefix: String = "") { + func handleIMKCandidatesPrepared( + _ candidates: [(keyArray: [String], value: String)], prefix: String = "" + ) { guard let separator = inputHandler?.keySeparator else { return } for theCandidate in candidates { - let theConverted = ChineseConverter.kanjiConversionIfRequired(theCandidate.1) - var result = (theCandidate.1 == theConverted) ? theCandidate.1 : "\(theConverted)\u{1A}(\(theCandidate.1))" + let theConverted = ChineseConverter.kanjiConversionIfRequired(theCandidate.value) + var result = (theCandidate.value == theConverted) ? theCandidate.value : "\(theConverted)\u{1A}(\(theCandidate.value))" if arrResult.contains(result) { let reading: String = PrefMgr.shared.cassetteEnabled - ? theCandidate.0.joined(separator: separator) + ? theCandidate.keyArray.joined(separator: separator) : (PrefMgr.shared.showHanyuPinyinInCompositionBuffer ? Tekkon.cnvPhonaToHanyuPinyin( targetJoined: { var arr = [String]() - theCandidate.0.forEach { key in + theCandidate.keyArray.forEach { key in arr.append(Tekkon.restoreToneOneInPhona(target: key)) } return arr.joined(separator: "-") }() ) - : theCandidate.0.joined(separator: separator)) + : theCandidate.keyArray.joined(separator: separator)) result = "\(result)\u{17}(\(reading))" } arrResult.append(prefix + result) @@ -51,11 +53,11 @@ public extension SessionCtl { handleIMKCandidatesPrepared(state.candidates, prefix: "⇧") } else if state.type == .ofSymbolTable { // 分類符號選單不會出現同符異音項、不需要康熙 / JIS 轉換,所以使用簡化過的處理方式。 - arrResult = state.candidates.map(\.1) + arrResult = state.candidates.map(\.value) } else if state.type == .ofCandidates { guard !state.candidates.isEmpty else { return .init() } - if state.candidates[0].0.contains("_punctuation") { - arrResult = state.candidates.map(\.1) // 標點符號選單處理。 + if state.candidates[0].keyArray.joined(separator: "-").contains("_punctuation") { + arrResult = state.candidates.map(\.value) // 標點符號選單處理。 } else { handleIMKCandidatesPrepared(state.candidates) } @@ -91,25 +93,29 @@ public extension SessionCtl { var indexDeducted = 0 // 注意:下文中的不可列印字元是用來方便在 IMEState 當中用來分割資料的。 - func handleIMKCandidatesSelected(_ candidates: [([String], String)], prefix: String = "") { + func handleIMKCandidatesSelected( + _ candidates: [(keyArray: [String], value: String)], prefix: String = "" + ) { guard let separator = inputHandler?.keySeparator else { return } for (i, neta) in candidates.enumerated() { - let theConverted = ChineseConverter.kanjiConversionIfRequired(neta.1) - let netaShown = (neta.1 == theConverted) ? neta.1 : "\(theConverted)\u{1A}(\(neta.1))" + let theConverted = ChineseConverter.kanjiConversionIfRequired(neta.value) + let netaShown = (neta.value == theConverted) + ? neta.value + : "\(theConverted)\u{1A}(\(neta.value))" let reading: String = PrefMgr.shared.cassetteEnabled - ? neta.0.joined(separator: separator) + ? neta.keyArray.joined(separator: separator) : (PrefMgr.shared.showHanyuPinyinInCompositionBuffer ? Tekkon.cnvPhonaToHanyuPinyin( targetJoined: { var arr = [String]() - neta.0.forEach { key in + neta.keyArray.forEach { key in arr.append(Tekkon.restoreToneOneInPhona(target: key)) } return arr.joined(separator: "-") }() ) - : neta.0.joined(separator: separator)) + : neta.keyArray.joined(separator: separator)) let netaShownWithPronunciation = "\(netaShown)\u{17}(\(reading))" if candidateString == prefix + netaShownWithPronunciation { indexDeducted = i @@ -123,9 +129,9 @@ public extension SessionCtl { } // 分類符號選單不會出現同符異音項、不需要康熙 / JIS 轉換,所以使用簡化過的處理方式。 - func handleSymbolCandidatesSelected(_ candidates: [([String], String)]) { + func handleSymbolCandidatesSelected(_ candidates: [(keyArray: [String], value: String)]) { for (i, neta) in candidates.enumerated() { - if candidateString == neta.1 { + if candidateString == neta.value { indexDeducted = i break } @@ -138,7 +144,7 @@ public extension SessionCtl { handleSymbolCandidatesSelected(state.candidates) } else if state.type == .ofCandidates { guard !state.candidates.isEmpty else { return } - if state.candidates[0].0.contains("_punctuation") { + if state.candidates[0].keyArray.description.contains("_punctuation") { handleSymbolCandidatesSelected(state.candidates) // 標點符號選單處理。 } else { handleIMKCandidatesSelected(state.candidates)