Files
OSGKeyboard/OSGKeyboardShared/Typing/RimeSchemaGenerator.swift
T
Rocky 38e5ad570d feat(typing): add English autocomplete and Chinese candidate expand panel
Offline English lexicon suggestions with autocapitalization, plus a same-height Chinese more-candidates grid over the key area.
2026-08-03 18:30:20 +08:00

190 lines
5.9 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// RimeSchemaGenerator.swift
// OSGKeyboard · Shared
//
// Generates OSG-owned schemas from public Microsoft/Sogou key maps.
// No GPL Rime schema files are copied or distributed.
import Foundation
public enum RimeSchemaGenerator {
public static func defaultConfiguration() -> String {
"""
# Generated by OSGKeyboard.
config_version: "1.0"
schema_list:
- schema: \(TypingInputSchema.fullPinyin.rawValue)
- schema: \(TypingInputSchema.microsoftDoublePinyin.rawValue)
- schema: \(TypingInputSchema.sogouDoublePinyin.rawValue)
switcher:
caption: 输入方案
hotkeys: []
menu:
# Large page so librime prepares enough candidates for the expand panel.
# The bridge also iterates beyond the current page via candidate_list_*.
page_size: 100
ascii_composer:
good_old_caps_lock: true
switch_key:
Shift_L: noop
Shift_R: noop
Control_L: noop
Control_R: noop
key_binder:
bindings: []
recognizer:
patterns: {}
"""
}
public static func schema(
for inputSchema: TypingInputSchema,
fuzzyPairs: Set<PinyinFuzzyPair>
) -> String {
let alphabet = inputSchema == .fullPinyin
? "zyxwvutsrqponmlkjihgfedcba"
: "zyxwvutsrqponmlkjihgfedcba;"
let algebra = fuzzyRules(fuzzyPairs) + algebraRules(for: inputSchema)
let algebraYAML = algebra.map { " - '\($0)'" }.joined(separator: "\n")
return """
# Generated by OSGKeyboard. Do not edit; change settings in the host app.
schema:
schema_id: \(inputSchema.rawValue)
name: \(inputSchema.displayName)
version: "1.0"
author:
- OSGKeyboard contributors
description: |
Commercially permissive OSG schema backed by osg_pinyin.
switches:
- name: ascii_mode
reset: 0
states: [中, 英]
engine:
processors:
- ascii_composer
- recognizer
- key_binder
- speller
- punctuator
- selector
- navigator
- express_editor
segmentors:
- ascii_segmentor
- matcher
- abc_segmentor
- punct_segmentor
- fallback_segmentor
translators:
- punct_translator
- script_translator
speller:
alphabet: "\(alphabet)"
initials: "\(alphabet.replacingOccurrences(of: ";", with: ""))"
delimiter: " '"
algebra:
\(algebraYAML)
translator:
dictionary: osg_pinyin
prism: \(inputSchema.rawValue)
enable_sentence: true
enable_completion: true
enable_user_dict: true
initial_quality: 1.2
punctuator:
half_shape:
",": ""
".": ""
"?": ""
"!": ""
key_binder:
import_preset: default
recognizer:
import_preset: default
"""
}
/// Rules run against full-pinyin dictionary codes before double-pinyin
/// transforms, so fuzzy pairs work consistently in all three schemas.
public static func fuzzyRules(_ enabled: Set<PinyinFuzzyPair>) -> [String] {
var rules: [String] = []
for pair in PinyinFuzzyPair.allCases where enabled.contains(pair) {
switch pair {
case .zhZ:
rules += ["derive/^zh/z/", "derive/^z([^h])/zh$1/"]
case .chC:
rules += ["derive/^ch/c/", "derive/^c([^h])/ch$1/"]
case .shS:
rules += ["derive/^sh/s/", "derive/^s([^h])/sh$1/"]
case .nL:
rules += ["derive/^n/l/", "derive/^l/n/"]
case .fH:
rules += ["derive/^f/h/", "derive/^h/f/"]
case .anAng:
rules += ["derive/ang$/an/", "derive/an$/ang/"]
case .enEng:
rules += ["derive/eng$/en/", "derive/en$/eng/"]
case .inIng:
rules += ["derive/ing$/in/", "derive/in$/ing/"]
}
}
return rules
}
private static func algebraRules(for schema: TypingInputSchema) -> [String] {
switch schema {
case .fullPinyin:
return [
"derive/^([jqxy])u$/$1v/",
"abbrev/^([a-z]).+$/$1/"
]
case .microsoftDoublePinyin, .sogouDoublePinyin:
// Microsoft and Sogou's commonly shipped layouts are key-compatible.
// Uppercase markers prevent transforms from matching each other.
return [
"erase/^xx$/",
"derive/^([jqxy])u$/$1v/",
"derive/^([aoe].*)$/o$1/",
"xform/^([ae])(.*)$/$1$1$2/",
"xform/iu$/Q/",
"xform/[iu]a$/W/",
"xform/er$|[uv]an$/R/",
"xform/[uv]e$/T/",
"xform/v$|uai$/Y/",
"xform/^sh/U/",
"xform/^ch/I/",
"xform/^zh/V/",
"xform/uo$/O/",
"xform/[uv]n$/P/",
"xform/(.)i?ong$/$1S/",
"xform/[iu]ang$/D/",
"xform/(.)en$/$1F/",
"xform/(.)eng$/$1G/",
"xform/(.)ang$/$1H/",
"xform/ian$/M/",
"xform/(.)an$/$1J/",
"xform/iao$/C/",
"xform/(.)ao$/$1K/",
"xform/(.)ai$/$1L/",
"xform/(.)ei$/$1Z/",
"xform/ie$/X/",
"xform/ui$/V/",
"derive/T$/V/",
"xform/(.)ou$/$1B/",
"xform/in$/N/",
"xform/ing$/;/",
"xlit/QWRTYUIOPSDFGHMJCKLZXVBN/qwrtyuiopsdfghmjcklzxvbn/"
]
}
}
}