diff --git a/Fire.xcodeproj/project.pbxproj b/Fire.xcodeproj/project.pbxproj index d7a0fcd..eaebcbd 100644 --- a/Fire.xcodeproj/project.pbxproj +++ b/Fire.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 45B76CA92AEA6042009AFABD /* PunctuationConversion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45B76CA82AEA6042009AFABD /* PunctuationConversion.swift */; }; 6753419E2AB54A3A00757F76 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6753419D2AB54A3A00757F76 /* main.cpp */; }; 675341A72AB54AEA00757F76 /* sqlite3.c in Sources */ = {isa = PBXBuildFile; fileRef = 675341A52AB54AEA00757F76 /* sqlite3.c */; }; 67AA47FF2AB733860073AC86 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 67C9A0232AB53ED3000B5281 /* Assets.xcassets */; }; @@ -67,6 +68,7 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 45B76CA82AEA6042009AFABD /* PunctuationConversion.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PunctuationConversion.swift; sourceTree = ""; }; 6753419B2AB54A3A00757F76 /* TableBuilder */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = TableBuilder; sourceTree = BUILT_PRODUCTS_DIR; }; 6753419D2AB54A3A00757F76 /* main.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; 675341A52AB54AEA00757F76 /* sqlite3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqlite3.c; sourceTree = ""; }; @@ -196,6 +198,7 @@ 67C9A0062AB53E83000B5281 /* Fire.swift */, 67C9A0222AB53ED3000B5281 /* FireInputServer.swift */, 67C9A0072AB53E83000B5281 /* FireInputController.swift */, + 45B76CA82AEA6042009AFABD /* PunctuationConversion.swift */, 67C9A0022AB53E83000B5281 /* InputSource.swift */, 67C9A0012AB53E83000B5281 /* MainMenu.xib */, 67C9A0042AB53E83000B5281 /* StatusBar.swift */, @@ -432,6 +435,7 @@ 67C9A0422AB53ED3000B5281 /* ThesaurusPane.swift in Sources */, 67C9A0002AB53E62000B5281 /* ModifierKeyUpChecker.swift in Sources */, 67C9A0442AB53ED3000B5281 /* CandidatesWindow.swift in Sources */, + 45B76CA92AEA6042009AFABD /* PunctuationConversion.swift in Sources */, 67C9A0362AB53ED3000B5281 /* DictManager.swift in Sources */, 67C9A0582AB5429B000B5281 /* sqlite3.c in Sources */, 67C99FFD2AB53E62000B5281 /* ToastWindow.swift in Sources */, @@ -619,7 +623,7 @@ CURRENT_PROJECT_VERSION = 1; DEPLOYMENT_LOCATION = YES; DEVELOPMENT_TEAM = T68XK6867P; - DSTROOT = "/Library/Input Methods"; + DSTROOT = "$HOME/Library/Input Methods"; ENABLE_HARDENED_RUNTIME = YES; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", diff --git a/Fire/Fire.swift b/Fire/Fire.swift index 30e3331..2d1ee18 100644 --- a/Fire/Fire.swift +++ b/Fire/Fire.swift @@ -20,24 +20,6 @@ class Fire: NSObject { var inputMode: InputMode = .zhhans - func transformPunctuation(_ origin: String) -> String? { - let isPunctuation = punctuation.keys.contains(origin) - if !isPunctuation { - return nil - } - let mode = Defaults[.punctuationMode] - if mode == .enUs { - return origin - } - if mode == .zhhans { - return punctuation[origin] - } - if mode == .custom { - return Defaults[.customPunctuationSettings][origin] - } - return nil - } - override init() { super.init() _ = InputSource.shared.onSelectChanged { selected in diff --git a/Fire/FireInputController.swift b/Fire/FireInputController.swift index 0ac920e..993d28d 100644 --- a/Fire/FireInputController.swift +++ b/Fire/FireInputController.swift @@ -272,7 +272,7 @@ class FireInputController: IMKInputController { } // 如果输入的字符是标点符号,转换标点符号为中文符号 - if inputMode == .zhhans, let result = Fire.shared.transformPunctuation(string) { + if inputMode == .zhhans, let result = PunctuationConversion.shared.conversion(string) { insertText(result) return true } diff --git a/Fire/PunctuationConversion.swift b/Fire/PunctuationConversion.swift new file mode 100644 index 0000000..607b966 --- /dev/null +++ b/Fire/PunctuationConversion.swift @@ -0,0 +1,60 @@ +// +// PunctuationConversion.swift +// Fire +// +// Created by 杨永榜 on 2023/10/26. +// + +import Foundation +import Defaults + +protocol Conversion { + func conversion(_ origin: String) -> String? +} + +class PunctuationConversion: Conversion { + // 左引号暂存栈 + private var parisPunctuationStack: [String] = [] + private let MAX_STACK_SIZE = 30 // 暂存栈大小,防止随着使用出现内存上涨 + + private func transformResult(_ result: String) -> String { + let resultMap = [ + "‘": "’", + "“": "”" + ] + // 存在需要待匹配的左侧引号,并且当前输出和待匹配的引号一致,把结果转为对应的右侧引号 + if resultMap.keys.contains(result) && result == parisPunctuationStack.last { + _ = parisPunctuationStack.popLast() + return resultMap[result] ?? result + } + // 没有待匹配的引号,并且输入了左侧引号,存入待匹配区 + if resultMap.keys.contains(result) { + parisPunctuationStack.append(result) + if parisPunctuationStack.count > MAX_STACK_SIZE { + parisPunctuationStack.removeFirst() + } + return result + } + return result + } + + func conversion(_ origin: String) -> String? { + let isPunctuation = punctuation.keys.contains(origin) + if !isPunctuation { + return nil + } + let mode = Defaults[.punctuationMode] + if mode == .enUs { + return origin + } + if mode == .zhhans { + return punctuation[origin] == nil ? nil : transformResult(punctuation[origin]!) + } + if mode == .custom { + return Defaults[.customPunctuationSettings][origin] + } + return nil + } + + static let shared = PunctuationConversion() +} diff --git a/Fire/types.swift b/Fire/types.swift index e648724..4c4fd5a 100644 --- a/Fire/types.swift +++ b/Fire/types.swift @@ -189,28 +189,28 @@ let punctuation: [String: String] = [ "/": "、", ";": ";", "'": "‘", - "[": "[", - "]": "]", - "`": "`", + "[": "【", + "]": "】", + "`": "·", "!": "!", - "@": "‧", - "#": "#", + "@": "@", + "#": "#", "$": "¥", - "%": "%", + "%": "%", "^": "……", - "&": "&", - "*": "×", + "&": "&", + "*": "*", "(": "(", ")": ")", - "-": "-", + "-": "-", "_": "——", - "+": "+", - "=": "=", - "~": "~", - "{": "{", + "+": "+", + "=": "=", + "~": "~", + "{": "「", "\\": "、", - "|": "|", - "}": "}", + "|": "|", + "}": "」", ":": ":", "\"": "“", "<": "《",