LMCassette // Auto-generate `%quick` results when appropriate.

This commit is contained in:
ShikiSuen 2023-06-28 00:38:37 +08:00
parent 45925c3263
commit 86c407a16d
4 changed files with 70 additions and 44 deletions

View File

@ -37,6 +37,7 @@ public extension vChewingLM {
/// [:(, )] /// [:(, )]
public private(set) var octagramDividedMap: [String: (Int, String)] = [:] public private(set) var octagramDividedMap: [String: (Int, String)] = [:]
public private(set) var areCandidateKeysShiftHeld: Bool = false public private(set) var areCandidateKeysShiftHeld: Bool = false
public private(set) var supplyQuickResults: Bool = false
/// 西 /// 西
private static let fscale = 2.7 private static let fscale = 2.7
@ -91,38 +92,49 @@ public extension vChewingLM {
var loadingOctagramData = false var loadingOctagramData = false
var keysUsedInCharDef: Set<String> = .init() var keysUsedInCharDef: Set<String> = .init()
for strLine in lineReader { for strLine in lineReader {
if !loadingKeys, strLine.contains("%keyname"), strLine.contains("begin") { loadingKeys = true } if strLine.starts(with: "%keyname") {
if loadingKeys, strLine.contains("%keyname"), strLine.contains("end") { loadingKeys = false } if !loadingKeys, strLine.contains("begin") { loadingKeys = true }
// %quick if loadingKeys, strLine.contains("end") { loadingKeys = false }
if !loadingQuickSets, strLine.contains("%quick"), strLine.contains("begin") {
loadingQuickSets = true
} }
if loadingQuickSets, strLine.contains("%quick"), strLine.contains("end") { // %quick
loadingQuickSets = false if strLine.starts(with: "%quick") {
if quickDefMap.keys.contains(wildcardKey) { wildcardKey = "" } if strLine == "%quick", !supplyQuickResults { supplyQuickResults = true }
if !loadingQuickSets, strLine.contains("begin") {
loadingQuickSets = true
}
if loadingQuickSets, strLine.contains("end") {
loadingQuickSets = false
if quickDefMap.keys.contains(wildcardKey) { wildcardKey = "" }
}
} }
// %chardef // %chardef
if !loadingCharDefinitions, strLine.contains("%chardef"), strLine.contains("begin") { if strLine.starts(with: "%chardef") {
loadingCharDefinitions = true if !loadingCharDefinitions, strLine.contains("begin") {
} loadingCharDefinitions = true
if loadingCharDefinitions, strLine.contains("%chardef"), strLine.contains("end") { }
loadingCharDefinitions = false if loadingCharDefinitions, strLine.contains("end") {
if charDefMap.keys.contains(wildcardKey) { wildcardKey = "" } loadingCharDefinitions = false
if charDefMap.keys.contains(wildcardKey) { wildcardKey = "" }
}
} }
// %symboldef // %symboldef
if !loadingSymbolDefinitions, strLine.contains("%symboldef"), strLine.contains("begin") { if strLine.starts(with: "%symboldef") {
loadingSymbolDefinitions = true if !loadingSymbolDefinitions, strLine.contains("begin") {
} loadingSymbolDefinitions = true
if loadingSymbolDefinitions, strLine.contains("%symboldef"), strLine.contains("end") { }
loadingSymbolDefinitions = false if loadingSymbolDefinitions, strLine.contains("end") {
if symbolDefMap.keys.contains(wildcardKey) { wildcardKey = "" } loadingSymbolDefinitions = false
if symbolDefMap.keys.contains(wildcardKey) { wildcardKey = "" }
}
} }
// %octagram // %octagram
if !loadingOctagramData, strLine.contains("%octagram"), strLine.contains("begin") { if strLine.starts(with: "%octagram") {
loadingOctagramData = true if !loadingOctagramData, strLine.contains("begin") {
} loadingOctagramData = true
if loadingOctagramData, strLine.contains("%octagram"), strLine.contains("end") { }
loadingOctagramData = false if loadingOctagramData, strLine.contains("end") {
loadingOctagramData = false
}
} }
// Start data parsing. // Start data parsing.
let cells: [String.SubSequence] = let cells: [String.SubSequence] =
@ -130,13 +142,13 @@ public extension vChewingLM {
guard cells.count >= 2 else { continue } guard cells.count >= 2 else { continue }
let strFirstCell = cells[0].trimmingCharacters(in: .newlines) let strFirstCell = cells[0].trimmingCharacters(in: .newlines)
let strSecondCell = cells[1].trimmingCharacters(in: .newlines) let strSecondCell = cells[1].trimmingCharacters(in: .newlines)
if loadingKeys, !cells[0].contains("%keyname") { if loadingKeys, !cells[0].starts(with: "%keyname") {
keyNameMap[strFirstCell] = cells[1].trimmingCharacters(in: .newlines) keyNameMap[strFirstCell] = cells[1].trimmingCharacters(in: .newlines)
} else if loadingQuickSets, !strLine.contains("%quick") { } else if loadingQuickSets, !strLine.starts(with: "%quick") {
theMaxKeyLength = max(theMaxKeyLength, cells[0].count) theMaxKeyLength = max(theMaxKeyLength, cells[0].count)
quickDefMap[strFirstCell, default: .init()].append(strSecondCell) quickDefMap[strFirstCell, default: .init()].append(strSecondCell)
} else if loadingCharDefinitions, !loadingSymbolDefinitions, } else if loadingCharDefinitions, !loadingSymbolDefinitions,
!strLine.contains("%chardef"), !strLine.contains("%symboldef") !strLine.starts(with: "%chardef"), !strLine.starts(with: "%symboldef")
{ {
theMaxKeyLength = max(theMaxKeyLength, cells[0].count) theMaxKeyLength = max(theMaxKeyLength, cells[0].count)
charDefMap[strFirstCell, default: []].append(strSecondCell) charDefMap[strFirstCell, default: []].append(strSecondCell)
@ -151,11 +163,11 @@ public extension vChewingLM {
keyComps.removeLast() keyComps.removeLast()
charDefWildcardMap[keyComps.joined() + wildcard, default: []].append(strSecondCell) charDefWildcardMap[keyComps.joined() + wildcard, default: []].append(strSecondCell)
} }
} else if loadingSymbolDefinitions, !strLine.contains("%chardef"), !strLine.contains("%symboldef") { } else if loadingSymbolDefinitions, !strLine.starts(with: "%chardef"), !strLine.starts(with: "%symboldef") {
theMaxKeyLength = max(theMaxKeyLength, cells[0].count) theMaxKeyLength = max(theMaxKeyLength, cells[0].count)
symbolDefMap[strFirstCell, default: []].append(strSecondCell) symbolDefMap[strFirstCell, default: []].append(strSecondCell)
reverseLookupMap[strSecondCell, default: []].append(strFirstCell) reverseLookupMap[strSecondCell, default: []].append(strFirstCell)
} else if loadingOctagramData, !strLine.contains("%octagram") { } else if loadingOctagramData, !strLine.starts(with: "%octagram") {
guard let countValue = Int(cells[1]) else { continue } guard let countValue = Int(cells[1]) else { continue }
switch cells.count { switch cells.count {
case 2: octagramMap[strFirstCell] = countValue case 2: octagramMap[strFirstCell] = countValue
@ -165,7 +177,7 @@ public extension vChewingLM {
norm += Self.fscale ** (Double(cells[0].count) / 3.0 - 1.0) * Double(countValue) norm += Self.fscale ** (Double(cells[0].count) / 3.0 - 1.0) * Double(countValue)
} }
guard !loadingKeys, !loadingQuickSets, !loadingCharDefinitions, !loadingOctagramData else { continue } guard !loadingKeys, !loadingQuickSets, !loadingCharDefinitions, !loadingOctagramData else { continue }
if nameENG.isEmpty, strLine.contains("%ename ") { if nameENG.isEmpty, strLine.starts(with: "%ename ") {
for neta in cells[1].components(separatedBy: ";") { for neta in cells[1].components(separatedBy: ";") {
let subNetaGroup = neta.components(separatedBy: ":") let subNetaGroup = neta.components(separatedBy: ":")
if subNetaGroup.count == 2, subNetaGroup[1].contains("en") { if subNetaGroup.count == 2, subNetaGroup[1].contains("en") {
@ -175,19 +187,19 @@ public extension vChewingLM {
} }
if nameENG.isEmpty { nameENG = strSecondCell } if nameENG.isEmpty { nameENG = strSecondCell }
} }
if nameIntl.isEmpty, strLine.contains("%intlname ") { if nameIntl.isEmpty, strLine.starts(with: "%intlname ") {
nameIntl = strSecondCell.replacingOccurrences(of: "_", with: " ") nameIntl = strSecondCell.replacingOccurrences(of: "_", with: " ")
} }
if nameCJK.isEmpty, strLine.contains("%cname ") { nameCJK = strSecondCell } if nameCJK.isEmpty, strLine.starts(with: "%cname ") { nameCJK = strSecondCell }
if nameShort.isEmpty, strLine.contains("%sname ") { nameShort = strSecondCell } if nameShort.isEmpty, strLine.starts(with: "%sname ") { nameShort = strSecondCell }
if nullCandidate.isEmpty, strLine.contains("%nullcandidate ") { nullCandidate = strSecondCell } if nullCandidate.isEmpty, strLine.starts(with: "%nullcandidate ") { nullCandidate = strSecondCell }
if selectionKeys.isEmpty, strLine.contains("%selkey ") { if selectionKeys.isEmpty, strLine.starts(with: "%selkey ") {
selectionKeys = cells[1].map(\.description).deduplicated.joined() selectionKeys = cells[1].map(\.description).deduplicated.joined()
} }
if endKeys.isEmpty, strLine.contains("%endkey ") { if endKeys.isEmpty, strLine.starts(with: "%endkey ") {
endKeys = cells[1].map(\.description).deduplicated endKeys = cells[1].map(\.description).deduplicated
} }
if wildcardKey.isEmpty, strLine.contains("%wildcardkey ") { if wildcardKey.isEmpty, strLine.starts(with: "%wildcardkey ") {
wildcardKey = cells[1].first?.description ?? "" wildcardKey = cells[1].first?.description ?? ""
} }
} }
@ -232,8 +244,22 @@ public extension vChewingLM {
} }
public func quickSetsFor(key: String) -> String? { public func quickSetsFor(key: String) -> String? {
guard let result = quickDefMap[key] as String? else { return nil } guard !key.isEmpty else { return nil }
return result.isEmpty ? nil : result var result = [String]()
if let specifiedResult = quickDefMap[key], !specifiedResult.isEmpty {
result.append(contentsOf: specifiedResult.map(\.description))
}
if supplyQuickResults, quickDefMap.isEmpty {
let fetched = charDefMap.compactMap {
$0.key.starts(with: key) ? $0 : nil
}.stableSort {
$0.key.count < $1.key.count
}.flatMap(\.value).filter {
$0.count == 1
}
result.append(contentsOf: fetched.deduplicated.prefix(selectionKeys.count * 6))
}
return result.isEmpty ? nil : result.joined(separator: "\t")
} }
/// ///

View File

@ -49,8 +49,8 @@ final class LMCassetteTests: XCTestCase {
XCTAssertFalse(lmCassette.quickDefMap.isEmpty) XCTAssertFalse(lmCassette.quickDefMap.isEmpty)
print(lmCassette.quickSetsFor(key: ",.") ?? "") print(lmCassette.quickSetsFor(key: ",.") ?? "")
XCTAssertEqual(lmCassette.keyNameMap.count, 41) XCTAssertEqual(lmCassette.keyNameMap.count, 41)
XCTAssertEqual(lmCassette.charDefMap.count, 29491) XCTAssertEqual(lmCassette.charDefMap.count, 29537)
XCTAssertEqual(lmCassette.charDefWildcardMap.count, 11946) XCTAssertEqual(lmCassette.charDefWildcardMap.count, 11973)
XCTAssertEqual(lmCassette.octagramMap.count, 0) XCTAssertEqual(lmCassette.octagramMap.count, 0)
XCTAssertEqual(lmCassette.octagramDividedMap.count, 0) XCTAssertEqual(lmCassette.octagramDividedMap.count, 0)
XCTAssertEqual(lmCassette.nameShort, "AR30") XCTAssertEqual(lmCassette.nameShort, "AR30")

View File

@ -279,7 +279,7 @@ extension InputHandler {
if !isStrokesFull { if !isStrokesFull {
var result = generateStateOfInputting() var result = generateStateOfInputting()
if !calligrapher.isEmpty, var fetched = currentLM.cassetteQuickSetsFor(key: calligrapher) { if !calligrapher.isEmpty, var fetched = currentLM.cassetteQuickSetsFor(key: calligrapher)?.split(separator: "\t") {
if prefs.useIMKCandidateWindow { if prefs.useIMKCandidateWindow {
fetched = fetched.deduplicated.filter { $0.description != currentLM.nullCandidateInCassette } fetched = fetched.deduplicated.filter { $0.description != currentLM.nullCandidateInCassette }
} }

View File

@ -507,7 +507,7 @@ extension InputHandler {
switch isConsideredEmptyForNow { switch isConsideredEmptyForNow {
case false: case false:
var result = generateStateOfInputting() var result = generateStateOfInputting()
if prefs.cassetteEnabled, var fetched = currentLM.cassetteQuickSetsFor(key: calligrapher) { if prefs.cassetteEnabled, var fetched = currentLM.cassetteQuickSetsFor(key: calligrapher)?.split(separator: "\t") {
if prefs.useIMKCandidateWindow { if prefs.useIMKCandidateWindow {
fetched = fetched.deduplicated.filter { $0.description != currentLM.nullCandidateInCassette } fetched = fetched.deduplicated.filter { $0.description != currentLM.nullCandidateInCassette }
} }