From 9a999f1e664d76f1d897e498739ebab8ca523add Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Fri, 22 Jul 2022 13:39:06 +0800 Subject: [PATCH 01/15] KeyHandler // Comment fix. --- Source/Modules/ControllerModules/KeyHandler_Core.swift | 4 ++-- Source/Modules/ControllerModules/KeyHandler_States.swift | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Source/Modules/ControllerModules/KeyHandler_Core.swift b/Source/Modules/ControllerModules/KeyHandler_Core.swift index 5ab32f12..020192ef 100644 --- a/Source/Modules/ControllerModules/KeyHandler_Core.swift +++ b/Source/Modules/ControllerModules/KeyHandler_Core.swift @@ -161,7 +161,7 @@ class KeyHandler { /// 然後再將對應的節錨內的節點標記為「已經手動選字過」。 /// - Parameters: /// - value: 給定之候選字字串。 - /// - respectCursorPushing: 若該選項為 true,則會在選字之後始終將游標推送至選字厚的節錨的前方。 + /// - respectCursorPushing: 若該選項為 true,則會在選字之後始終將游標推送至選字後的節錨的前方。 func fixNode(candidate: (String, String), respectCursorPushing: Bool = true) { let theCandidate: Megrez.KeyValuePaired = .init(key: candidate.0, value: candidate.1) let adjustedCursor = max(0, min(actualCandidateCursor + (mgrPrefs.useRearCursorMode ? 1 : 0), compositorLength)) @@ -196,7 +196,7 @@ class KeyHandler { // 開始爬軌。 walk() - /// 若偏好設定內啟用了相關選項,則會在選字之後始終將游標推送至選字厚的節錨的前方。 + /// 若偏好設定內啟用了相關選項,則會在選字之後始終將游標推送至選字後的節錨的前方。 if mgrPrefs.moveCursorAfterSelectingCandidate, respectCursorPushing { compositor.jumpCursorBySpan(to: .front) } diff --git a/Source/Modules/ControllerModules/KeyHandler_States.swift b/Source/Modules/ControllerModules/KeyHandler_States.swift index bc45cb13..4f04c98f 100644 --- a/Source/Modules/ControllerModules/KeyHandler_States.swift +++ b/Source/Modules/ControllerModules/KeyHandler_States.swift @@ -817,7 +817,8 @@ extension KeyHandler { /// 讀音組成的雙字詞的權重、導致這個雙字詞並未在爬軌時被自動 /// 選中的話,則使用者可以直接摁下本函式對應的按鍵來輪替候選字即可。 /// (預設情況下是 (Shift+)Tab 來做正 (反) 向切換,但也可以用 - /// Shift(+CMD)+Space 來切換、以應對臉書綁架 Tab 鍵的情況。 + /// Shift(+CMD)+Space 或 Alt+↑/↓ 來切換(縱排輸入時則是 Alt+←/→)、 + /// 以應對臉書綁架 Tab 鍵的情況。 if candidates[0].0 == currentPaired.key, candidates[0].1 == currentPaired.value { /// 如果第一個候選字詞是當前節點的候選字詞的值的話, /// 那就切到下一個(或上一個,也就是最後一個)候選字詞。 From 9402c36bf9aabc632256c9a66c7c3f599bf83766 Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Fri, 22 Jul 2022 11:31:14 +0800 Subject: [PATCH 02/15] InputSignal // Comment that Fn+Enter is already supported. --- Source/Modules/ControllerModules/InputSignal.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Modules/ControllerModules/InputSignal.swift b/Source/Modules/ControllerModules/InputSignal.swift index d53866bd..4bf8309a 100644 --- a/Source/Modules/ControllerModules/InputSignal.swift +++ b/Source/Modules/ControllerModules/InputSignal.swift @@ -50,7 +50,7 @@ enum KeyCode: UInt16 { case kVolumeUp = 72 case kVolumeDown = 73 case kMute = 74 - case kLineFeed = 76 // Another keyCode to identify the Enter Key. + case kLineFeed = 76 // Another keyCode to identify the Enter Key, typable by Fn+Enter. case kF18 = 79 case kF19 = 80 case kF20 = 90 From f03a641882673dd3f1e6a5cca0fc9a629e2485f7 Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Fri, 22 Jul 2022 11:52:07 +0800 Subject: [PATCH 03/15] UnitTests // Sync changes from LMAssociates. --- vChewingTests/KeyHandlerTestsSCPCCHT.swift | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/vChewingTests/KeyHandlerTestsSCPCCHT.swift b/vChewingTests/KeyHandlerTestsSCPCCHT.swift index 25cb3747..5753ccd2 100644 --- a/vChewingTests/KeyHandlerTestsSCPCCHT.swift +++ b/vChewingTests/KeyHandlerTestsSCPCCHT.swift @@ -357,13 +357,15 @@ extension String { extension vChewing.LMAssociates { public mutating func forceOpenStringInstead(_ strData: String) { - strData.ranges(splitBy: "\n").forEach { + strData.ranges(splitBy: "\n").filter({ !$0.isEmpty }).forEach { let neta = strData[$0].split(separator: " ") if neta.count >= 2 { let theKey = String(neta[0]) - if !neta[0].isEmpty, !neta[1].isEmpty, theKey.first != "#" { - let theValue = $0 - rangeMap[theKey, default: []].append(theValue) + if !theKey.isEmpty, theKey.first != "#" { + for (i, _) in neta.filter({ $0.first != "#" && !$0.isEmpty }).enumerated() { + if i == 0 { continue } + rangeMap[theKey, default: []].append(($0, i)) + } } } } From 8c4f94584b2b769a49453d592595c279c828cefc Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Fri, 22 Jul 2022 10:11:22 +0800 Subject: [PATCH 04/15] AUTHORS // InputHandler -> InputSignal. --- AUTHORS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AUTHORS b/AUTHORS index e7f7fa63..f8dfe3a6 100644 --- a/AUTHORS +++ b/AUTHORS @@ -16,7 +16,7 @@ $ Contributors and volunteers of the upstream repo, having no responsibility in - Zonble Yang: - McBopomofo for macOS 2.x architect, especially state-based IME behavior management. - Voltaire candidate window MK2 (massively modified as MK3 in vChewing by Shiki Suen). - - InputHandler. + - InputSignal (previously "KeyHandlerInput"). - Notifier window and Tooltip UI. - NSStringUtils and FSEventStreamHelper. - App-style installer (only preserved for developer purposes). From ab8f7fe7a2da061a14d61ba4a7a6544bac745207 Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Fri, 22 Jul 2022 11:10:27 +0800 Subject: [PATCH 05/15] KeyHandler_Core // Format fix. --- Source/Modules/ControllerModules/KeyHandler_Core.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Modules/ControllerModules/KeyHandler_Core.swift b/Source/Modules/ControllerModules/KeyHandler_Core.swift index 020192ef..cec71c10 100644 --- a/Source/Modules/ControllerModules/KeyHandler_Core.swift +++ b/Source/Modules/ControllerModules/KeyHandler_Core.swift @@ -288,7 +288,7 @@ class KeyHandler { /// - epsilon: 半衰模組的衰減指數。 /// - Returns: 尋獲的最高權重數值。 func findHighestScore(nodeAnchors: [Megrez.NodeAnchor], epsilon: Double) -> Double { - return nodeAnchors.map(\.node.highestUnigramScore).max() ?? 0 + epsilon + nodeAnchors.map(\.node.highestUnigramScore).max() ?? 0 + epsilon } // MARK: - Extracted methods and functions (Tekkon). From cd2baf2c4f9a3ab85da7aafb0a98852ac991c186 Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Fri, 22 Jul 2022 12:50:56 +0800 Subject: [PATCH 06/15] KeyHandler // Fix a condition for handling AbsorbedArrowKey. --- Source/Modules/ControllerModules/KeyHandler_HandleInput.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Modules/ControllerModules/KeyHandler_HandleInput.swift b/Source/Modules/ControllerModules/KeyHandler_HandleInput.swift index db5a6e62..f7c0cd59 100644 --- a/Source/Modules/ControllerModules/KeyHandler_HandleInput.swift +++ b/Source/Modules/ControllerModules/KeyHandler_HandleInput.swift @@ -354,7 +354,7 @@ extension KeyHandler { // MARK: AbsorbedArrowKey if input.isAbsorbedArrowKey || input.isExtraChooseCandidateKey || input.isExtraChooseCandidateKeyReverse { - if input.isOptionHold, state.type == .ofInputting { + if input.isOptionHold, state is InputState.Inputting { if input.isExtraChooseCandidateKey { return handleInlineCandidateRotation( state: state, reverseModifier: false, stateCallback: stateCallback, errorCallback: errorCallback From f5470752283b214dbc217fe3636dd2c10713a047 Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Fri, 22 Jul 2022 14:34:21 +0800 Subject: [PATCH 07/15] KeyHandler // Tweaking buildInputtingState(). --- Source/Modules/ControllerModules/KeyHandler_States.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Modules/ControllerModules/KeyHandler_States.swift b/Source/Modules/ControllerModules/KeyHandler_States.swift index 4f04c98f..60268fcc 100644 --- a/Source/Modules/ControllerModules/KeyHandler_States.swift +++ b/Source/Modules/ControllerModules/KeyHandler_States.swift @@ -77,7 +77,7 @@ extension KeyHandler { /// 這裡先計算一下要用在工具提示當中的顯示參數的內容。 switch compositorCursorIndex { case compositor.readings.count...: - tooltipParameterRef[0] = compositor.readings[compositor.readings.count - 1] + tooltipParameterRef[0] = compositor.readings[compositorCursorIndex - 1] case 0: tooltipParameterRef[1] = compositor.readings[compositorCursorIndex] default: From 905d6481096b5431fb5a4c594d423e8135214e27 Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Fri, 22 Jul 2022 15:35:29 +0800 Subject: [PATCH 08/15] Repo // Warn about ununsed symbols. --- vChewing.xcodeproj/project.pbxproj | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/vChewing.xcodeproj/project.pbxproj b/vChewing.xcodeproj/project.pbxproj index 1b14118b..31ec6b36 100644 --- a/vChewing.xcodeproj/project.pbxproj +++ b/vChewing.xcodeproj/project.pbxproj @@ -1575,6 +1575,8 @@ GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_LABEL = YES; + GCC_WARN_UNUSED_PARAMETER = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11.5; ONLY_ACTIVE_ARCH = YES; @@ -1616,6 +1618,8 @@ GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_LABEL = YES; + GCC_WARN_UNUSED_PARAMETER = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11.5; OTHER_CPLUSPLUSFLAGS = ( @@ -1665,9 +1669,6 @@ GCC_WARN_SHADOW = YES; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_LABEL = YES; - GCC_WARN_UNUSED_VARIABLE = YES; INFOPLIST_FILE = "Source/Resources/IME-Info.plist"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", @@ -1717,9 +1718,6 @@ GCC_WARN_SHADOW = YES; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_LABEL = YES; - GCC_WARN_UNUSED_VARIABLE = YES; INFOPLIST_FILE = "Source/Resources/IME-Info.plist"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", @@ -1762,7 +1760,6 @@ GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_VARIABLE = YES; INFOPLIST_FILE = "Installer/Installer-Info.plist"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", @@ -1799,7 +1796,6 @@ GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_VARIABLE = YES; INFOPLIST_FILE = "Installer/Installer-Info.plist"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", From 73e072ae540e6b64fd2b73d83ceb861d800f4fc1 Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Fri, 22 Jul 2022 14:44:10 +0800 Subject: [PATCH 09/15] KeyHandler // -keyLengthAtCurrentIndex. --- Source/Modules/ControllerModules/KeyHandler_Core.swift | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Source/Modules/ControllerModules/KeyHandler_Core.swift b/Source/Modules/ControllerModules/KeyHandler_Core.swift index cec71c10..c1cc127c 100644 --- a/Source/Modules/ControllerModules/KeyHandler_Core.swift +++ b/Source/Modules/ControllerModules/KeyHandler_Core.swift @@ -400,12 +400,6 @@ class KeyHandler { compositor.dropReading(direction: .front) } - /// 獲取指定游標位置的鍵值長度。 - /// - Returns: 指定游標位置的鍵值長度。 - var keyLengthAtCurrentIndex: Int { - walkedAnchors[compositorCursorIndex].node.key.split(separator: "-").count - } - var nextPhrasePosition: Int { var nextPosition = 0 for theAnchor in walkedAnchors { From 7dceb5e53346b00da41f46252d646e527ceaa4d3 Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Fri, 22 Jul 2022 15:57:39 +0800 Subject: [PATCH 10/15] KeyHandler // -nextPhrasePosition. --- Source/Modules/ControllerModules/KeyHandler_Core.swift | 9 --------- 1 file changed, 9 deletions(-) diff --git a/Source/Modules/ControllerModules/KeyHandler_Core.swift b/Source/Modules/ControllerModules/KeyHandler_Core.swift index c1cc127c..aa85b107 100644 --- a/Source/Modules/ControllerModules/KeyHandler_Core.swift +++ b/Source/Modules/ControllerModules/KeyHandler_Core.swift @@ -400,15 +400,6 @@ class KeyHandler { compositor.dropReading(direction: .front) } - var nextPhrasePosition: Int { - var nextPosition = 0 - for theAnchor in walkedAnchors { - if nextPosition > actualCandidateCursor { break } - nextPosition += theAnchor.spanLength - } - return min(nextPosition, compositorLength) - } - /// 生成標點符號索引鍵。 /// - Parameter input: 輸入的按鍵訊號。 /// - Returns: 生成的標點符號索引鍵。 From 042f96d73d567973226f30cdc63cd1c7b258b384 Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Fri, 22 Jul 2022 16:03:46 +0800 Subject: [PATCH 11/15] KeyHandler // Reduce useless symbols. --- .../ControllerModules/KeyHandler_Core.swift | 49 ++--------------- .../KeyHandler_HandleCandidate.swift | 10 ++-- .../KeyHandler_HandleInput.swift | 14 ++--- .../ControllerModules/KeyHandler_States.swift | 54 +++++++++---------- 4 files changed, 43 insertions(+), 84 deletions(-) diff --git a/Source/Modules/ControllerModules/KeyHandler_Core.swift b/Source/Modules/ControllerModules/KeyHandler_Core.swift index aa85b107..d1147792 100644 --- a/Source/Modules/ControllerModules/KeyHandler_Core.swift +++ b/Source/Modules/ControllerModules/KeyHandler_Core.swift @@ -103,7 +103,7 @@ class KeyHandler { /// /// 威注音對游標前置與游標後置模式採取的候選字節點陣列抓取方法是分離的,且不使用 Node Crossing。 var actualCandidateCursor: Int { - mgrPrefs.useRearCursorMode ? min(compositorCursorIndex, compositorLength - 1) : max(compositorCursorIndex, 1) + mgrPrefs.useRearCursorMode ? min(compositor.cursor, compositor.length - 1) : max(compositor.cursor, 1) } /// 利用給定的讀音鏈來試圖爬取最接近的組字結果(最大相似度估算)。 @@ -164,7 +164,7 @@ class KeyHandler { /// - respectCursorPushing: 若該選項為 true,則會在選字之後始終將游標推送至選字後的節錨的前方。 func fixNode(candidate: (String, String), respectCursorPushing: Bool = true) { let theCandidate: Megrez.KeyValuePaired = .init(key: candidate.0, value: candidate.1) - let adjustedCursor = max(0, min(actualCandidateCursor + (mgrPrefs.useRearCursorMode ? 1 : 0), compositorLength)) + let adjustedCursor = max(0, min(actualCandidateCursor + (mgrPrefs.useRearCursorMode ? 1 : 0), compositor.length)) // 開始讓半衰模組觀察目前的狀況。 let selectedNode: Megrez.NodeAnchor = compositor.fixNodeWithCandidate(theCandidate, at: adjustedCursor) // 不要針對逐字選字模式啟用臨時半衰記憶模型。 @@ -254,7 +254,7 @@ class KeyHandler { /// 向半衰引擎詢問可能的選字建議。拿到的結果會是一個單元圖陣列。 func fetchSuggestedCandidates() -> [Megrez.Unigram] { currentUOM.suggest( - walkedAnchors: walkedAnchors, cursorIndex: compositorCursorIndex, + walkedAnchors: walkedAnchors, cursorIndex: compositor.cursor, timestamp: NSDate().timeIntervalSince1970 ) } @@ -273,7 +273,7 @@ class KeyHandler { IME.prtDebugIntel( "UOM: Suggestion retrieved, overriding the node score of the selected candidate.") compositor.overrideNodeScoreForSelectedCandidate( - location: min(actualCandidateCursor + (mgrPrefs.useRearCursorMode ? 1 : 0), compositorLength), + location: min(actualCandidateCursor + (mgrPrefs.useRearCursorMode ? 1 : 0), compositor.length), value: overrideValue, overridingScore: findHighestScore(nodeAnchors: rawAnchorsOfNodes, epsilon: kEpsilon) ) @@ -337,9 +337,6 @@ class KeyHandler { // MARK: - Extracted methods and functions (Megrez). - /// 組字器是否為空。 - var isCompositorEmpty: Bool { compositor.isEmpty } - /// 獲取原始節錨資料陣列。 var rawAnchorsOfNodes: [Megrez.NodeAnchor] { /// 警告:不要對游標前置風格使用 nodesCrossing,否則會導致游標行為與 macOS 內建注音輸入法不一致。 @@ -362,44 +359,6 @@ class KeyHandler { compositor = Megrez.Compositor(lm: currentLM, separator: "-") } - /// 自組字器獲取目前的讀音陣列。 - var currentReadings: [String] { compositor.readings } - - /// 以給定的(讀音)索引鍵,來檢測當前主語言模型內是否有對應的資料在庫。 - func ifLangModelHasUnigrams(forKey reading: String) -> Bool { - currentLM.hasUnigramsFor(key: reading) - } - - /// 在組字器的給定游標位置內插入讀音。 - func insertToCompositorAtCursor(reading: String) { - compositor.insertReading(reading) - } - - /// 組字器的游標位置。 - var compositorCursorIndex: Int { - get { compositor.cursor } - set { compositor.cursor = newValue } - } - - /// 組字器的目前的長度。 - var compositorLength: Int { - compositor.length - } - - /// 在組字器內,朝著與文字輸入方向相反的方向、砍掉一個與游標相鄰的讀音。 - /// - /// 在威注音的術語體系當中,「與文字輸入方向相反的方向」為向後(Rear)。 - func deleteCompositorReadingAtTheRearOfCursor() { - compositor.dropReading(direction: .rear) - } - - /// 在組字器內,朝著往文字輸入方向、砍掉一個與游標相鄰的讀音。 - /// - /// 在威注音的術語體系當中,「文字輸入方向」為向前(Front)。 - func deleteCompositorReadingToTheFrontOfCursor() { - compositor.dropReading(direction: .front) - } - /// 生成標點符號索引鍵。 /// - Parameter input: 輸入的按鍵訊號。 /// - Returns: 生成的標點符號索引鍵。 diff --git a/Source/Modules/ControllerModules/KeyHandler_HandleCandidate.swift b/Source/Modules/ControllerModules/KeyHandler_HandleCandidate.swift index f9bb3236..0b512e4b 100644 --- a/Source/Modules/ControllerModules/KeyHandler_HandleCandidate.swift +++ b/Source/Modules/ControllerModules/KeyHandler_HandleCandidate.swift @@ -61,12 +61,12 @@ extension KeyHandler { if cancelCandidateKey { if (state is InputState.AssociatedPhrases) || mgrPrefs.useSCPCTypingMode - || isCompositorEmpty + || compositor.isEmpty { // 如果此時發現當前組字緩衝區為真空的情況的話, // 就將當前的組字緩衝區析構處理、強制重設輸入狀態。 // 否則,一個本不該出現的真空組字緩衝區會使前後方向鍵與 BackSpace 鍵失靈。 - // 所以這裡需要對 isCompositorEmpty 做判定。 + // 所以這裡需要對 compositor.isEmpty 做判定。 clear() stateCallback(InputState.EmptyIgnoringPreviousState()) } else { @@ -326,12 +326,12 @@ extension KeyHandler { let punctuation: String = arrPunctuations.joined(separator: "") var shouldAutoSelectCandidate: Bool = - composer.inputValidityCheck(key: charCode) || ifLangModelHasUnigrams(forKey: customPunctuation) - || ifLangModelHasUnigrams(forKey: punctuation) + composer.inputValidityCheck(key: charCode) || currentLM.hasUnigramsFor(key: customPunctuation) + || currentLM.hasUnigramsFor(key: punctuation) if !shouldAutoSelectCandidate, input.isUpperCaseASCIILetterKey { let letter: String! = String(format: "%@%c", "_letter_", CChar(charCode)) - if ifLangModelHasUnigrams(forKey: letter) { shouldAutoSelectCandidate = true } + if currentLM.hasUnigramsFor(key: letter) { shouldAutoSelectCandidate = true } } if shouldAutoSelectCandidate { diff --git a/Source/Modules/ControllerModules/KeyHandler_HandleInput.swift b/Source/Modules/ControllerModules/KeyHandler_HandleInput.swift index f7c0cd59..25fbf97f 100644 --- a/Source/Modules/ControllerModules/KeyHandler_HandleInput.swift +++ b/Source/Modules/ControllerModules/KeyHandler_HandleInput.swift @@ -188,7 +188,7 @@ extension KeyHandler { // 如果輸入法的辭典索引是漢語拼音的話,要注意上一行拿到的內容得是漢語拼音。 // 向語言模型詢問是否有對應的記錄。 - if !ifLangModelHasUnigrams(forKey: reading) { + if !currentLM.hasUnigramsFor(key: reading) { IME.prtDebugIntel("B49C0979:語彙庫內無「\(reading)」的匹配記錄。") errorCallback() composer.clear() @@ -198,7 +198,7 @@ extension KeyHandler { } // 將該讀音插入至組字器內的軌格當中。 - insertToCompositorAtCursor(reading: reading) + compositor.insertReading(reading) // 讓組字器反爬軌格。 let textToCommit = commitOverflownCompositionAndWalk @@ -270,7 +270,7 @@ extension KeyHandler { if input.isSpace { /// 倘若沒有在偏好設定內將 Space 空格鍵設為選字窗呼叫用鍵的話……… if !mgrPrefs.chooseCandidateUsingSpace { - if compositorCursorIndex >= compositorLength { + if compositor.cursor >= compositor.length { let composingBuffer = currentState.composingBuffer if !composingBuffer.isEmpty { stateCallback(InputState.Committing(textToCommit: composingBuffer)) @@ -278,8 +278,8 @@ extension KeyHandler { clear() stateCallback(InputState.Committing(textToCommit: " ")) stateCallback(InputState.Empty()) - } else if ifLangModelHasUnigrams(forKey: " ") { - insertToCompositorAtCursor(reading: " ") + } else if currentLM.hasUnigramsFor(key: " ") { + compositor.insertReading(" ") let textToCommit = commitOverflownCompositionAndWalk let inputting = buildInputtingState inputting.textToCommit = textToCommit @@ -396,9 +396,9 @@ extension KeyHandler { if input.isSymbolMenuPhysicalKey && !input.isShiftHold { if input.isOptionHold { - if ifLangModelHasUnigrams(forKey: "_punctuation_list") { + if currentLM.hasUnigramsFor(key: "_punctuation_list") { if composer.isEmpty { - insertToCompositorAtCursor(reading: "_punctuation_list") + compositor.insertReading("_punctuation_list") let textToCommit: String! = commitOverflownCompositionAndWalk let inputting = buildInputtingState inputting.textToCommit = textToCommit diff --git a/Source/Modules/ControllerModules/KeyHandler_States.swift b/Source/Modules/ControllerModules/KeyHandler_States.swift index 60268fcc..6ed1b3e1 100644 --- a/Source/Modules/ControllerModules/KeyHandler_States.swift +++ b/Source/Modules/ControllerModules/KeyHandler_States.swift @@ -54,35 +54,35 @@ extension KeyHandler { /// 每個節錨(NodeAnchor)都有自身的幅位長度(spanningLength),可以用來 /// 累加、以此為依據,來校正「可見游標位置」。 let spanningLength: Int = theAnchor.spanLength - if readingCursorIndex + spanningLength <= compositorCursorIndex { + if readingCursorIndex + spanningLength <= compositor.cursor { composedStringCursorIndex += strNodeValue.utf16.count readingCursorIndex += spanningLength } else { if codepointCount == spanningLength { var i = 0 - while i < codepointCount, readingCursorIndex < compositorCursorIndex { + while i < codepointCount, readingCursorIndex < compositor.cursor { composedStringCursorIndex += arrSplit[i].utf16.count readingCursorIndex += 1 i += 1 } } else { - if readingCursorIndex < compositorCursorIndex { + if readingCursorIndex < compositor.cursor { composedStringCursorIndex += strNodeValue.utf16.count readingCursorIndex += spanningLength - readingCursorIndex = min(readingCursorIndex, compositorCursorIndex) + readingCursorIndex = min(readingCursorIndex, compositor.cursor) /// 接下來再處理這麼一種情況: /// 某些錨點內的當前候選字詞長度與讀音長度不相等。 /// 但此時游標還是按照每個讀音單位來移動的, /// 所以需要上下文工具提示來顯示游標的相對位置。 /// 這裡先計算一下要用在工具提示當中的顯示參數的內容。 - switch compositorCursorIndex { + switch compositor.cursor { case compositor.readings.count...: - tooltipParameterRef[0] = compositor.readings[compositorCursorIndex - 1] + tooltipParameterRef[0] = compositor.readings[compositor.cursor - 1] case 0: - tooltipParameterRef[1] = compositor.readings[compositorCursorIndex] + tooltipParameterRef[1] = compositor.readings[compositor.cursor] default: - tooltipParameterRef[0] = compositor.readings[compositorCursorIndex - 1] - tooltipParameterRef[1] = compositor.readings[compositorCursorIndex] + tooltipParameterRef[0] = compositor.readings[compositor.cursor - 1] + tooltipParameterRef[1] = compositor.readings[compositor.cursor] } /// 注音轉拼音 for (i, _) in tooltipParameterRef.enumerated() { @@ -301,7 +301,7 @@ extension KeyHandler { stateCallback: @escaping (InputStateProtocol) -> Void, errorCallback: @escaping () -> Void ) -> Bool { - if !ifLangModelHasUnigrams(forKey: customPunctuation) { + if !currentLM.hasUnigramsFor(key: customPunctuation) { return false } @@ -313,7 +313,7 @@ extension KeyHandler { return true } - insertToCompositorAtCursor(reading: customPunctuation) + compositor.insertReading(customPunctuation) let textToCommit = commitOverflownCompositionAndWalk let inputting = buildInputtingState inputting.textToCommit = textToCommit @@ -372,7 +372,7 @@ extension KeyHandler { ) -> Bool { guard state is InputState.Inputting else { return false } - var composingBuffer = currentReadings.joined(separator: "-") + var composingBuffer = compositor.readings.joined(separator: "-") if mgrPrefs.inlineDumpPinyinInLieuOfZhuyin { composingBuffer = Tekkon.restoreToneOneInZhuyinKey(target: composingBuffer) // 恢復陰平標記 composingBuffer = Tekkon.cnvPhonaToHanyuPinyin(target: composingBuffer) // 注音轉拼音 @@ -445,8 +445,8 @@ extension KeyHandler { if composer.hasToneMarker(withNothingElse: true) { composer.clear() } else if composer.isEmpty { - if compositorCursorIndex > 0 { - deleteCompositorReadingAtTheRearOfCursor() + if compositor.cursor > 0 { + compositor.dropReading(direction: .rear) walk() } else { IME.prtDebugIntel("9D69908D") @@ -485,14 +485,14 @@ extension KeyHandler { return true } - guard compositorCursorIndex != compositorLength else { + guard compositor.cursor != compositor.length else { IME.prtDebugIntel("9B69938D") errorCallback() stateCallback(state) return true } - deleteCompositorReadingToTheFrontOfCursor() + compositor.dropReading(direction: .front) walk() let inputting = buildInputtingState // 這裡不用「count > 0」,因為該整數變數只要「!isEmpty」那就必定滿足這個條件。 @@ -544,8 +544,8 @@ extension KeyHandler { return true } - if compositorCursorIndex != 0 { - compositorCursorIndex = 0 + if compositor.cursor != 0 { + compositor.cursor = 0 stateCallback(buildInputtingState) } else { IME.prtDebugIntel("66D97F90") @@ -578,8 +578,8 @@ extension KeyHandler { return true } - if compositorCursorIndex != compositorLength { - compositorCursorIndex = compositorLength + if compositor.cursor != compositor.length { + compositor.cursor = compositor.length stateCallback(buildInputtingState) } else { IME.prtDebugIntel("9B69908E") @@ -650,7 +650,7 @@ extension KeyHandler { composingBuffer: currentState.composingBuffer, cursorIndex: currentState.cursorIndex, markerIndex: nextPosition, - readings: currentReadings + readings: compositor.readings ) marking.tooltipForInputting = currentState.tooltip stateCallback(marking) @@ -672,8 +672,8 @@ extension KeyHandler { } stateCallback(buildInputtingState) } else { - if compositorCursorIndex < compositorLength { - compositorCursorIndex += 1 + if compositor.cursor < compositor.length { + compositor.cursor += 1 stateCallback(buildInputtingState) } else { IME.prtDebugIntel("A96AAD58") @@ -718,7 +718,7 @@ extension KeyHandler { composingBuffer: currentState.composingBuffer, cursorIndex: currentState.cursorIndex, markerIndex: previousPosition, - readings: currentReadings + readings: compositor.readings ) marking.tooltipForInputting = currentState.tooltip stateCallback(marking) @@ -740,8 +740,8 @@ extension KeyHandler { } stateCallback(buildInputtingState) } else { - if compositorCursorIndex > 0 { - compositorCursorIndex -= 1 + if compositor.cursor > 0 { + compositor.cursor -= 1 stateCallback(buildInputtingState) } else { IME.prtDebugIntel("7045E6F3") @@ -795,7 +795,7 @@ extension KeyHandler { var length = 0 var currentAnchor = Megrez.NodeAnchor() let cursorIndex = min( - actualCandidateCursor + (mgrPrefs.useRearCursorMode ? 1 : 0), compositorLength + actualCandidateCursor + (mgrPrefs.useRearCursorMode ? 1 : 0), compositor.length ) for anchor in walkedAnchors { length += anchor.spanLength From 4cc105b2576cf9c4cbab9436977da413b43af7c5 Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Fri, 22 Jul 2022 16:20:44 +0800 Subject: [PATCH 12/15] LMAssoc. // Optimize key conversion process. --- .../SubLMs/lmAssociates.swift | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Source/Modules/LangModelRelated/SubLMs/lmAssociates.swift b/Source/Modules/LangModelRelated/SubLMs/lmAssociates.swift index a17d1faf..e69b4935 100644 --- a/Source/Modules/LangModelRelated/SubLMs/lmAssociates.swift +++ b/Source/Modules/LangModelRelated/SubLMs/lmAssociates.swift @@ -42,6 +42,15 @@ extension vChewing { !rangeMap.isEmpty } + internal func cnvNgramKeyFromPinyinToPhona(target: String) -> String { + guard target.contains("("), target.contains(","), target.contains(")") else { + return target + } + let arrTarget = target.dropLast().dropFirst().split(separator: ",") + guard arrTarget.count == 2 else { return target } + return "(\(Tekkon.cnvHanyuPinyinToPhona(target: String(arrTarget[0]))),\(arrTarget[1]))" + } + @discardableResult public mutating func open(_ path: String) -> Bool { if isLoaded() { return false @@ -60,7 +69,7 @@ extension vChewing { if !theKey.isEmpty, theKey.first != "#" { for (i, _) in neta.filter({ $0.first != "#" && !$0.isEmpty }).enumerated() { if i == 0 { continue } - rangeMap[theKey, default: []].append(($0, i)) + rangeMap[cnvNgramKeyFromPinyinToPhona(target: theKey), default: []].append(($0, i)) } } } @@ -102,8 +111,6 @@ extension vChewing { } public func valuesFor(pair: Megrez.KeyValuePaired) -> [String] { - var pairPinyin = pair - pairPinyin.key = Tekkon.cnvPhonaToHanyuPinyin(target: pairPinyin.key) var pairs: [String] = [] if let arrRangeRecords: [(Range, Int)] = rangeMap[pair.toNGramKey] { for (netaRange, index) in arrRangeRecords { @@ -112,13 +119,6 @@ extension vChewing { pairs.append(theValue) } } - if let arrRangeRecords: [(Range, Int)] = rangeMap[pairPinyin.toNGramKey] { - for (netaRange, index) in arrRangeRecords { - let neta = strData[netaRange].split(separator: " ") - let theValue: String = .init(neta[index]) - pairs.append(theValue) - } - } if let arrRangeRecords: [(Range, Int)] = rangeMap[pair.value] { for (netaRange, index) in arrRangeRecords { let neta = strData[netaRange].split(separator: " ") From 4f8ece9b5136af0164d6d18f29b12e97394c8d63 Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Fri, 22 Jul 2022 17:17:14 +0800 Subject: [PATCH 13/15] Tekkon // v1.2.7 update. --- Source/Modules/ControllerModules/SyllableComposer.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Modules/ControllerModules/SyllableComposer.swift b/Source/Modules/ControllerModules/SyllableComposer.swift index abfa4e11..b34d0982 100644 --- a/Source/Modules/ControllerModules/SyllableComposer.swift +++ b/Source/Modules/ControllerModules/SyllableComposer.swift @@ -906,7 +906,7 @@ public struct Tekkon { } for key in Tekkon.mapArayuruPinyinIntonation.keys.sorted(by: { $0.count > $1.count }) { guard let value = Tekkon.mapArayuruPinyinIntonation[key] else { continue } - result = result.replacingOccurrences(of: key, with: value) + result = result.replacingOccurrences(of: key, with: (key == "1") ? "" : value) } return result } From 58084351bc06d9d609d80f5794e23ee49d83950b Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Fri, 22 Jul 2022 18:06:58 +0800 Subject: [PATCH 14/15] Update Data - 20220722 --- Source/Data | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Data b/Source/Data index 32ae1957..91a12bb5 160000 --- a/Source/Data +++ b/Source/Data @@ -1 +1 @@ -Subproject commit 32ae1957bdbbb1daabf108f6352708677aec27fa +Subproject commit 91a12bb5a355b56456beceec42cb001dea036b2b From 1ae7960409955b3b74207c162383d1658bbebd21 Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Fri, 22 Jul 2022 18:07:39 +0800 Subject: [PATCH 15/15] Bump version to 1.8.3 Build 1983 --- Update-Info.plist | 4 ++-- vChewing.pkgproj | 2 +- vChewing.xcodeproj/project.pbxproj | 32 +++++++++++++++--------------- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/Update-Info.plist b/Update-Info.plist index a533f61a..06df0777 100644 --- a/Update-Info.plist +++ b/Update-Info.plist @@ -3,9 +3,9 @@ CFBundleShortVersionString - 1.8.2 + 1.8.3 CFBundleVersion - 1982 + 1983 UpdateInfoEndpoint https://gitee.com/vchewing/vChewing-macOS/raw/main/Update-Info.plist UpdateInfoSite diff --git a/vChewing.pkgproj b/vChewing.pkgproj index 1a74a316..7b11ff18 100644 --- a/vChewing.pkgproj +++ b/vChewing.pkgproj @@ -726,7 +726,7 @@ USE_HFS+_COMPRESSION VERSION - 1.8.2 + 1.8.3 TYPE 0 diff --git a/vChewing.xcodeproj/project.pbxproj b/vChewing.xcodeproj/project.pbxproj index 31ec6b36..5ea47912 100644 --- a/vChewing.xcodeproj/project.pbxproj +++ b/vChewing.xcodeproj/project.pbxproj @@ -1389,7 +1389,7 @@ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1982; + CURRENT_PROJECT_VERSION = 1983; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_DYNAMIC_NO_PIC = NO; GCC_PREPROCESSOR_DEFINITIONS = ( @@ -1399,7 +1399,7 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.8.2; + MARKETING_VERSION = 1.8.3; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewingTests; @@ -1428,13 +1428,13 @@ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1982; + CURRENT_PROJECT_VERSION = 1983; ENABLE_NS_ASSERTIONS = NO; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.8.2; + MARKETING_VERSION = 1.8.3; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewingTests; @@ -1465,7 +1465,7 @@ CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 1982; + CURRENT_PROJECT_VERSION = 1983; DEAD_CODE_STRIPPING = YES; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_DYNAMIC_NO_PIC = NO; @@ -1486,7 +1486,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 1.8.2; + MARKETING_VERSION = 1.8.3; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewing.vChewingPhraseEditor; @@ -1515,7 +1515,7 @@ CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 1982; + CURRENT_PROJECT_VERSION = 1983; DEAD_CODE_STRIPPING = YES; ENABLE_NS_ASSERTIONS = NO; GCC_C_LANGUAGE_STANDARD = gnu11; @@ -1532,7 +1532,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 1.8.2; + MARKETING_VERSION = 1.8.3; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewing.vChewingPhraseEditor; @@ -1646,7 +1646,7 @@ CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 1982; + CURRENT_PROJECT_VERSION = 1983; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_ASSET_PATHS = ""; DEVELOPMENT_TEAM = ""; @@ -1674,7 +1674,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 1.8.2; + MARKETING_VERSION = 1.8.3; ONLY_ACTIVE_ARCH = YES; PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.inputmethod.vChewing; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -1701,7 +1701,7 @@ CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 1982; + CURRENT_PROJECT_VERSION = 1983; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_ASSET_PATHS = ""; DEVELOPMENT_TEAM = ""; @@ -1723,7 +1723,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 1.8.2; + MARKETING_VERSION = 1.8.3; PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.inputmethod.vChewing; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -1745,7 +1745,7 @@ CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 1982; + CURRENT_PROJECT_VERSION = 1983; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = ""; GCC_C_LANGUAGE_STANDARD = gnu99; @@ -1765,7 +1765,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 1.8.2; + MARKETING_VERSION = 1.8.3; ONLY_ACTIVE_ARCH = YES; PRODUCT_BUNDLE_IDENTIFIER = "org.atelierInmu.vChewing.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -1787,7 +1787,7 @@ CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 1982; + CURRENT_PROJECT_VERSION = 1983; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = ""; GCC_C_LANGUAGE_STANDARD = gnu99; @@ -1801,7 +1801,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 1.8.2; + MARKETING_VERSION = 1.8.3; PRODUCT_BUNDLE_IDENTIFIER = "org.atelierInmu.vChewing.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = "";