Repo // Add parameter names for ([String], String).
This commit is contained in:
parent
e6696d910d
commit
a2f5606579
|
@ -77,7 +77,7 @@ public struct CandidatePool {
|
||||||
/// - direction: 橫向排列還是縱向排列(預設情況下是縱向)。
|
/// - direction: 橫向排列還是縱向排列(預設情況下是縱向)。
|
||||||
/// - locale: 區域編碼。例:「zh-Hans」或「zh-Hant」。
|
/// - locale: 區域編碼。例:「zh-Hans」或「zh-Hant」。
|
||||||
public init(
|
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 = ""
|
layout: LayoutOrientation = .vertical, locale: String = ""
|
||||||
) {
|
) {
|
||||||
self.layout = layout
|
self.layout = layout
|
||||||
|
@ -87,7 +87,7 @@ public struct CandidatePool {
|
||||||
blankCell.locale = locale
|
blankCell.locale = locale
|
||||||
self.selectionKeys = selectionKeys.isEmpty ? "123456789" : selectionKeys
|
self.selectionKeys = selectionKeys.isEmpty ? "123456789" : selectionKeys
|
||||||
var allCandidates = candidates.map {
|
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) }
|
if allCandidates.isEmpty { allCandidates.append(blankCell) }
|
||||||
candidateDataAll = allCandidates
|
candidateDataAll = allCandidates
|
||||||
|
|
|
@ -375,7 +375,7 @@ struct VwrCandidateTDK_Previews: PreviewProvider {
|
||||||
@State static var tooltip = "📼"
|
@State static var tooltip = "📼"
|
||||||
@State static var oldOS: Bool = true
|
@State static var oldOS: Bool = true
|
||||||
|
|
||||||
static var testCandidatesConverted: [([String], String)] {
|
static var testCandidatesConverted: [(keyArray: [String], value: String)] {
|
||||||
testCandidates.map { candidate in
|
testCandidates.map { candidate in
|
||||||
let firstValue: [String] = .init(repeating: "", count: candidate.count)
|
let firstValue: [String] = .init(repeating: "", count: candidate.count)
|
||||||
return (firstValue, candidate)
|
return (firstValue, candidate)
|
||||||
|
|
|
@ -19,7 +19,7 @@ final class CandidatePoolTests: XCTestCase {
|
||||||
"嗯", "哼", "啊",
|
"嗯", "哼", "啊",
|
||||||
]
|
]
|
||||||
|
|
||||||
var testCandidatesConverted: [([String], String)] {
|
var testCandidatesConverted: [(keyArray: [String], value: String)] {
|
||||||
testCandidates.map { candidate in
|
testCandidates.map { candidate in
|
||||||
let firstValue: [String] = .init(repeating: "", count: candidate.count)
|
let firstValue: [String] = .init(repeating: "", count: candidate.count)
|
||||||
return (firstValue, candidate)
|
return (firstValue, candidate)
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
import Cocoa
|
import Cocoa
|
||||||
|
|
||||||
public protocol CtlCandidateDelegate {
|
public protocol CtlCandidateDelegate {
|
||||||
func candidatePairs(conv: Bool) -> [([String], String)]
|
func candidatePairs(conv: Bool) -> [(keyArray: [String], value: String)]
|
||||||
func candidatePairSelected(at index: Int)
|
func candidatePairSelected(at index: Int)
|
||||||
func candidatePairRightClicked(at index: Int, action: CandidateContextMenuAction)
|
func candidatePairRightClicked(at index: Int, action: CandidateContextMenuAction)
|
||||||
func candidates(_ sender: Any!) -> [Any]!
|
func candidates(_ sender: Any!) -> [Any]!
|
||||||
|
|
|
@ -104,7 +104,7 @@ public extension IMEState {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
static func ofAssociates(candidates: [([String], String)]) -> IMEState {
|
static func ofAssociates(candidates: [(keyArray: [String], value: String)]) -> IMEState {
|
||||||
var result = IMEState(type: .ofAssociates)
|
var result = IMEState(type: .ofAssociates)
|
||||||
result.candidates = candidates
|
result.candidates = candidates
|
||||||
return result
|
return result
|
||||||
|
@ -129,7 +129,7 @@ public extension IMEState {
|
||||||
return result
|
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
|
-> IMEState
|
||||||
{
|
{
|
||||||
var result = IMEState(displayTextSegments: displayTextSegments, cursor: cursor)
|
var result = IMEState(displayTextSegments: displayTextSegments, cursor: cursor)
|
||||||
|
|
|
@ -216,7 +216,7 @@ public extension IMEStateData {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
let text = pair.1
|
let text = pair.value
|
||||||
let readingDisplay = readingThreadForDisplay
|
let readingDisplay = readingThreadForDisplay
|
||||||
if markedRange.count < Self.allowedMarkLengthRange.lowerBound {
|
if markedRange.count < Self.allowedMarkLengthRange.lowerBound {
|
||||||
tooltipColorState = .denialInsufficiency
|
tooltipColorState = .denialInsufficiency
|
||||||
|
|
|
@ -34,7 +34,7 @@ public protocol InputHandlerProtocol {
|
||||||
func generateStateOfInputting(sansReading: Bool) -> IMEStateProtocol
|
func generateStateOfInputting(sansReading: Bool) -> IMEStateProtocol
|
||||||
func generateStateOfAssociates(withPair pair: Megrez.Compositor.KeyValuePaired) -> IMEStateProtocol
|
func generateStateOfAssociates(withPair pair: Megrez.Compositor.KeyValuePaired) -> IMEStateProtocol
|
||||||
func consolidateNode(
|
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
|
func updateUnigramData() -> Bool
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,7 @@ extension InputHandlerProtocol {
|
||||||
generateStateOfInputting(sansReading: sansReading)
|
generateStateOfInputting(sansReading: sansReading)
|
||||||
}
|
}
|
||||||
|
|
||||||
func consolidateNode(candidate: ([String], String), respectCursorPushing: Bool, preConsolidate: Bool) {
|
func consolidateNode(candidate: (keyArray: [String], value: String), respectCursorPushing: Bool, preConsolidate: Bool) {
|
||||||
consolidateNode(
|
consolidateNode(
|
||||||
candidate: candidate, respectCursorPushing: respectCursorPushing,
|
candidate: candidate, respectCursorPushing: respectCursorPushing,
|
||||||
preConsolidate: preConsolidate, skipObservation: false
|
preConsolidate: preConsolidate, skipObservation: false
|
||||||
|
@ -196,8 +196,8 @@ public class InputHandler: InputHandlerProtocol {
|
||||||
/// - Parameter key: 給定的聯想詞的開頭字。
|
/// - Parameter key: 給定的聯想詞的開頭字。
|
||||||
/// - Returns: 抓取到的聯想詞陣列。
|
/// - Returns: 抓取到的聯想詞陣列。
|
||||||
/// 不會是 nil,但那些負責接收結果的函式會對空白陣列結果做出正確的處理。
|
/// 不會是 nil,但那些負責接收結果的函式會對空白陣列結果做出正確的處理。
|
||||||
func generateArrayOfAssociates(withPair pair: Megrez.Compositor.KeyValuePaired) -> [([String], String)] {
|
func generateArrayOfAssociates(withPair pair: Megrez.Compositor.KeyValuePaired) -> [(keyArray: [String], value: String)] {
|
||||||
var arrResult: [([String], String)] = []
|
var arrResult: [(keyArray: [String], value: String)] = []
|
||||||
if currentLM.hasAssociatedPhrasesFor(pair: pair) {
|
if currentLM.hasAssociatedPhrasesFor(pair: pair) {
|
||||||
arrResult = currentLM.associatedPhrasesFor(pair: pair).map { ([""], $0) }
|
arrResult = currentLM.associatedPhrasesFor(pair: pair).map { ([""], $0) }
|
||||||
}
|
}
|
||||||
|
@ -299,10 +299,12 @@ public class InputHandler: InputHandlerProtocol {
|
||||||
/// - preConsolidate: 在固化節點之前,先鞏固上下文。該選項可能會破壞在內文組字區內就地輪替候選字詞時的體驗。
|
/// - preConsolidate: 在固化節點之前,先鞏固上下文。該選項可能會破壞在內文組字區內就地輪替候選字詞時的體驗。
|
||||||
/// - skipObservation: 不要讓半衰記憶模組對此做出觀察。
|
/// - skipObservation: 不要讓半衰記憶模組對此做出觀察。
|
||||||
public func consolidateNode(
|
public func consolidateNode(
|
||||||
candidate: ([String], String), respectCursorPushing: Bool = true,
|
candidate: (keyArray: [String], value: String), respectCursorPushing: Bool = true,
|
||||||
preConsolidate: Bool = false, skipObservation: Bool = false
|
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) }
|
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 內建注音輸入法不一致。
|
/// 警告:不要對游標前置風格使用 nodesCrossing,否則會導致游標行為與 macOS 內建注音輸入法不一致。
|
||||||
/// 微軟新注音輸入法的游標後置風格也是不允許 nodeCrossing 的。
|
/// 微軟新注音輸入法的游標後置風格也是不允許 nodeCrossing 的。
|
||||||
var arrCandidates: [Megrez.Compositor.KeyValuePaired] = {
|
var arrCandidates: [Megrez.Compositor.KeyValuePaired] = {
|
||||||
|
|
|
@ -143,12 +143,12 @@ extension InputHandler {
|
||||||
case 2...: delegate.switchState(candidateState)
|
case 2...: delegate.switchState(candidateState)
|
||||||
case 1:
|
case 1:
|
||||||
let firstCandidate = candidateState.candidates.first! // 一定會有,所以強制拆包也無妨。
|
let firstCandidate = candidateState.candidates.first! // 一定會有,所以強制拆包也無妨。
|
||||||
let reading: String = firstCandidate.0.joined(separator: compositor.separator)
|
let reading: [String] = firstCandidate.keyArray
|
||||||
let text: String = firstCandidate.1
|
let text: String = firstCandidate.value
|
||||||
delegate.switchState(IMEState.ofCommitting(textToCommit: text))
|
delegate.switchState(IMEState.ofCommitting(textToCommit: text))
|
||||||
|
|
||||||
if prefs.associatedPhrasesEnabled {
|
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)
|
delegate.switchState(associatedPhrases.candidates.isEmpty ? IMEState.ofEmpty() : associatedPhrases)
|
||||||
}
|
}
|
||||||
default: break
|
default: break
|
||||||
|
@ -285,7 +285,7 @@ extension InputHandler {
|
||||||
case 1:
|
case 1:
|
||||||
let firstCandidate = candidateState.candidates.first! // 一定會有,所以強制拆包也無妨。
|
let firstCandidate = candidateState.candidates.first! // 一定會有,所以強制拆包也無妨。
|
||||||
let reading: String = firstCandidate.0.joined(separator: compositor.separator)
|
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))
|
delegate.switchState(IMEState.ofCommitting(textToCommit: text))
|
||||||
|
|
||||||
if prefs.associatedPhrasesEnabled {
|
if prefs.associatedPhrasesEnabled {
|
||||||
|
|
|
@ -275,8 +275,8 @@ extension InputHandler {
|
||||||
case 2...: delegate.switchState(candidateState)
|
case 2...: delegate.switchState(candidateState)
|
||||||
case 1:
|
case 1:
|
||||||
clear() // 這句不要砍,因為下文可能會回呼 candidateState。
|
clear() // 這句不要砍,因為下文可能會回呼 candidateState。
|
||||||
if let candidateToCommit: ([String], String) = candidateState.candidates.first, !candidateToCommit.1.isEmpty {
|
if let strToCommit = candidateState.candidates.first?.value, !strToCommit.isEmpty {
|
||||||
delegate.switchState(IMEState.ofCommitting(textToCommit: candidateToCommit.1))
|
delegate.switchState(IMEState.ofCommitting(textToCommit: strToCommit))
|
||||||
} else {
|
} else {
|
||||||
delegate.switchState(candidateState)
|
delegate.switchState(candidateState)
|
||||||
}
|
}
|
||||||
|
@ -813,7 +813,7 @@ extension InputHandler {
|
||||||
var newState = generateStateOfInputting()
|
var newState = generateStateOfInputting()
|
||||||
let locID = Bundle.main.preferredLocalizations[0]
|
let locID = Bundle.main.preferredLocalizations[0]
|
||||||
let newTooltip = NSMutableString()
|
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" {
|
if #available(macOS 10.13, *), isContextVertical(), locID != "en" {
|
||||||
newTooltip.insert((newIndex + 1).i18n(loc: locID) + "・" + candidates.count.i18n(loc: locID), at: 0)
|
newTooltip.insert((newIndex + 1).i18n(loc: locID) + "・" + candidates.count.i18n(loc: locID), at: 0)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -95,16 +95,15 @@ extension SessionCtl: CtlCandidateDelegate {
|
||||||
PrefMgr.shared.useIMKCandidateWindow ? "123456789" : PrefMgr.shared.candidateKeys
|
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 !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
|
return state.candidates
|
||||||
}
|
}
|
||||||
let convertedCandidates: [([String], String)] = state.candidates.map { theCandidatePair -> ([String], String) in
|
let convertedCandidates = state.candidates.map { theCandidatePair -> (keyArray: [String], value: String) in
|
||||||
let theCandidate = theCandidatePair.1
|
var theCandidatePair = theCandidatePair
|
||||||
let theConverted = ChineseConverter.kanjiConversionIfRequired(theCandidate)
|
theCandidatePair.value = ChineseConverter.kanjiConversionIfRequired(theCandidatePair.value)
|
||||||
let result = (theCandidate == theConverted) ? theCandidate : "\(theConverted)(\(theCandidate))"
|
return theCandidatePair
|
||||||
return (theCandidatePair.0, result)
|
|
||||||
}
|
}
|
||||||
return convertedCandidates
|
return convertedCandidates
|
||||||
}
|
}
|
||||||
|
@ -136,10 +135,10 @@ extension SessionCtl: CtlCandidateDelegate {
|
||||||
|
|
||||||
if PrefMgr.shared.useSCPCTypingMode {
|
if PrefMgr.shared.useSCPCTypingMode {
|
||||||
switchState(IMEState.ofCommitting(textToCommit: inputting.displayedText))
|
switchState(IMEState.ofCommitting(textToCommit: inputting.displayedText))
|
||||||
// 此時是逐字選字模式,所以「selectedValue.1」是單個字、不用追加處理。
|
// 此時是逐字選字模式,所以「selectedValue.value」是單個字、不用追加處理。
|
||||||
if PrefMgr.shared.associatedPhrasesEnabled {
|
if PrefMgr.shared.associatedPhrasesEnabled {
|
||||||
let associates = inputHandler.generateStateOfAssociates(
|
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)
|
switchState(associates.candidates.isEmpty ? IMEState.ofEmpty() : associates)
|
||||||
} else {
|
} else {
|
||||||
|
@ -153,16 +152,16 @@ extension SessionCtl: CtlCandidateDelegate {
|
||||||
|
|
||||||
if state.type == .ofAssociates {
|
if state.type == .ofAssociates {
|
||||||
let selectedValue = state.candidates[index]
|
let selectedValue = state.candidates[index]
|
||||||
switchState(IMEState.ofCommitting(textToCommit: selectedValue.1))
|
switchState(IMEState.ofCommitting(textToCommit: selectedValue.value))
|
||||||
// 此時是聯想詞選字模式,所以「selectedValue.1」必須只保留最後一個字。
|
// 此時是聯想詞選字模式,所以「selectedValue.value」必須只保留最後一個字。
|
||||||
// 不然的話,一旦你選中了由多個字組成的聯想候選詞,則連續聯想會被打斷。
|
// 不然的話,一旦你選中了由多個字組成的聯想候選詞,則連續聯想會被打斷。
|
||||||
guard let valueKept = selectedValue.1.last else {
|
guard let valueKept = selectedValue.value.last else {
|
||||||
switchState(IMEState.ofEmpty())
|
switchState(IMEState.ofEmpty())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if PrefMgr.shared.associatedPhrasesEnabled {
|
if PrefMgr.shared.associatedPhrasesEnabled {
|
||||||
let associates = inputHandler.generateStateOfAssociates(
|
let associates = inputHandler.generateStateOfAssociates(
|
||||||
withPair: .init(keyArray: selectedValue.0, value: String(valueKept))
|
withPair: .init(keyArray: selectedValue.keyArray, value: String(valueKept))
|
||||||
)
|
)
|
||||||
if !associates.candidates.isEmpty {
|
if !associates.candidates.isEmpty {
|
||||||
switchState(associates)
|
switchState(associates)
|
||||||
|
|
|
@ -21,26 +21,28 @@ public extension SessionCtl {
|
||||||
var arrResult = [String]()
|
var arrResult = [String]()
|
||||||
|
|
||||||
// 注意:下文中的不可列印字元是用來方便在 IMEState 當中用來分割資料的。
|
// 注意:下文中的不可列印字元是用來方便在 IMEState 當中用來分割資料的。
|
||||||
func handleIMKCandidatesPrepared(_ candidates: [([String], String)], prefix: String = "") {
|
func handleIMKCandidatesPrepared(
|
||||||
|
_ candidates: [(keyArray: [String], value: String)], prefix: String = ""
|
||||||
|
) {
|
||||||
guard let separator = inputHandler?.keySeparator else { return }
|
guard let separator = inputHandler?.keySeparator else { return }
|
||||||
for theCandidate in candidates {
|
for theCandidate in candidates {
|
||||||
let theConverted = ChineseConverter.kanjiConversionIfRequired(theCandidate.1)
|
let theConverted = ChineseConverter.kanjiConversionIfRequired(theCandidate.value)
|
||||||
var result = (theCandidate.1 == theConverted) ? theCandidate.1 : "\(theConverted)\u{1A}(\(theCandidate.1))"
|
var result = (theCandidate.value == theConverted) ? theCandidate.value : "\(theConverted)\u{1A}(\(theCandidate.value))"
|
||||||
if arrResult.contains(result) {
|
if arrResult.contains(result) {
|
||||||
let reading: String =
|
let reading: String =
|
||||||
PrefMgr.shared.cassetteEnabled
|
PrefMgr.shared.cassetteEnabled
|
||||||
? theCandidate.0.joined(separator: separator)
|
? theCandidate.keyArray.joined(separator: separator)
|
||||||
: (PrefMgr.shared.showHanyuPinyinInCompositionBuffer
|
: (PrefMgr.shared.showHanyuPinyinInCompositionBuffer
|
||||||
? Tekkon.cnvPhonaToHanyuPinyin(
|
? Tekkon.cnvPhonaToHanyuPinyin(
|
||||||
targetJoined: {
|
targetJoined: {
|
||||||
var arr = [String]()
|
var arr = [String]()
|
||||||
theCandidate.0.forEach { key in
|
theCandidate.keyArray.forEach { key in
|
||||||
arr.append(Tekkon.restoreToneOneInPhona(target: key))
|
arr.append(Tekkon.restoreToneOneInPhona(target: key))
|
||||||
}
|
}
|
||||||
return arr.joined(separator: "-")
|
return arr.joined(separator: "-")
|
||||||
}()
|
}()
|
||||||
)
|
)
|
||||||
: theCandidate.0.joined(separator: separator))
|
: theCandidate.keyArray.joined(separator: separator))
|
||||||
result = "\(result)\u{17}(\(reading))"
|
result = "\(result)\u{17}(\(reading))"
|
||||||
}
|
}
|
||||||
arrResult.append(prefix + result)
|
arrResult.append(prefix + result)
|
||||||
|
@ -51,11 +53,11 @@ public extension SessionCtl {
|
||||||
handleIMKCandidatesPrepared(state.candidates, prefix: "⇧")
|
handleIMKCandidatesPrepared(state.candidates, prefix: "⇧")
|
||||||
} else if state.type == .ofSymbolTable {
|
} else if state.type == .ofSymbolTable {
|
||||||
// 分類符號選單不會出現同符異音項、不需要康熙 / JIS 轉換,所以使用簡化過的處理方式。
|
// 分類符號選單不會出現同符異音項、不需要康熙 / JIS 轉換,所以使用簡化過的處理方式。
|
||||||
arrResult = state.candidates.map(\.1)
|
arrResult = state.candidates.map(\.value)
|
||||||
} else if state.type == .ofCandidates {
|
} else if state.type == .ofCandidates {
|
||||||
guard !state.candidates.isEmpty else { return .init() }
|
guard !state.candidates.isEmpty else { return .init() }
|
||||||
if state.candidates[0].0.contains("_punctuation") {
|
if state.candidates[0].keyArray.joined(separator: "-").contains("_punctuation") {
|
||||||
arrResult = state.candidates.map(\.1) // 標點符號選單處理。
|
arrResult = state.candidates.map(\.value) // 標點符號選單處理。
|
||||||
} else {
|
} else {
|
||||||
handleIMKCandidatesPrepared(state.candidates)
|
handleIMKCandidatesPrepared(state.candidates)
|
||||||
}
|
}
|
||||||
|
@ -91,25 +93,29 @@ public extension SessionCtl {
|
||||||
var indexDeducted = 0
|
var indexDeducted = 0
|
||||||
|
|
||||||
// 注意:下文中的不可列印字元是用來方便在 IMEState 當中用來分割資料的。
|
// 注意:下文中的不可列印字元是用來方便在 IMEState 當中用來分割資料的。
|
||||||
func handleIMKCandidatesSelected(_ candidates: [([String], String)], prefix: String = "") {
|
func handleIMKCandidatesSelected(
|
||||||
|
_ candidates: [(keyArray: [String], value: String)], prefix: String = ""
|
||||||
|
) {
|
||||||
guard let separator = inputHandler?.keySeparator else { return }
|
guard let separator = inputHandler?.keySeparator else { return }
|
||||||
for (i, neta) in candidates.enumerated() {
|
for (i, neta) in candidates.enumerated() {
|
||||||
let theConverted = ChineseConverter.kanjiConversionIfRequired(neta.1)
|
let theConverted = ChineseConverter.kanjiConversionIfRequired(neta.value)
|
||||||
let netaShown = (neta.1 == theConverted) ? neta.1 : "\(theConverted)\u{1A}(\(neta.1))"
|
let netaShown = (neta.value == theConverted)
|
||||||
|
? neta.value
|
||||||
|
: "\(theConverted)\u{1A}(\(neta.value))"
|
||||||
let reading: String =
|
let reading: String =
|
||||||
PrefMgr.shared.cassetteEnabled
|
PrefMgr.shared.cassetteEnabled
|
||||||
? neta.0.joined(separator: separator)
|
? neta.keyArray.joined(separator: separator)
|
||||||
: (PrefMgr.shared.showHanyuPinyinInCompositionBuffer
|
: (PrefMgr.shared.showHanyuPinyinInCompositionBuffer
|
||||||
? Tekkon.cnvPhonaToHanyuPinyin(
|
? Tekkon.cnvPhonaToHanyuPinyin(
|
||||||
targetJoined: {
|
targetJoined: {
|
||||||
var arr = [String]()
|
var arr = [String]()
|
||||||
neta.0.forEach { key in
|
neta.keyArray.forEach { key in
|
||||||
arr.append(Tekkon.restoreToneOneInPhona(target: key))
|
arr.append(Tekkon.restoreToneOneInPhona(target: key))
|
||||||
}
|
}
|
||||||
return arr.joined(separator: "-")
|
return arr.joined(separator: "-")
|
||||||
}()
|
}()
|
||||||
)
|
)
|
||||||
: neta.0.joined(separator: separator))
|
: neta.keyArray.joined(separator: separator))
|
||||||
let netaShownWithPronunciation = "\(netaShown)\u{17}(\(reading))"
|
let netaShownWithPronunciation = "\(netaShown)\u{17}(\(reading))"
|
||||||
if candidateString == prefix + netaShownWithPronunciation {
|
if candidateString == prefix + netaShownWithPronunciation {
|
||||||
indexDeducted = i
|
indexDeducted = i
|
||||||
|
@ -123,9 +129,9 @@ public extension SessionCtl {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 分類符號選單不會出現同符異音項、不需要康熙 / JIS 轉換,所以使用簡化過的處理方式。
|
// 分類符號選單不會出現同符異音項、不需要康熙 / JIS 轉換,所以使用簡化過的處理方式。
|
||||||
func handleSymbolCandidatesSelected(_ candidates: [([String], String)]) {
|
func handleSymbolCandidatesSelected(_ candidates: [(keyArray: [String], value: String)]) {
|
||||||
for (i, neta) in candidates.enumerated() {
|
for (i, neta) in candidates.enumerated() {
|
||||||
if candidateString == neta.1 {
|
if candidateString == neta.value {
|
||||||
indexDeducted = i
|
indexDeducted = i
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -138,7 +144,7 @@ public extension SessionCtl {
|
||||||
handleSymbolCandidatesSelected(state.candidates)
|
handleSymbolCandidatesSelected(state.candidates)
|
||||||
} else if state.type == .ofCandidates {
|
} else if state.type == .ofCandidates {
|
||||||
guard !state.candidates.isEmpty else { return }
|
guard !state.candidates.isEmpty else { return }
|
||||||
if state.candidates[0].0.contains("_punctuation") {
|
if state.candidates[0].keyArray.description.contains("_punctuation") {
|
||||||
handleSymbolCandidatesSelected(state.candidates) // 標點符號選單處理。
|
handleSymbolCandidatesSelected(state.candidates) // 標點符號選單處理。
|
||||||
} else {
|
} else {
|
||||||
handleIMKCandidatesSelected(state.candidates)
|
handleIMKCandidatesSelected(state.candidates)
|
||||||
|
|
Loading…
Reference in New Issue