mgrLM // Turn paths into URLs for fidelity of type conversion.
This commit is contained in:
parent
3f1d939647
commit
5d1df0992e
|
@ -311,38 +311,38 @@ extension ctlInputMethod {
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func openUserPhrases(_: Any?) {
|
@objc func openUserPhrases(_: Any?) {
|
||||||
IME.openPhraseFile(userFileAt: mgrLangModel.userPhrasesDataPath(IME.getInputMode()))
|
IME.openPhraseFile(fromURL: mgrLangModel.userPhrasesDataURL(IME.getInputMode()))
|
||||||
if NSEvent.modifierFlags.contains(.option), mgrPrefs.isDebugModeEnabled {
|
if NSEvent.modifierFlags.contains(.option), mgrPrefs.isDebugModeEnabled {
|
||||||
IME.openPhraseFile(userFileAt: mgrLangModel.userPhrasesDataPath(IME.getInputMode(isReversed: true)))
|
IME.openPhraseFile(fromURL: mgrLangModel.userPhrasesDataURL(IME.getInputMode(isReversed: true)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func openExcludedPhrases(_: Any?) {
|
@objc func openExcludedPhrases(_: Any?) {
|
||||||
IME.openPhraseFile(userFileAt: mgrLangModel.userFilteredDataPath(IME.getInputMode()))
|
IME.openPhraseFile(fromURL: mgrLangModel.userFilteredDataURL(IME.getInputMode()))
|
||||||
if NSEvent.modifierFlags.contains(.option), mgrPrefs.isDebugModeEnabled {
|
if NSEvent.modifierFlags.contains(.option), mgrPrefs.isDebugModeEnabled {
|
||||||
IME.openPhraseFile(userFileAt: mgrLangModel.userFilteredDataPath(IME.getInputMode(isReversed: true)))
|
IME.openPhraseFile(fromURL: mgrLangModel.userFilteredDataURL(IME.getInputMode(isReversed: true)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func openUserSymbols(_: Any?) {
|
@objc func openUserSymbols(_: Any?) {
|
||||||
IME.openPhraseFile(userFileAt: mgrLangModel.userSymbolDataPath(IME.getInputMode()))
|
IME.openPhraseFile(fromURL: mgrLangModel.userSymbolDataURL(IME.getInputMode()))
|
||||||
if NSEvent.modifierFlags.contains(.option), mgrPrefs.isDebugModeEnabled {
|
if NSEvent.modifierFlags.contains(.option), mgrPrefs.isDebugModeEnabled {
|
||||||
IME.openPhraseFile(userFileAt: mgrLangModel.userSymbolDataPath(IME.getInputMode(isReversed: true)))
|
IME.openPhraseFile(fromURL: mgrLangModel.userSymbolDataURL(IME.getInputMode(isReversed: true)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func openPhraseReplacement(_: Any?) {
|
@objc func openPhraseReplacement(_: Any?) {
|
||||||
IME.openPhraseFile(userFileAt: mgrLangModel.userReplacementsDataPath(IME.getInputMode()))
|
IME.openPhraseFile(fromURL: mgrLangModel.userReplacementsDataURL(IME.getInputMode()))
|
||||||
if NSEvent.modifierFlags.contains(.option), mgrPrefs.isDebugModeEnabled {
|
if NSEvent.modifierFlags.contains(.option), mgrPrefs.isDebugModeEnabled {
|
||||||
IME.openPhraseFile(userFileAt: mgrLangModel.userReplacementsDataPath(IME.getInputMode(isReversed: true)))
|
IME.openPhraseFile(fromURL: mgrLangModel.userReplacementsDataURL(IME.getInputMode(isReversed: true)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func openAssociatedPhrases(_: Any?) {
|
@objc func openAssociatedPhrases(_: Any?) {
|
||||||
IME.openPhraseFile(userFileAt: mgrLangModel.userAssociatesDataPath(IME.getInputMode()))
|
IME.openPhraseFile(fromURL: mgrLangModel.userAssociatesDataURL(IME.getInputMode()))
|
||||||
if NSEvent.modifierFlags.contains(.option), mgrPrefs.isDebugModeEnabled {
|
if NSEvent.modifierFlags.contains(.option), mgrPrefs.isDebugModeEnabled {
|
||||||
IME.openPhraseFile(
|
IME.openPhraseFile(
|
||||||
userFileAt: mgrLangModel.userAssociatesDataPath(IME.getInputMode(isReversed: true)))
|
fromURL: mgrLangModel.userAssociatesDataURL(IME.getInputMode(isReversed: true)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -122,6 +122,10 @@ public enum IME {
|
||||||
|
|
||||||
// MARK: - Open a phrase data file.
|
// MARK: - Open a phrase data file.
|
||||||
|
|
||||||
|
static func openPhraseFile(fromURL url: URL) {
|
||||||
|
openPhraseFile(userFileAt: url.path)
|
||||||
|
}
|
||||||
|
|
||||||
static func openPhraseFile(userFileAt path: String) {
|
static func openPhraseFile(userFileAt path: String) {
|
||||||
func checkIfUserFilesExist() -> Bool {
|
func checkIfUserFilesExist() -> Bool {
|
||||||
if !mgrLangModel.chkUserLMFilesExist(InputMode.imeModeCHS)
|
if !mgrLangModel.chkUserLMFilesExist(InputMode.imeModeCHS)
|
||||||
|
|
|
@ -41,13 +41,13 @@ class SymbolNode {
|
||||||
}
|
}
|
||||||
|
|
||||||
static func parseUserSymbolNodeData() {
|
static func parseUserSymbolNodeData() {
|
||||||
let path = mgrLangModel.userSymbolNodeDataPath()
|
let url = mgrLangModel.userSymbolNodeDataURL()
|
||||||
// 這兩個變數單獨拿出來,省得每次都重建還要浪費算力。
|
// 這兩個變數單獨拿出來,省得每次都重建還要浪費算力。
|
||||||
var arrLines = [String.SubSequence]()
|
var arrLines = [String.SubSequence]()
|
||||||
var fieldSlice = [Substring.SubSequence]()
|
var fieldSlice = [Substring.SubSequence]()
|
||||||
var arrChildren = [SymbolNode]()
|
var arrChildren = [SymbolNode]()
|
||||||
do {
|
do {
|
||||||
arrLines = try String(contentsOfFile: path, encoding: .utf8).split(separator: "\n")
|
arrLines = try String(contentsOfFile: url.path, encoding: .utf8).split(separator: "\n")
|
||||||
for strLine in arrLines.lazy.filter({ !$0.isEmpty }) {
|
for strLine in arrLines.lazy.filter({ !$0.isEmpty }) {
|
||||||
fieldSlice = strLine.split(separator: "=")
|
fieldSlice = strLine.split(separator: "=")
|
||||||
switch fieldSlice.count {
|
switch fieldSlice.count {
|
||||||
|
|
|
@ -149,33 +149,33 @@ enum mgrLangModel {
|
||||||
|
|
||||||
public static func loadUserPhrasesData() {
|
public static func loadUserPhrasesData() {
|
||||||
gLangModelCHT.loadUserPhrasesData(
|
gLangModelCHT.loadUserPhrasesData(
|
||||||
path: userPhrasesDataPath(InputMode.imeModeCHT),
|
path: userPhrasesDataURL(InputMode.imeModeCHT).path,
|
||||||
filterPath: userFilteredDataPath(InputMode.imeModeCHT)
|
filterPath: userFilteredDataURL(InputMode.imeModeCHT).path
|
||||||
)
|
)
|
||||||
gLangModelCHS.loadUserPhrasesData(
|
gLangModelCHS.loadUserPhrasesData(
|
||||||
path: userPhrasesDataPath(InputMode.imeModeCHS),
|
path: userPhrasesDataURL(InputMode.imeModeCHS).path,
|
||||||
filterPath: userFilteredDataPath(InputMode.imeModeCHS)
|
filterPath: userFilteredDataURL(InputMode.imeModeCHS).path
|
||||||
)
|
)
|
||||||
gLangModelCHT.loadUserSymbolData(path: userSymbolDataPath(InputMode.imeModeCHT))
|
gLangModelCHT.loadUserSymbolData(path: userSymbolDataURL(InputMode.imeModeCHT).path)
|
||||||
gLangModelCHS.loadUserSymbolData(path: userSymbolDataPath(InputMode.imeModeCHS))
|
gLangModelCHS.loadUserSymbolData(path: userSymbolDataURL(InputMode.imeModeCHS).path)
|
||||||
SymbolNode.parseUserSymbolNodeData()
|
SymbolNode.parseUserSymbolNodeData()
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func loadUserAssociatesData() {
|
public static func loadUserAssociatesData() {
|
||||||
gLangModelCHT.loadUserAssociatesData(
|
gLangModelCHT.loadUserAssociatesData(
|
||||||
path: mgrLangModel.userAssociatesDataPath(InputMode.imeModeCHT)
|
path: mgrLangModel.userAssociatesDataURL(InputMode.imeModeCHT).path
|
||||||
)
|
)
|
||||||
gLangModelCHS.loadUserAssociatesData(
|
gLangModelCHS.loadUserAssociatesData(
|
||||||
path: mgrLangModel.userAssociatesDataPath(InputMode.imeModeCHS)
|
path: mgrLangModel.userAssociatesDataURL(InputMode.imeModeCHS).path
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func loadUserPhraseReplacement() {
|
public static func loadUserPhraseReplacement() {
|
||||||
gLangModelCHT.loadReplacementsData(
|
gLangModelCHT.loadReplacementsData(
|
||||||
path: mgrLangModel.userReplacementsDataPath(InputMode.imeModeCHT)
|
path: mgrLangModel.userReplacementsDataURL(InputMode.imeModeCHT).path
|
||||||
)
|
)
|
||||||
gLangModelCHS.loadReplacementsData(
|
gLangModelCHS.loadReplacementsData(
|
||||||
path: mgrLangModel.userReplacementsDataPath(InputMode.imeModeCHS)
|
path: mgrLangModel.userReplacementsDataURL(InputMode.imeModeCHS).path
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,47 +220,48 @@ enum mgrLangModel {
|
||||||
|
|
||||||
// Swift 的 appendingPathComponent 需要藉由 URL 完成,最後再用 .path 轉為路徑。
|
// Swift 的 appendingPathComponent 需要藉由 URL 完成,最後再用 .path 轉為路徑。
|
||||||
|
|
||||||
static func userPhrasesDataPath(_ mode: InputMode) -> String {
|
static func userPhrasesDataURL(_ mode: InputMode) -> URL {
|
||||||
let fileName = (mode == InputMode.imeModeCHT) ? "userdata-cht.txt" : "userdata-chs.txt"
|
let fileName = (mode == InputMode.imeModeCHT) ? "userdata-cht.txt" : "userdata-chs.txt"
|
||||||
return URL(fileURLWithPath: dataFolderPath(isDefaultFolder: false)).appendingPathComponent(fileName).path
|
return URL(fileURLWithPath: dataFolderPath(isDefaultFolder: false)).appendingPathComponent(fileName)
|
||||||
}
|
}
|
||||||
|
|
||||||
static func userSymbolDataPath(_ mode: InputMode) -> String {
|
static func userSymbolDataURL(_ mode: InputMode) -> URL {
|
||||||
let fileName = (mode == InputMode.imeModeCHT) ? "usersymbolphrases-cht.txt" : "usersymbolphrases-chs.txt"
|
let fileName = (mode == InputMode.imeModeCHT) ? "usersymbolphrases-cht.txt" : "usersymbolphrases-chs.txt"
|
||||||
return URL(fileURLWithPath: dataFolderPath(isDefaultFolder: false)).appendingPathComponent(fileName).path
|
return URL(fileURLWithPath: dataFolderPath(isDefaultFolder: false)).appendingPathComponent(fileName)
|
||||||
}
|
}
|
||||||
|
|
||||||
static func userAssociatesDataPath(_ mode: InputMode) -> String {
|
static func userAssociatesDataURL(_ mode: InputMode) -> URL {
|
||||||
let fileName = (mode == InputMode.imeModeCHT) ? "associatedPhrases-cht.txt" : "associatedPhrases-chs.txt"
|
let fileName = (mode == InputMode.imeModeCHT) ? "associatedPhrases-cht.txt" : "associatedPhrases-chs.txt"
|
||||||
return URL(fileURLWithPath: dataFolderPath(isDefaultFolder: false)).appendingPathComponent(fileName).path
|
return URL(fileURLWithPath: dataFolderPath(isDefaultFolder: false)).appendingPathComponent(fileName)
|
||||||
}
|
}
|
||||||
|
|
||||||
static func userFilteredDataPath(_ mode: InputMode) -> String {
|
static func userFilteredDataURL(_ mode: InputMode) -> URL {
|
||||||
let fileName = (mode == InputMode.imeModeCHT) ? "exclude-phrases-cht.txt" : "exclude-phrases-chs.txt"
|
let fileName = (mode == InputMode.imeModeCHT) ? "exclude-phrases-cht.txt" : "exclude-phrases-chs.txt"
|
||||||
return URL(fileURLWithPath: dataFolderPath(isDefaultFolder: false)).appendingPathComponent(fileName).path
|
return URL(fileURLWithPath: dataFolderPath(isDefaultFolder: false)).appendingPathComponent(fileName)
|
||||||
}
|
}
|
||||||
|
|
||||||
static func userReplacementsDataPath(_ mode: InputMode) -> String {
|
static func userReplacementsDataURL(_ mode: InputMode) -> URL {
|
||||||
let fileName = (mode == InputMode.imeModeCHT) ? "phrases-replacement-cht.txt" : "phrases-replacement-chs.txt"
|
let fileName = (mode == InputMode.imeModeCHT) ? "phrases-replacement-cht.txt" : "phrases-replacement-chs.txt"
|
||||||
return URL(fileURLWithPath: dataFolderPath(isDefaultFolder: false)).appendingPathComponent(fileName).path
|
return URL(fileURLWithPath: dataFolderPath(isDefaultFolder: false)).appendingPathComponent(fileName)
|
||||||
}
|
}
|
||||||
|
|
||||||
static func userSymbolNodeDataPath() -> String {
|
static func userSymbolNodeDataURL() -> URL {
|
||||||
let fileName = "symbols.dat"
|
let fileName = "symbols.dat"
|
||||||
return URL(fileURLWithPath: dataFolderPath(isDefaultFolder: false)).appendingPathComponent(fileName).path
|
return URL(fileURLWithPath: dataFolderPath(isDefaultFolder: false)).appendingPathComponent(fileName)
|
||||||
}
|
}
|
||||||
|
|
||||||
static func userOverrideModelDataPath(_ mode: InputMode) -> String {
|
static func userOverrideModelDataURL(_ mode: InputMode) -> URL {
|
||||||
let fileName = (mode == InputMode.imeModeCHT) ? "override-model-data-chs.dat" : "override-model-data-cht.dat"
|
let fileName = (mode == InputMode.imeModeCHT) ? "override-model-data-chs.dat" : "override-model-data-cht.dat"
|
||||||
return URL(fileURLWithPath: dataFolderPath(isDefaultFolder: false)).appendingPathComponent(fileName).path
|
return URL(fileURLWithPath: dataFolderPath(isDefaultFolder: false)).appendingPathComponent(fileName)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - 檢查具體的使用者語彙檔案是否存在
|
// MARK: - 檢查具體的使用者語彙檔案是否存在
|
||||||
|
|
||||||
static func ensureFileExists(
|
static func ensureFileExists(
|
||||||
_ filePath: String, populateWithTemplate templateBasename: String = "1145141919810",
|
_ fileURL: URL, populateWithTemplate templateBasename: String = "1145141919810",
|
||||||
extension ext: String = "txt"
|
extension ext: String = "txt"
|
||||||
) -> Bool {
|
) -> Bool {
|
||||||
|
let filePath = fileURL.path
|
||||||
if !FileManager.default.fileExists(atPath: filePath) {
|
if !FileManager.default.fileExists(atPath: filePath) {
|
||||||
let templateURL = Bundle.main.url(forResource: templateBasename, withExtension: ext)
|
let templateURL = Bundle.main.url(forResource: templateBasename, withExtension: ext)
|
||||||
var templateData = Data("".utf8)
|
var templateData = Data("".utf8)
|
||||||
|
@ -285,11 +286,14 @@ enum mgrLangModel {
|
||||||
if !userDataFolderExists {
|
if !userDataFolderExists {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if !ensureFileExists(userPhrasesDataPath(mode))
|
/// SymbolNode 資料與 UserOverrideModel 半衰模組資料檔案不需要強行確保存在。
|
||||||
|| !ensureFileExists(userAssociatesDataPath(mode))
|
/// 前者的話,需要該檔案存在的人自己會建立。
|
||||||
|| !ensureFileExists(userFilteredDataPath(mode))
|
/// 後者的話,你在敲字時自己就會建立。
|
||||||
|| !ensureFileExists(userReplacementsDataPath(mode))
|
if !ensureFileExists(userPhrasesDataURL(mode))
|
||||||
|| !ensureFileExists(userSymbolDataPath(mode))
|
|| !ensureFileExists(userAssociatesDataURL(mode))
|
||||||
|
|| !ensureFileExists(userFilteredDataURL(mode))
|
||||||
|
|| !ensureFileExists(userReplacementsDataURL(mode))
|
||||||
|
|| !ensureFileExists(userSymbolDataURL(mode))
|
||||||
{
|
{
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -402,7 +406,7 @@ enum mgrLangModel {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
let path = areWeDeleting ? userFilteredDataPath(mode) : userPhrasesDataPath(mode)
|
let theURL = areWeDeleting ? userFilteredDataURL(mode) : userPhrasesDataURL(mode)
|
||||||
|
|
||||||
if areWeDuplicating, !areWeDeleting {
|
if areWeDuplicating, !areWeDeleting {
|
||||||
// Do not use ASCII characters to comment here.
|
// Do not use ASCII characters to comment here.
|
||||||
|
@ -411,7 +415,7 @@ enum mgrLangModel {
|
||||||
currentMarkedPhrase += "\t#𝙾𝚟𝚎𝚛𝚛𝚒𝚍𝚎"
|
currentMarkedPhrase += "\t#𝙾𝚟𝚎𝚛𝚛𝚒𝚍𝚎"
|
||||||
}
|
}
|
||||||
|
|
||||||
if let writeFile = FileHandle(forUpdatingAtPath: path),
|
if let writeFile = FileHandle(forUpdatingAtPath: theURL.path),
|
||||||
let data = currentMarkedPhrase.data(using: .utf8),
|
let data = currentMarkedPhrase.data(using: .utf8),
|
||||||
let endl = "\n".data(using: .utf8)
|
let endl = "\n".data(using: .utf8)
|
||||||
{
|
{
|
||||||
|
@ -426,7 +430,7 @@ enum mgrLangModel {
|
||||||
|
|
||||||
// We enforce the format consolidation here, since the pragma header
|
// We enforce the format consolidation here, since the pragma header
|
||||||
// will let the UserPhraseLM bypasses the consolidating process on load.
|
// will let the UserPhraseLM bypasses the consolidating process on load.
|
||||||
if !vChewing.LMConsolidator.consolidate(path: path, pragma: false) {
|
if !vChewing.LMConsolidator.consolidate(path: theURL.path, pragma: false) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue