From 6e9c878928dc6d36e8a1c2bd17de3c25aac35412 Mon Sep 17 00:00:00 2001 From: zonble Date: Sat, 9 Dec 2023 00:57:10 +0800 Subject: [PATCH 1/7] Adds InputMacroController. --- McBopomofo.xcodeproj/project.pbxproj | 4 + Source/Data/Symbols.txt | 15 ++- Source/InputMacro.swift | 174 +++++++++++++++++++++++++++ Source/LanguageModelManager.mm | 4 + 4 files changed, 196 insertions(+), 1 deletion(-) create mode 100644 Source/InputMacro.swift diff --git a/McBopomofo.xcodeproj/project.pbxproj b/McBopomofo.xcodeproj/project.pbxproj index c2f918885..bda66af31 100644 --- a/McBopomofo.xcodeproj/project.pbxproj +++ b/McBopomofo.xcodeproj/project.pbxproj @@ -46,6 +46,7 @@ D427F7B4279086DC004A2160 /* InputSourceHelper in Frameworks */ = {isa = PBXBuildFile; productRef = D427F7B3279086DC004A2160 /* InputSourceHelper */; }; D427F7B6279086F6004A2160 /* InputSourceHelper in Frameworks */ = {isa = PBXBuildFile; productRef = D427F7B5279086F6004A2160 /* InputSourceHelper */; }; D427F7C127908EFC004A2160 /* OpenCCBridge in Frameworks */ = {isa = PBXBuildFile; productRef = D427F7C027908EFC004A2160 /* OpenCCBridge */; }; + D43FC40B2B23788400ED5A1C /* InputMacro.swift in Sources */ = {isa = PBXBuildFile; fileRef = D43FC40A2B23788400ED5A1C /* InputMacro.swift */; }; D44FB74527915565003C80A6 /* Preferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = D44FB74427915555003C80A6 /* Preferences.swift */; }; D44FB74A2791B829003C80A6 /* VXHanConvert in Frameworks */ = {isa = PBXBuildFile; productRef = D44FB7492791B829003C80A6 /* VXHanConvert */; }; D44FB74D2792189A003C80A6 /* PhraseReplacementMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D44FB74B2792189A003C80A6 /* PhraseReplacementMap.cpp */; }; @@ -167,6 +168,7 @@ D427F7AC27907B7E004A2160 /* NotifierUI */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = NotifierUI; path = Packages/NotifierUI; sourceTree = ""; }; D427F7B2279086B5004A2160 /* InputSourceHelper */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = InputSourceHelper; path = Packages/InputSourceHelper; sourceTree = ""; }; D427F7BF27908EAC004A2160 /* OpenCCBridge */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = OpenCCBridge; path = Packages/OpenCCBridge; sourceTree = ""; }; + D43FC40A2B23788400ED5A1C /* InputMacro.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InputMacro.swift; sourceTree = ""; }; D44FB74427915555003C80A6 /* Preferences.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Preferences.swift; sourceTree = ""; }; D44FB7482791B346003C80A6 /* VXHanConvert */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = VXHanConvert; path = Packages/VXHanConvert; sourceTree = ""; }; D44FB74B2792189A003C80A6 /* PhraseReplacementMap.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PhraseReplacementMap.cpp; sourceTree = ""; }; @@ -278,6 +280,7 @@ D4E569DB27A34CC100AC2CEF /* KeyHandler.mm */, 6AE215102A2849BB005A6A02 /* UTF8Helper.cpp */, 6AE2150F2A2849BB005A6A02 /* UTF8Helper.h */, + D43FC40A2B23788400ED5A1C /* InputMacro.swift */, D456576D279E4F7B00DF6BC9 /* KeyHandlerInput.swift */, D461B791279DAC010070E734 /* InputState.swift */, D427F76B278CA1BA004A2160 /* AppDelegate.swift */, @@ -671,6 +674,7 @@ 6A0D4F4515FC0EB100ABF4B3 /* Mandarin.cpp in Sources */, 6ACC3D452793701600F1B140 /* ParselessLM.cpp in Sources */, D41355DE278EA3ED005E5CBD /* UserPhrasesLM.cpp in Sources */, + D43FC40B2B23788400ED5A1C /* InputMacro.swift in Sources */, 6AE215112A2849BB005A6A02 /* UTF8Helper.cpp in Sources */, 6ACC3D3F27914F2400F1B140 /* KeyValueBlobReader.cpp in Sources */, B058C5272AC9DF51002EDD66 /* ServiceProvider.swift in Sources */, diff --git a/Source/Data/Symbols.txt b/Source/Data/Symbols.txt index ae4abfd6a..ba6d65b88 100644 --- a/Source/Data/Symbols.txt +++ b/Source/Data/Symbols.txt @@ -1,3 +1,16 @@ +今天日期 ㄐㄧㄣ-ㄊㄧㄢ-ㄖˋ-ㄑㄧˊ -8 +MACRO@DATE_TODAY_SHORT ㄐㄧㄣ-ㄊㄧㄢ-ㄖˋ-ㄑㄧˊ -8 +MACRO@DATE_TODAY_MEDIUEM ㄐㄧㄣ-ㄊㄧㄢ-ㄖˋ-ㄑㄧˊ -8 +MACRO@DATE_TODAY_MEDIUEM_ROC ㄐㄧㄣ-ㄊㄧㄢ-ㄖˋ-ㄑㄧˊ -8 +MACRO@DATE_TODAY_MEDIUEM_CHINESE ㄐㄧㄣ-ㄊㄧㄢ-ㄖˋ-ㄑㄧˊ -8 +現在時刻 ㄒㄧㄢˋ-ㄗㄞˋ-ㄕˊ-ㄎㄜˋ -8 +MACRO@TIME_NOW_SHORT ㄒㄧㄢˋ-ㄗㄞˋ-ㄕˊ-ㄎㄜˋ -8 +MACRO@TIME_NOW_MEDIUM ㄒㄧㄢˋ-ㄗㄞˋ-ㄕˊ-ㄎㄜˋ -8 +現在時刻 ㄒㄧㄢˋ-ㄗㄞˋ-ㄕˊ-ㄐㄧㄢ -8 +MACRO@TIME_NOW_SHORT ㄒㄧㄢˋ-ㄗㄞˋ-ㄕˊ-ㄐㄧㄢ -8 +MACRO@TIME_NOW_MEDIUM ㄒㄧㄢˋ-ㄗㄞˋ-ㄕˊ-ㄐㄧㄢ -8 +MACRO@TIMEZONE_STANDARD ㄇㄨˋ-ㄑㄧㄢˊ-ㄕˊ-ㄑㄩ -8 +MACRO@TIMEZONE_GENERIC_SHORT ㄇㄨˋ-ㄑㄧㄢˊ-ㄕˊ-ㄑㄩ -8 ㏕ ㄅㄞˇ-ㄨㄢˋ -8 © ㄅㄢˇ-ㄑㄩㄢˊ -8 ⌬ ㄅㄣˇ-ㄏㄨㄢˊ -8 @@ -18,8 +31,8 @@ ☢ ㄈㄨˊ-ㄕㄜˋ-ㄒㄧㄥˋ -8 ≥ ㄉㄚˋ-ㄩˊ-ㄉㄥˇ-ㄩˊ -8 🉐 ㄉㄜˊ -8 -▼ ㄉㄠˋ-ㄙㄢ-ㄐㄧㄠˇ -8 ℡ ㄉㄧㄢˋ-ㄏㄨㄚˋ -8 +▼ ㄉㄠˋ-ㄙㄢ-ㄐㄧㄠˇ -8 ㏒ ㄉㄨㄟˋ-ㄕㄨˋ -8 ♏ ㄊㄧㄢ-ㄒㄧㄝ -8 ♎ ㄊㄧㄢ-ㄔㄥˋ -8 diff --git a/Source/InputMacro.swift b/Source/InputMacro.swift new file mode 100644 index 000000000..bce044395 --- /dev/null +++ b/Source/InputMacro.swift @@ -0,0 +1,174 @@ +// Copyright (c) 2022 and onwards The McBopomofo Authors. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. + +import Foundation + +protocol InputMacro { + var name: String { get } + var replacement: String { get } +} + +fileprivate struct InputMacroDateTodayShort: InputMacro { + var name: String { + "MACRO@DATE_TODAY_SHORT" + } + + var replacement: String { + let date = Date() + let dateFormatter = DateFormatter() + dateFormatter.dateStyle = .short + dateFormatter.timeStyle = .none + dateFormatter.locale = Locale(identifier: "zh_Hant_TW") + return dateFormatter.string(from: date) + } +} + +fileprivate struct InputMacroDateTodayMedium: InputMacro { + var name: String { + "MACRO@DATE_TODAY_MEDIUEM" + } + + var replacement: String { + let date = Date() + let dateFormatter = DateFormatter() + dateFormatter.dateStyle = .medium + dateFormatter.timeStyle = .none + dateFormatter.locale = Locale(identifier: "zh_Hant_TW") + return dateFormatter.string(from: date) + } +} + +fileprivate struct InputMacroDateTodayMediumROC: InputMacro { + var name: String { + "MACRO@DATE_TODAY_MEDIUEM_ROC" + } + + var replacement: String { + let date = Date() + let dateFormatter = DateFormatter() + dateFormatter.dateStyle = .medium + dateFormatter.timeStyle = .none + dateFormatter.locale = Locale(identifier: "zh_Hant_TW") + dateFormatter.calendar = Calendar(identifier: .republicOfChina) + return dateFormatter.string(from: date) + } +} + +fileprivate struct InputMacroDateTodayMediumChinese: InputMacro { + var name: String { + "MACRO@DATE_TODAY_MEDIUEM_CHINESE" + } + + var replacement: String { + let date = Date() + let dateFormatter = DateFormatter() + dateFormatter.dateStyle = .medium + dateFormatter.timeStyle = .none + dateFormatter.locale = Locale(identifier: "zh_Hant_TW") + dateFormatter.calendar = Calendar(identifier: .chinese) + return dateFormatter.string(from: date) + } +} + +fileprivate struct InputMacroTimeNowShort: InputMacro { + var name: String { + "MACRO@TIME_NOW_SHORT" + } + + var replacement: String { + let date = Date() + let dateFormatter = DateFormatter() + dateFormatter.dateStyle = .none + dateFormatter.timeStyle = .short + dateFormatter.locale = Locale(identifier: "zh_Hant_TW") + return dateFormatter.string(from: date) + } +} + +fileprivate struct InputMacroTimeNowMedium: InputMacro { + var name: String { + "MACRO@TIME_NOW_MEDIUM" + } + + var replacement: String { + let date = Date() + let dateFormatter = DateFormatter() + dateFormatter.dateStyle = .none + dateFormatter.timeStyle = .medium + dateFormatter.locale = Locale(identifier: "zh_Hant_TW") + return dateFormatter.string(from: date) + } +} + +fileprivate struct InputMacroTimeZoneStandard: InputMacro { + var name: String { + "MACRO@TIMEZONE_STANDARD" + } + + var replacement: String { + let timezone = TimeZone.current + let locale = Locale(identifier: "zh_Hant_TW") + return timezone.localizedName(for: .standard, locale: locale) ?? "" + } +} + +fileprivate struct InputMacroTimeZoneShortGeneric: InputMacro { + var name: String { + "MACRO@TIMEZONE_GENERIC_SHORT" + } + + var replacement: String { + let timezone = TimeZone.current + let locale = Locale(identifier: "zh_Hant_TW") + return timezone.localizedName(for: .shortGeneric, locale: locale) ?? "" + } +} + +class InputMacroController: NSObject { + @objc + static let shared = InputMacroController() + + private var macros: [InputMacro] = + [ + InputMacroDateTodayShort(), + InputMacroDateTodayMedium(), + InputMacroDateTodayMediumROC(), + InputMacroDateTodayMediumChinese(), + InputMacroTimeNowShort(), + InputMacroTimeNowMedium(), + InputMacroTimeZoneStandard(), + InputMacroTimeZoneShortGeneric(), + ] + + @objc + func handle(_ input: String) -> String { + for inputMacro in macros { + if inputMacro.name == input { + return inputMacro.replacement + } + } + return input + } + +} + diff --git a/Source/LanguageModelManager.mm b/Source/LanguageModelManager.mm index 4000d9aca..7e83e4d41 100644 --- a/Source/LanguageModelManager.mm +++ b/Source/LanguageModelManager.mm @@ -102,6 +102,10 @@ + (void)loadUserPhraseReplacement + (void)setupDataModelValueConverter { auto converter = [](std::string input) { + NSString *inputText = [NSString stringWithUTF8String:input.c_str()]; + NSString *handled = [[InputMacroController shared] handle:inputText]; + input = std::string(handled.UTF8String); + if (!Preferences.chineseConversionEnabled) { return input; } From c30410bd25d9ef925a567c58098952da921ea2ca Mon Sep 17 00:00:00 2001 From: zonble Date: Sat, 9 Dec 2023 05:21:29 +0800 Subject: [PATCH 2/7] Adds additioanl macros for years. --- Source/Data/Macros.txt | 21 ++++++++++++ Source/Data/Makefile | 6 ++-- Source/Data/Symbols.txt | 13 -------- Source/Data/bin/cook.py | 6 ++++ Source/Engine/McBopomofoLM.cpp | 2 +- Source/InputMacro.swift | 61 ++++++++++++++++++++++++++++++++++ 6 files changed, 92 insertions(+), 17 deletions(-) create mode 100644 Source/Data/Macros.txt diff --git a/Source/Data/Macros.txt b/Source/Data/Macros.txt new file mode 100644 index 000000000..d1433fbc9 --- /dev/null +++ b/Source/Data/Macros.txt @@ -0,0 +1,21 @@ +今天日期 ㄐㄧㄣ-ㄊㄧㄢ-ㄖˋ-ㄑㄧˊ -8 +MACRO@DATE_TODAY_SHORT ㄐㄧㄣ-ㄊㄧㄢ-ㄖˋ-ㄑㄧˊ -8 +MACRO@DATE_TODAY_MEDIUEM ㄐㄧㄣ-ㄊㄧㄢ-ㄖˋ-ㄑㄧˊ -8 +MACRO@DATE_TODAY_MEDIUEM_ROC ㄐㄧㄣ-ㄊㄧㄢ-ㄖˋ-ㄑㄧˊ -8 +MACRO@DATE_TODAY_MEDIUEM_CHINESE ㄐㄧㄣ-ㄊㄧㄢ-ㄖˋ-ㄑㄧˊ -8 +現在時刻 ㄒㄧㄢˋ-ㄗㄞˋ-ㄕˊ-ㄎㄜˋ -8 +MACRO@TIME_NOW_SHORT ㄒㄧㄢˋ-ㄗㄞˋ-ㄕˊ-ㄎㄜˋ -8 +MACRO@TIME_NOW_MEDIUM ㄒㄧㄢˋ-ㄗㄞˋ-ㄕˊ-ㄎㄜˋ -8 +現在時間 ㄒㄧㄢˋ-ㄗㄞˋ-ㄕˊ-ㄐㄧㄢ -8 +MACRO@TIME_NOW_SHORT ㄒㄧㄢˋ-ㄗㄞˋ-ㄕˊ-ㄐㄧㄢ -8 +MACRO@TIME_NOW_MEDIUM ㄒㄧㄢˋ-ㄗㄞˋ-ㄕˊ-ㄐㄧㄢ -8 +目前時區 ㄇㄨˋ-ㄑㄧㄢˊ-ㄕˊ-ㄑㄩ -8 +MACRO@TIMEZONE_STANDARD ㄇㄨˋ-ㄑㄧㄢˊ-ㄕˊ-ㄑㄩ -8 +MACRO@TIMEZONE_GENERIC_SHORT ㄇㄨˋ-ㄑㄧㄢˊ-ㄕˊ-ㄑㄩ -8 +所在時區 ㄙㄨㄛˇ-ㄗㄞˋ-ㄕˊ-ㄑㄩ -8 +MACRO@TIMEZONE_STANDARD ㄙㄨㄛˇ-ㄗㄞˋ-ㄕˊ-ㄑㄩ -8 +MACRO@TIMEZONE_GENERIC_SHORT ㄙㄨㄛˇ-ㄗㄞˋ-ㄕˊ-ㄑㄩ -8 +今年干支 ㄐㄧㄣ-ㄋㄧㄢˊ-ㄍㄢ-ㄓ -8 +MACRO@THIS_YEAR_GANZHI ㄐㄧㄣ-ㄋㄧㄢˊ-ㄍㄢ-ㄓ -8 +今年生肖 ㄐㄧㄣ-ㄋㄧㄢˊ-ㄕㄥ-ㄒㄧㄠˋ -8 +MACRO@THIS_YEAR_WOOD_RAT ㄐㄧㄣ-ㄋㄧㄢˊ-ㄕㄥ-ㄒㄧㄠˋ -8 \ No newline at end of file diff --git a/Source/Data/Makefile b/Source/Data/Makefile index 15f2dc33e..875f7093f 100644 --- a/Source/Data/Makefile +++ b/Source/Data/Makefile @@ -8,9 +8,9 @@ data-plain-bpmf.txt: bin/cook-plain-bpmf.py BPMFBase.txt BPMFPunctuations.txt bin/cook-plain-bpmf.py BPMFBase.txt BPMFPunctuations.txt data-plain-bpmf.txt data.txt: bin/cook.py BPMFBase.txt BPMFMappings.txt BPMFPunctuations.txt \ - PhraseFreq.txt phrase.occ Symbols.txt \ - heterophony1.list heterophony2.list heterophony3.list - bin/cook.py PhraseFreq.txt BPMFMappings.txt BPMFBase.txt BPMFPunctuations.txt Symbols.txt $@ + PhraseFreq.txt phrase.occ Symbols.txt Macros.txt\ + heterophony1.list heterophony2.list heterophony3.list + bin/cook.py PhraseFreq.txt BPMFMappings.txt BPMFBase.txt BPMFPunctuations.txt Symbols.txt Macros.txt $@ PhraseFreq.txt: bin/buildFreq.py phrase.occ exclusion.txt bin/buildFreq.py diff --git a/Source/Data/Symbols.txt b/Source/Data/Symbols.txt index ba6d65b88..30a2f100e 100644 --- a/Source/Data/Symbols.txt +++ b/Source/Data/Symbols.txt @@ -1,16 +1,3 @@ -今天日期 ㄐㄧㄣ-ㄊㄧㄢ-ㄖˋ-ㄑㄧˊ -8 -MACRO@DATE_TODAY_SHORT ㄐㄧㄣ-ㄊㄧㄢ-ㄖˋ-ㄑㄧˊ -8 -MACRO@DATE_TODAY_MEDIUEM ㄐㄧㄣ-ㄊㄧㄢ-ㄖˋ-ㄑㄧˊ -8 -MACRO@DATE_TODAY_MEDIUEM_ROC ㄐㄧㄣ-ㄊㄧㄢ-ㄖˋ-ㄑㄧˊ -8 -MACRO@DATE_TODAY_MEDIUEM_CHINESE ㄐㄧㄣ-ㄊㄧㄢ-ㄖˋ-ㄑㄧˊ -8 -現在時刻 ㄒㄧㄢˋ-ㄗㄞˋ-ㄕˊ-ㄎㄜˋ -8 -MACRO@TIME_NOW_SHORT ㄒㄧㄢˋ-ㄗㄞˋ-ㄕˊ-ㄎㄜˋ -8 -MACRO@TIME_NOW_MEDIUM ㄒㄧㄢˋ-ㄗㄞˋ-ㄕˊ-ㄎㄜˋ -8 -現在時刻 ㄒㄧㄢˋ-ㄗㄞˋ-ㄕˊ-ㄐㄧㄢ -8 -MACRO@TIME_NOW_SHORT ㄒㄧㄢˋ-ㄗㄞˋ-ㄕˊ-ㄐㄧㄢ -8 -MACRO@TIME_NOW_MEDIUM ㄒㄧㄢˋ-ㄗㄞˋ-ㄕˊ-ㄐㄧㄢ -8 -MACRO@TIMEZONE_STANDARD ㄇㄨˋ-ㄑㄧㄢˊ-ㄕˊ-ㄑㄩ -8 -MACRO@TIMEZONE_GENERIC_SHORT ㄇㄨˋ-ㄑㄧㄢˊ-ㄕˊ-ㄑㄩ -8 ㏕ ㄅㄞˇ-ㄨㄢˋ -8 © ㄅㄢˇ-ㄑㄩㄢˊ -8 ⌬ ㄅㄣˇ-ㄏㄨㄢˊ -8 diff --git a/Source/Data/bin/cook.py b/Source/Data/bin/cook.py index ae1f710c7..25170302e 100755 --- a/Source/Data/bin/cook.py +++ b/Source/Data/bin/cook.py @@ -200,6 +200,12 @@ assert len(row) == 3, row output.append(tuple(row)) + with open(sys.argv[6]) as macro_file: + for line in macro_file: + row = line.rstrip().split(" ") + assert len(row) == 3, row + output.append(tuple(row)) + output = convert_vks_rows_to_sorted_kvs_rows(output) with open(sys.argv[-1], "w") as fout: fout.write(HEADER) diff --git a/Source/Engine/McBopomofoLM.cpp b/Source/Engine/McBopomofoLM.cpp index f3e078717..bd4066392 100644 --- a/Source/Engine/McBopomofoLM.cpp +++ b/Source/Engine/McBopomofoLM.cpp @@ -199,7 +199,7 @@ std::vector McBopomofoLM::filterA std::string replacement = m_externalConverter(value); value = replacement; } - if (insertedValues.find(value) == insertedValues.end()) { + if (!value.empty() && insertedValues.find(value) == insertedValues.end()) { results.emplace_back(value, unigram.score()); insertedValues.insert(value); } diff --git a/Source/InputMacro.swift b/Source/InputMacro.swift index bce044395..73c153142 100644 --- a/Source/InputMacro.swift +++ b/Source/InputMacro.swift @@ -144,6 +144,65 @@ fileprivate struct InputMacroTimeZoneShortGeneric: InputMacro { } } +fileprivate struct InputMacroThisYearGanZhi: InputMacro { + var name: String { + "MACRO@THIS_YEAR_GANZHI" + } + + var replacement: String { + func ganshi(year: Int) -> String { + let gan = ["癸", "甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬"] + let zhi = ["亥", "子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌"] + + if year < 4 { + let year = year * -1 + let base = 60 - (year + 2) % 60 + let ganBase = base % 10 + let zhiBase = base % 12 + return gan[ganBase] + zhi[zhiBase] + "年" + } + let base = (year - 3) % 60 + let ganBase = base % 10 + let zhiBase = base % 12 + return gan[ganBase] + zhi[zhiBase] + "年" + } + let date = Date() + let calendar = Calendar(identifier: .gregorian) + let year = calendar.component(.year, from: date) + return ganshi(year: year) + } +} + +fileprivate struct InputMacroThisYearWoodRat: InputMacro { + var name: String { + "MACRO@THIS_YEAR_WOOD_RAT" + } + + var replacement: String { + func woodRat(year: Int) -> String { + let gan = ["水", "木", "木", "火", "火", "土", "土", "金", "金", "水"] + let zhi = ["豬", "鼠", "牛", "虎", "兔", "龍", "蛇", "馬", "羊", "猴", "雞", "狗"] + + if year < 4 { + let year = year * -1 + let base = 60 - (year + 2) % 60 + let ganBase = base % 10 + let zhiBase = base % 12 + return gan[ganBase] + zhi[zhiBase] + "年" + } + let base = (year - 3) % 60 + let ganBase = base % 10 + let zhiBase = base % 12 + return gan[ganBase] + zhi[zhiBase] + "年" + } + + let date = Date() + let calendar = Calendar(identifier: .gregorian) + let year = calendar.component(.year, from: date) + return woodRat(year: year) + } +} + class InputMacroController: NSObject { @objc static let shared = InputMacroController() @@ -158,6 +217,8 @@ class InputMacroController: NSObject { InputMacroTimeNowMedium(), InputMacroTimeZoneStandard(), InputMacroTimeZoneShortGeneric(), + InputMacroThisYearGanZhi(), + InputMacroThisYearWoodRat(), ] @objc From 7c335ac07004f90476c3fa135aff9ce5843cdf78 Mon Sep 17 00:00:00 2001 From: zonble Date: Sat, 9 Dec 2023 05:44:57 +0800 Subject: [PATCH 3/7] Adds additional macros for Chinese years. --- Source/Data/Macros.txt | 10 +++- Source/InputMacro.swift | 116 ++++++++++++++++++++++++++++------------ 2 files changed, 92 insertions(+), 34 deletions(-) diff --git a/Source/Data/Macros.txt b/Source/Data/Macros.txt index d1433fbc9..2b9454d73 100644 --- a/Source/Data/Macros.txt +++ b/Source/Data/Macros.txt @@ -17,5 +17,13 @@ MACRO@TIMEZONE_STANDARD ㄙㄨㄛˇ-ㄗㄞˋ-ㄕˊ-ㄑㄩ -8 MACRO@TIMEZONE_GENERIC_SHORT ㄙㄨㄛˇ-ㄗㄞˋ-ㄕˊ-ㄑㄩ -8 今年干支 ㄐㄧㄣ-ㄋㄧㄢˊ-ㄍㄢ-ㄓ -8 MACRO@THIS_YEAR_GANZHI ㄐㄧㄣ-ㄋㄧㄢˊ-ㄍㄢ-ㄓ -8 +去年干支 ㄑㄩˋ-ㄋㄧㄢˊ-ㄍㄢ-ㄓ -8 +MACRO@LAST_YEAR_GANZHI ㄑㄩˋ-ㄋㄧㄢˊ-ㄍㄢ-ㄓ -8 +明年干支 ㄇㄧㄥˊ-ㄋㄧㄢˊ-ㄍㄢ-ㄓ -8 +MACRO@NEXT_YEAR_GANZHI ㄇㄧㄥˊ-ㄋㄧㄢˊ-ㄍㄢ-ㄓ -8 今年生肖 ㄐㄧㄣ-ㄋㄧㄢˊ-ㄕㄥ-ㄒㄧㄠˋ -8 -MACRO@THIS_YEAR_WOOD_RAT ㄐㄧㄣ-ㄋㄧㄢˊ-ㄕㄥ-ㄒㄧㄠˋ -8 \ No newline at end of file +MACRO@THIS_YEAR_WOOD_RAT ㄐㄧㄣ-ㄋㄧㄢˊ-ㄕㄥ-ㄒㄧㄠˋ -8 +去年生肖 ㄑㄩˋ-ㄋㄧㄢˊ-ㄕㄥ-ㄒㄧㄠˋ -8 +MACRO@LAST_YEAR_WOOD_RAT ㄑㄩˋ-ㄋㄧㄢˊ-ㄕㄥ-ㄒㄧㄠˋ -8 +明年生肖 ㄇㄧㄥˊ-ㄋㄧㄢˊ-ㄕㄥ-ㄒㄧㄠˋ -8 +MACRO@NEXT_YEAR_WOOD_RAT ㄇㄧㄥˊ-ㄋㄧㄢˊ-ㄕㄥ-ㄒㄧㄠˋ -8 \ No newline at end of file diff --git a/Source/InputMacro.swift b/Source/InputMacro.swift index 73c153142..c3389d627 100644 --- a/Source/InputMacro.swift +++ b/Source/InputMacro.swift @@ -144,28 +144,38 @@ fileprivate struct InputMacroTimeZoneShortGeneric: InputMacro { } } +fileprivate func getYearBase(year: Int) -> (Int, Int) { + let base: Int = { + if year < 4 { + let year = year * -1 + return 60 - (year + 2) % 60 + } + return (year - 3) % 60 + }() + return (base % 10, base % 12) +} + + +fileprivate func ganshi(year: Int) -> String { + let gan = ["癸", "甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬"] + let zhi = ["亥", "子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌"] + let (ganBase, zhiBase) = getYearBase(year: year) + return gan[ganBase] + zhi[zhiBase] + "年" +} + +func woodRat(year: Int) -> String { + let gan = ["水", "木", "木", "火", "火", "土", "土", "金", "金", "水"] + let zhi = ["豬", "鼠", "牛", "虎", "兔", "龍", "蛇", "馬", "羊", "猴", "雞", "狗"] + let (ganBase, zhiBase) = getYearBase(year: year) + return gan[ganBase] + zhi[zhiBase] + "年" +} + fileprivate struct InputMacroThisYearGanZhi: InputMacro { var name: String { "MACRO@THIS_YEAR_GANZHI" } var replacement: String { - func ganshi(year: Int) -> String { - let gan = ["癸", "甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬"] - let zhi = ["亥", "子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌"] - - if year < 4 { - let year = year * -1 - let base = 60 - (year + 2) % 60 - let ganBase = base % 10 - let zhiBase = base % 12 - return gan[ganBase] + zhi[zhiBase] + "年" - } - let base = (year - 3) % 60 - let ganBase = base % 10 - let zhiBase = base % 12 - return gan[ganBase] + zhi[zhiBase] + "年" - } let date = Date() let calendar = Calendar(identifier: .gregorian) let year = calendar.component(.year, from: date) @@ -173,29 +183,38 @@ fileprivate struct InputMacroThisYearGanZhi: InputMacro { } } +fileprivate struct InputMacroLastYearGanZhi: InputMacro { + var name: String { + "MACRO@LAST_YEAR_GANZHI" + } + + var replacement: String { + let date = Date() + let calendar = Calendar(identifier: .gregorian) + let year = calendar.component(.year, from: date) + return ganshi(year: year - 1) + } +} + +fileprivate struct InputMacroNextYearGanZhi: InputMacro { + var name: String { + "MACRO@NEXT_YEAR_GANZHI" + } + + var replacement: String { + let date = Date() + let calendar = Calendar(identifier: .gregorian) + let year = calendar.component(.year, from: date) + return ganshi(year: year + 1) + } +} + fileprivate struct InputMacroThisYearWoodRat: InputMacro { var name: String { "MACRO@THIS_YEAR_WOOD_RAT" } var replacement: String { - func woodRat(year: Int) -> String { - let gan = ["水", "木", "木", "火", "火", "土", "土", "金", "金", "水"] - let zhi = ["豬", "鼠", "牛", "虎", "兔", "龍", "蛇", "馬", "羊", "猴", "雞", "狗"] - - if year < 4 { - let year = year * -1 - let base = 60 - (year + 2) % 60 - let ganBase = base % 10 - let zhiBase = base % 12 - return gan[ganBase] + zhi[zhiBase] + "年" - } - let base = (year - 3) % 60 - let ganBase = base % 10 - let zhiBase = base % 12 - return gan[ganBase] + zhi[zhiBase] + "年" - } - let date = Date() let calendar = Calendar(identifier: .gregorian) let year = calendar.component(.year, from: date) @@ -203,6 +222,33 @@ fileprivate struct InputMacroThisYearWoodRat: InputMacro { } } +fileprivate struct InputMacroLastYearWoodRat: InputMacro { + var name: String { + "MACRO@LAST_YEAR_WOOD_RAT" + } + + var replacement: String { + let date = Date() + let calendar = Calendar(identifier: .gregorian) + let year = calendar.component(.year, from: date) + return woodRat(year: year - 1) + } +} + +fileprivate struct InputMacroNextYearWoodRat: InputMacro { + var name: String { + "MACRO@NEXT_YEAR_WOOD_RAT" + } + + var replacement: String { + let date = Date() + let calendar = Calendar(identifier: .gregorian) + let year = calendar.component(.year, from: date) + return woodRat(year: year + 1) + } +} + + class InputMacroController: NSObject { @objc static let shared = InputMacroController() @@ -218,7 +264,11 @@ class InputMacroController: NSObject { InputMacroTimeZoneStandard(), InputMacroTimeZoneShortGeneric(), InputMacroThisYearGanZhi(), + InputMacroLastYearGanZhi(), + InputMacroNextYearGanZhi(), InputMacroThisYearWoodRat(), + InputMacroLastYearWoodRat(), + InputMacroNextYearWoodRat(), ] @objc From 971870e463e91e33eb3adba7581eb2eb9a56d299 Mon Sep 17 00:00:00 2001 From: zonble Date: Sat, 9 Dec 2023 13:30:59 +0800 Subject: [PATCH 4/7] Adds input macros for yesterday and tomorrow. --- Source/Data/Macros.txt | 16 +++- Source/InputMacro.swift | 180 +++++++++++++++++++++++++--------------- 2 files changed, 125 insertions(+), 71 deletions(-) diff --git a/Source/Data/Macros.txt b/Source/Data/Macros.txt index 2b9454d73..ec23057d6 100644 --- a/Source/Data/Macros.txt +++ b/Source/Data/Macros.txt @@ -1,8 +1,18 @@ 今天日期 ㄐㄧㄣ-ㄊㄧㄢ-ㄖˋ-ㄑㄧˊ -8 MACRO@DATE_TODAY_SHORT ㄐㄧㄣ-ㄊㄧㄢ-ㄖˋ-ㄑㄧˊ -8 -MACRO@DATE_TODAY_MEDIUEM ㄐㄧㄣ-ㄊㄧㄢ-ㄖˋ-ㄑㄧˊ -8 -MACRO@DATE_TODAY_MEDIUEM_ROC ㄐㄧㄣ-ㄊㄧㄢ-ㄖˋ-ㄑㄧˊ -8 -MACRO@DATE_TODAY_MEDIUEM_CHINESE ㄐㄧㄣ-ㄊㄧㄢ-ㄖˋ-ㄑㄧˊ -8 +MACRO@DATE_TODAY_MEDIUM ㄐㄧㄣ-ㄊㄧㄢ-ㄖˋ-ㄑㄧˊ -8 +MACRO@DATE_TODAY_MEDIUM_ROC ㄐㄧㄣ-ㄊㄧㄢ-ㄖˋ-ㄑㄧˊ -8 +MACRO@DATE_TODAY_MEDIUM_CHINESE ㄐㄧㄣ-ㄊㄧㄢ-ㄖˋ-ㄑㄧˊ -8 +昨天日期 ㄗㄨㄛˊ-ㄊㄧㄢ-ㄖˋ-ㄑㄧˊ -8 +MACRO@DATE_YESTERDAY_SHORT ㄗㄨㄛˊ-ㄊㄧㄢ-ㄖˋ-ㄑㄧˊ -8 +MACRO@DATE_YESTERDAY_MEDIUM ㄗㄨㄛˊ-ㄊㄧㄢ-ㄖˋ-ㄑㄧˊ -8 +MACRO@DATE_YESTERDAY_MEDIUM_ROC ㄗㄨㄛˊ-ㄊㄧㄢ-ㄖˋ-ㄑㄧˊ -8 +MACRO@DATE_YESTERDAY_MEDIUM_CHINESE ㄗㄨㄛˊ-ㄊㄧㄢ-ㄖˋ-ㄑㄧˊ -8 +明天日期 ㄇㄧㄥˊ-ㄊㄧㄢ-ㄖˋ-ㄑㄧˊ -8 +MACRO@DATE_TOMORROW_SHORT ㄇㄧㄥˊ-ㄊㄧㄢ-ㄖˋ-ㄑㄧˊ -8 +MACRO@DATE_TOMORROW_MEDIUM ㄇㄧㄥˊ-ㄊㄧㄢ-ㄖˋ-ㄑㄧˊ -8 +MACRO@DATE_TOMORROW_MEDIUM_ROC ㄇㄧㄥˊ-ㄊㄧㄢ-ㄖˋ-ㄑㄧˊ -8 +MACRO@DATE_TOMORROW_MEDIUM_CHINESE ㄇㄧㄥˊ-ㄊㄧㄢ-ㄖˋ-ㄑㄧˊ -8 現在時刻 ㄒㄧㄢˋ-ㄗㄞˋ-ㄕˊ-ㄎㄜˋ -8 MACRO@TIME_NOW_SHORT ㄒㄧㄢˋ-ㄗㄞˋ-ㄕˊ-ㄎㄜˋ -8 MACRO@TIME_NOW_MEDIUM ㄒㄧㄢˋ-ㄗㄞˋ-ㄕˊ-ㄎㄜˋ -8 diff --git a/Source/InputMacro.swift b/Source/InputMacro.swift index c3389d627..f24b3d56a 100644 --- a/Source/InputMacro.swift +++ b/Source/InputMacro.swift @@ -28,72 +28,126 @@ protocol InputMacro { var replacement: String { get } } +fileprivate func formatDate(date: Date, style: DateFormatter.Style, calendar: Calendar = Calendar(identifier: .gregorian)) -> String { + let dateFormatter = DateFormatter() + dateFormatter.dateStyle = style + dateFormatter.timeStyle = .none + dateFormatter.locale = Locale(identifier: "zh_Hant_TW") + dateFormatter.calendar = calendar + return dateFormatter.string(from: date) +} + fileprivate struct InputMacroDateTodayShort: InputMacro { - var name: String { - "MACRO@DATE_TODAY_SHORT" - } + var name: String { "MACRO@DATE_TODAY_SHORT" } var replacement: String { let date = Date() - let dateFormatter = DateFormatter() - dateFormatter.dateStyle = .short - dateFormatter.timeStyle = .none - dateFormatter.locale = Locale(identifier: "zh_Hant_TW") - return dateFormatter.string(from: date) + return formatDate(date: date, style: .short) } } -fileprivate struct InputMacroDateTodayMedium: InputMacro { - var name: String { - "MACRO@DATE_TODAY_MEDIUEM" +fileprivate struct InputMacroDateYesterdayShort: InputMacro { + var name: String { "MACRO@DATE_YESTERDAY_SHORT" } + + var replacement: String { + let date = Date().addingTimeInterval(60 * 60 * -24) + return formatDate(date: date, style: .short) } +} + +fileprivate struct InputMacroDateTomorrowShort: InputMacro { + var name: String { "MACRO@DATE_TOMORROW_SHORT" } + + var replacement: String { + let date = Date().addingTimeInterval(60 * 60 * 24) + return formatDate(date: date, style: .short) + } +} + +fileprivate struct InputMacroDateTodayMedium: InputMacro { + var name: String { "MACRO@DATE_TODAY_MEDIUM" } var replacement: String { let date = Date() - let dateFormatter = DateFormatter() - dateFormatter.dateStyle = .medium - dateFormatter.timeStyle = .none - dateFormatter.locale = Locale(identifier: "zh_Hant_TW") - return dateFormatter.string(from: date) + return formatDate(date: date, style: .medium) } } -fileprivate struct InputMacroDateTodayMediumROC: InputMacro { - var name: String { - "MACRO@DATE_TODAY_MEDIUEM_ROC" +fileprivate struct InputMacroDateYesterdayMedium: InputMacro { + var name: String { "MACRO@DATE_YESTERDAY_MEDIUM" } + + var replacement: String { + let date = Date().addingTimeInterval(60 * 60 * -24) + return formatDate(date: date, style: .medium) } +} + +fileprivate struct InputMacroDateTomorrowMedium: InputMacro { + var name: String { "MACRO@DATE_TOMORROW_MEDIUM" } + + var replacement: String { + let date = Date().addingTimeInterval(60 * 60 * 24) + return formatDate(date: date, style: .medium) + } +} + +fileprivate struct InputMacroDateTodayMediumROC: InputMacro { + var name: String { "MACRO@DATE_TODAY_MEDIUM_ROC" } var replacement: String { let date = Date() - let dateFormatter = DateFormatter() - dateFormatter.dateStyle = .medium - dateFormatter.timeStyle = .none - dateFormatter.locale = Locale(identifier: "zh_Hant_TW") - dateFormatter.calendar = Calendar(identifier: .republicOfChina) - return dateFormatter.string(from: date) + return formatDate(date: date, style: .medium, calendar: Calendar(identifier: .republicOfChina)) } } -fileprivate struct InputMacroDateTodayMediumChinese: InputMacro { - var name: String { - "MACRO@DATE_TODAY_MEDIUEM_CHINESE" +fileprivate struct InputMacroDateYesterdayMediumROC: InputMacro { + var name: String { "MACRO@DATE_YESTERDAY_MEDIUM_ROC" } + + var replacement: String { + let date = Date().addingTimeInterval(60 * 60 * -24) + return formatDate(date: date, style: .medium, calendar: Calendar(identifier: .republicOfChina)) } +} + +fileprivate struct InputMacroDateTomorrowMediumROC: InputMacro { + var name: String { "MACRO@DATE_TOMORROW_MEDIUM_ROC" } + + var replacement: String { + let date = Date().addingTimeInterval(60 * 60 * 24) + return formatDate(date: date, style: .medium, calendar: Calendar(identifier: .republicOfChina)) + } +} + + +fileprivate struct InputMacroDateTodayMediumChinese: InputMacro { + var name: String { "MACRO@DATE_TODAY_MEDIUM_CHINESE" } var replacement: String { let date = Date() - let dateFormatter = DateFormatter() - dateFormatter.dateStyle = .medium - dateFormatter.timeStyle = .none - dateFormatter.locale = Locale(identifier: "zh_Hant_TW") - dateFormatter.calendar = Calendar(identifier: .chinese) - return dateFormatter.string(from: date) + return formatDate(date: date, style: .medium, calendar: Calendar(identifier: .chinese)) } } -fileprivate struct InputMacroTimeNowShort: InputMacro { - var name: String { - "MACRO@TIME_NOW_SHORT" +fileprivate struct InputMacroDateYesterdayMediumChinese: InputMacro { + var name: String { "MACRO@DATE_YESTERDAY_MEDIUM_CHINESE" } + + var replacement: String { + let date = Date().addingTimeInterval(60 * 60 * -24) + return formatDate(date: date, style: .medium, calendar: Calendar(identifier: .chinese)) } +} + +fileprivate struct InputMacroDateTomorrowMediumChinese: InputMacro { + var name: String { "MACRO@DATE_TOMORROW_MEDIUM_CHINESE" } + + var replacement: String { + let date = Date().addingTimeInterval(60 * 60 * 24) + return formatDate(date: date, style: .medium, calendar: Calendar(identifier: .chinese)) + } +} + +fileprivate struct InputMacroTimeNowShort: InputMacro { + var name: String { "MACRO@TIME_NOW_SHORT" } var replacement: String { let date = Date() @@ -106,9 +160,7 @@ fileprivate struct InputMacroTimeNowShort: InputMacro { } fileprivate struct InputMacroTimeNowMedium: InputMacro { - var name: String { - "MACRO@TIME_NOW_MEDIUM" - } + var name: String { "MACRO@TIME_NOW_MEDIUM" } var replacement: String { let date = Date() @@ -121,9 +173,7 @@ fileprivate struct InputMacroTimeNowMedium: InputMacro { } fileprivate struct InputMacroTimeZoneStandard: InputMacro { - var name: String { - "MACRO@TIMEZONE_STANDARD" - } + var name: String { "MACRO@TIMEZONE_STANDARD" } var replacement: String { let timezone = TimeZone.current @@ -133,9 +183,7 @@ fileprivate struct InputMacroTimeZoneStandard: InputMacro { } fileprivate struct InputMacroTimeZoneShortGeneric: InputMacro { - var name: String { - "MACRO@TIMEZONE_GENERIC_SHORT" - } + var name: String { "MACRO@TIMEZONE_GENERIC_SHORT" } var replacement: String { let timezone = TimeZone.current @@ -163,7 +211,7 @@ fileprivate func ganshi(year: Int) -> String { return gan[ganBase] + zhi[zhiBase] + "年" } -func woodRat(year: Int) -> String { +fileprivate func chineseZodiac(year: Int) -> String { let gan = ["水", "木", "木", "火", "火", "土", "土", "金", "金", "水"] let zhi = ["豬", "鼠", "牛", "虎", "兔", "龍", "蛇", "馬", "羊", "猴", "雞", "狗"] let (ganBase, zhiBase) = getYearBase(year: year) @@ -171,9 +219,7 @@ func woodRat(year: Int) -> String { } fileprivate struct InputMacroThisYearGanZhi: InputMacro { - var name: String { - "MACRO@THIS_YEAR_GANZHI" - } + var name: String { "MACRO@THIS_YEAR_GANZHI" } var replacement: String { let date = Date() @@ -184,9 +230,7 @@ fileprivate struct InputMacroThisYearGanZhi: InputMacro { } fileprivate struct InputMacroLastYearGanZhi: InputMacro { - var name: String { - "MACRO@LAST_YEAR_GANZHI" - } + var name: String { "MACRO@LAST_YEAR_GANZHI" } var replacement: String { let date = Date() @@ -197,9 +241,7 @@ fileprivate struct InputMacroLastYearGanZhi: InputMacro { } fileprivate struct InputMacroNextYearGanZhi: InputMacro { - var name: String { - "MACRO@NEXT_YEAR_GANZHI" - } + var name: String { "MACRO@NEXT_YEAR_GANZHI" } var replacement: String { let date = Date() @@ -210,41 +252,35 @@ fileprivate struct InputMacroNextYearGanZhi: InputMacro { } fileprivate struct InputMacroThisYearWoodRat: InputMacro { - var name: String { - "MACRO@THIS_YEAR_WOOD_RAT" - } + var name: String { "MACRO@THIS_YEAR_WOOD_RAT" } var replacement: String { let date = Date() let calendar = Calendar(identifier: .gregorian) let year = calendar.component(.year, from: date) - return woodRat(year: year) + return chineseZodiac(year: year) } } fileprivate struct InputMacroLastYearWoodRat: InputMacro { - var name: String { - "MACRO@LAST_YEAR_WOOD_RAT" - } + var name: String { "MACRO@LAST_YEAR_WOOD_RAT" } var replacement: String { let date = Date() let calendar = Calendar(identifier: .gregorian) let year = calendar.component(.year, from: date) - return woodRat(year: year - 1) + return chineseZodiac(year: year - 1) } } fileprivate struct InputMacroNextYearWoodRat: InputMacro { - var name: String { - "MACRO@NEXT_YEAR_WOOD_RAT" - } + var name: String { "MACRO@NEXT_YEAR_WOOD_RAT" } var replacement: String { let date = Date() let calendar = Calendar(identifier: .gregorian) let year = calendar.component(.year, from: date) - return woodRat(year: year + 1) + return chineseZodiac(year: year + 1) } } @@ -256,9 +292,17 @@ class InputMacroController: NSObject { private var macros: [InputMacro] = [ InputMacroDateTodayShort(), + InputMacroDateYesterdayShort(), + InputMacroDateTomorrowShort(), InputMacroDateTodayMedium(), + InputMacroDateYesterdayMedium(), + InputMacroDateTomorrowMedium(), InputMacroDateTodayMediumROC(), + InputMacroDateYesterdayMediumROC(), + InputMacroDateTomorrowMediumROC(), InputMacroDateTodayMediumChinese(), + InputMacroDateYesterdayMediumChinese(), + InputMacroDateTomorrowMediumChinese(), InputMacroTimeNowShort(), InputMacroTimeNowMedium(), InputMacroTimeZoneStandard(), From c669b9107aa9483289f64b04411a1fc68c6676f3 Mon Sep 17 00:00:00 2001 From: zonble Date: Mon, 11 Dec 2023 12:45:26 +0800 Subject: [PATCH 5/7] Uses a separated converter for macros. Also renames wood rat to Chinese zodiac. --- Source/Engine/McBopomofoLM.cpp | 9 +++++ Source/Engine/McBopomofoLM.h | 3 ++ Source/InputMacro.swift | 67 ++++++++++++++++------------------ Source/LanguageModelManager.mm | 7 +++- 4 files changed, 49 insertions(+), 37 deletions(-) diff --git a/Source/Engine/McBopomofoLM.cpp b/Source/Engine/McBopomofoLM.cpp index bd4066392..58af8d759 100644 --- a/Source/Engine/McBopomofoLM.cpp +++ b/Source/Engine/McBopomofoLM.cpp @@ -176,6 +176,10 @@ void McBopomofoLM::setExternalConverter(std::function m_externalConverter = externalConverter; } +void McBopomofoLM::setMacroConverter(std::function macroConverter) { + m_macroConverter = macroConverter; +} + std::vector McBopomofoLM::filterAndTransformUnigrams(const std::vector unigrams, const std::unordered_set& excludedValues, std::unordered_set& insertedValues) { std::vector results; @@ -189,12 +193,17 @@ std::vector McBopomofoLM::filterA } std::string value = originalValue; + if (m_phraseReplacementEnabled) { std::string replacement = m_phraseReplacement.valueForKey(value); if (!replacement.empty()) { value = replacement; } } + if (m_macroConverter) { + std::string replacement = m_macroConverter(value); + value = replacement; + } if (m_externalConverterEnabled && m_externalConverter) { std::string replacement = m_externalConverter(value); value = replacement; diff --git a/Source/Engine/McBopomofoLM.h b/Source/Engine/McBopomofoLM.h index 80ab5e154..917137da7 100644 --- a/Source/Engine/McBopomofoLM.h +++ b/Source/Engine/McBopomofoLM.h @@ -101,6 +101,8 @@ class McBopomofoLM : public Formosa::Gramambular2::LanguageModel { bool externalConverterEnabled() const; /// Sets a lambda to let the values of unigrams could be converted by it. void setExternalConverter(std::function externalConverter); + /// Sets a lambda to convert the macros. + void setMacroConverter(std::function macroConverter); const std::vector associatedPhrasesForKey(const std::string& key); bool hasAssociatedPhrasesForKey(const std::string& key); @@ -128,6 +130,7 @@ class McBopomofoLM : public Formosa::Gramambular2::LanguageModel { bool m_phraseReplacementEnabled; bool m_externalConverterEnabled; std::function m_externalConverter; + std::function m_macroConverter; }; }; diff --git a/Source/InputMacro.swift b/Source/InputMacro.swift index f24b3d56a..21ff61ac3 100644 --- a/Source/InputMacro.swift +++ b/Source/InputMacro.swift @@ -28,6 +28,8 @@ protocol InputMacro { var replacement: String { get } } +// MARK: - Date + fileprivate func formatDate(date: Date, style: DateFormatter.Style, calendar: Calendar = Calendar(identifier: .gregorian)) -> String { let dateFormatter = DateFormatter() dateFormatter.dateStyle = style @@ -146,6 +148,8 @@ fileprivate struct InputMacroDateTomorrowMediumChinese: InputMacro { } } +// MARK: - Time + fileprivate struct InputMacroTimeNowShort: InputMacro { var name: String { "MACRO@TIME_NOW_SHORT" } @@ -172,6 +176,8 @@ fileprivate struct InputMacroTimeNowMedium: InputMacro { } } +// MARK: - Time Zone + fileprivate struct InputMacroTimeZoneStandard: InputMacro { var name: String { "MACRO@TIMEZONE_STANDARD" } @@ -192,18 +198,20 @@ fileprivate struct InputMacroTimeZoneShortGeneric: InputMacro { } } +// MARK: - Ganzhi + +fileprivate func getCurrentYear() -> Int { + let date = Date() + let calendar = Calendar(identifier: .gregorian) + let year = calendar.component(.year, from: date) + return year +} + fileprivate func getYearBase(year: Int) -> (Int, Int) { - let base: Int = { - if year < 4 { - let year = year * -1 - return 60 - (year + 2) % 60 - } - return (year - 3) % 60 - }() + let base: Int = year < 4 ? 60 - ((year * -1) + 2) % 60 : (year - 3) % 60 return (base % 10, base % 12) } - fileprivate func ganshi(year: Int) -> String { let gan = ["癸", "甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬"] let zhi = ["亥", "子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌"] @@ -222,9 +230,7 @@ fileprivate struct InputMacroThisYearGanZhi: InputMacro { var name: String { "MACRO@THIS_YEAR_GANZHI" } var replacement: String { - let date = Date() - let calendar = Calendar(identifier: .gregorian) - let year = calendar.component(.year, from: date) + let year = getCurrentYear() return ganshi(year: year) } } @@ -233,9 +239,7 @@ fileprivate struct InputMacroLastYearGanZhi: InputMacro { var name: String { "MACRO@LAST_YEAR_GANZHI" } var replacement: String { - let date = Date() - let calendar = Calendar(identifier: .gregorian) - let year = calendar.component(.year, from: date) + let year = getCurrentYear() return ganshi(year: year - 1) } } @@ -244,46 +248,39 @@ fileprivate struct InputMacroNextYearGanZhi: InputMacro { var name: String { "MACRO@NEXT_YEAR_GANZHI" } var replacement: String { - let date = Date() - let calendar = Calendar(identifier: .gregorian) - let year = calendar.component(.year, from: date) + let year = getCurrentYear() return ganshi(year: year + 1) } } -fileprivate struct InputMacroThisYearWoodRat: InputMacro { - var name: String { "MACRO@THIS_YEAR_WOOD_RAT" } +fileprivate struct InputMacroThisYearChineseZodiac: InputMacro { + var name: String { "MACRO@THIS_YEAR_CHINESE_ZODIAC" } var replacement: String { - let date = Date() - let calendar = Calendar(identifier: .gregorian) - let year = calendar.component(.year, from: date) + let year = getCurrentYear() return chineseZodiac(year: year) } } -fileprivate struct InputMacroLastYearWoodRat: InputMacro { - var name: String { "MACRO@LAST_YEAR_WOOD_RAT" } +fileprivate struct InputMacroLastYearChineseZodiac: InputMacro { + var name: String { "MACRO@LAST_YEAR_CHINESE_ZODIAC" } var replacement: String { - let date = Date() - let calendar = Calendar(identifier: .gregorian) - let year = calendar.component(.year, from: date) + let year = getCurrentYear() return chineseZodiac(year: year - 1) } } -fileprivate struct InputMacroNextYearWoodRat: InputMacro { - var name: String { "MACRO@NEXT_YEAR_WOOD_RAT" } +fileprivate struct InputMacroNextYearChineseZodiac: InputMacro { + var name: String { "MACRO@NEXT_YEAR_CHINESE_ZODIAC" } var replacement: String { - let date = Date() - let calendar = Calendar(identifier: .gregorian) - let year = calendar.component(.year, from: date) + let year = getCurrentYear() return chineseZodiac(year: year + 1) } } +// MARK: - InputMacroController class InputMacroController: NSObject { @objc @@ -310,9 +307,9 @@ class InputMacroController: NSObject { InputMacroThisYearGanZhi(), InputMacroLastYearGanZhi(), InputMacroNextYearGanZhi(), - InputMacroThisYearWoodRat(), - InputMacroLastYearWoodRat(), - InputMacroNextYearWoodRat(), + InputMacroThisYearChineseZodiac(), + InputMacroLastYearChineseZodiac(), + InputMacroNextYearChineseZodiac(), ] @objc diff --git a/Source/LanguageModelManager.mm b/Source/LanguageModelManager.mm index 7e83e4d41..097cdaca3 100644 --- a/Source/LanguageModelManager.mm +++ b/Source/LanguageModelManager.mm @@ -101,11 +101,13 @@ + (void)loadUserPhraseReplacement + (void)setupDataModelValueConverter { - auto converter = [](std::string input) { + auto macroConverter = [](std::string input) { NSString *inputText = [NSString stringWithUTF8String:input.c_str()]; NSString *handled = [[InputMacroController shared] handle:inputText]; - input = std::string(handled.UTF8String); + return std::string(handled.UTF8String); + }; + auto converter = [](std::string input) { if (!Preferences.chineseConversionEnabled) { return input; } @@ -123,6 +125,7 @@ + (void)setupDataModelValueConverter return std::string(text.UTF8String); }; + gLanguageModelMcBopomofo.setMacroConverter(macroConverter); gLanguageModelMcBopomofo.setExternalConverter(converter); gLanguageModelPlainBopomofo.setExternalConverter(converter); } From 95854f16d331eec8bbf4e884cdeb3031b96161a7 Mon Sep 17 00:00:00 2001 From: zonble Date: Mon, 11 Dec 2023 14:10:29 +0800 Subject: [PATCH 6/7] Updates data. --- Source/Data/Macros.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/Data/Macros.txt b/Source/Data/Macros.txt index ec23057d6..3c2961640 100644 --- a/Source/Data/Macros.txt +++ b/Source/Data/Macros.txt @@ -32,8 +32,8 @@ MACRO@LAST_YEAR_GANZHI ㄑㄩˋ-ㄋㄧㄢˊ-ㄍㄢ-ㄓ -8 明年干支 ㄇㄧㄥˊ-ㄋㄧㄢˊ-ㄍㄢ-ㄓ -8 MACRO@NEXT_YEAR_GANZHI ㄇㄧㄥˊ-ㄋㄧㄢˊ-ㄍㄢ-ㄓ -8 今年生肖 ㄐㄧㄣ-ㄋㄧㄢˊ-ㄕㄥ-ㄒㄧㄠˋ -8 -MACRO@THIS_YEAR_WOOD_RAT ㄐㄧㄣ-ㄋㄧㄢˊ-ㄕㄥ-ㄒㄧㄠˋ -8 +MACRO@THIS_YEAR_CHINESE_ZODIAC ㄐㄧㄣ-ㄋㄧㄢˊ-ㄕㄥ-ㄒㄧㄠˋ -8 去年生肖 ㄑㄩˋ-ㄋㄧㄢˊ-ㄕㄥ-ㄒㄧㄠˋ -8 -MACRO@LAST_YEAR_WOOD_RAT ㄑㄩˋ-ㄋㄧㄢˊ-ㄕㄥ-ㄒㄧㄠˋ -8 +MACRO@LAST_YEAR_CHINESE_ZODIAC ㄑㄩˋ-ㄋㄧㄢˊ-ㄕㄥ-ㄒㄧㄠˋ -8 明年生肖 ㄇㄧㄥˊ-ㄋㄧㄢˊ-ㄕㄥ-ㄒㄧㄠˋ -8 -MACRO@NEXT_YEAR_WOOD_RAT ㄇㄧㄥˊ-ㄋㄧㄢˊ-ㄕㄥ-ㄒㄧㄠˋ -8 \ No newline at end of file +MACRO@NEXT_YEAR_CHINESE_ZODIAC ㄇㄧㄥˊ-ㄋㄧㄢˊ-ㄕㄥ-ㄒㄧㄠˋ -8 \ No newline at end of file From 7e19809095d347e2c2dc9e067292f541074fa11b Mon Sep 17 00:00:00 2001 From: zonble Date: Tue, 12 Dec 2023 00:03:29 +0800 Subject: [PATCH 7/7] Uses a dictionary to look up the macros. --- Source/InputMacro.swift | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/Source/InputMacro.swift b/Source/InputMacro.swift index 21ff61ac3..036bcd7a6 100644 --- a/Source/InputMacro.swift +++ b/Source/InputMacro.swift @@ -212,7 +212,7 @@ fileprivate func getYearBase(year: Int) -> (Int, Int) { return (base % 10, base % 12) } -fileprivate func ganshi(year: Int) -> String { +fileprivate func ganzhi(year: Int) -> String { let gan = ["癸", "甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬"] let zhi = ["亥", "子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌"] let (ganBase, zhiBase) = getYearBase(year: year) @@ -231,7 +231,7 @@ fileprivate struct InputMacroThisYearGanZhi: InputMacro { var replacement: String { let year = getCurrentYear() - return ganshi(year: year) + return ganzhi(year: year) } } @@ -240,7 +240,7 @@ fileprivate struct InputMacroLastYearGanZhi: InputMacro { var replacement: String { let year = getCurrentYear() - return ganshi(year: year - 1) + return ganzhi(year: year - 1) } } @@ -249,7 +249,7 @@ fileprivate struct InputMacroNextYearGanZhi: InputMacro { var replacement: String { let year = getCurrentYear() - return ganshi(year: year + 1) + return ganzhi(year: year + 1) } } @@ -286,8 +286,8 @@ class InputMacroController: NSObject { @objc static let shared = InputMacroController() - private var macros: [InputMacro] = - [ + private var macros: [String:InputMacro] = { + let macros: [InputMacro] = [ InputMacroDateTodayShort(), InputMacroDateYesterdayShort(), InputMacroDateTomorrowShort(), @@ -311,13 +311,18 @@ class InputMacroController: NSObject { InputMacroLastYearChineseZodiac(), InputMacroNextYearChineseZodiac(), ] + var map:[String:InputMacro] = [:] + macros.forEach { macro in + map[macro.name] = macro + } + return map + } () + @objc func handle(_ input: String) -> String { - for inputMacro in macros { - if inputMacro.name == input { - return inputMacro.replacement - } + if let macro = macros[input] { + return macro.replacement } return input }