Skip to content

Commit

Permalink
SwiftFormat // Fix configuration file.
Browse files Browse the repository at this point in the history
  • Loading branch information
ShikiSuen committed Jun 13, 2024
1 parent 416f9c4 commit 1ee42f8
Show file tree
Hide file tree
Showing 7 changed files with 926 additions and 480 deletions.
11 changes: 8 additions & 3 deletions .swiftformat.json → .swiftformat
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ redundantRawValues, \
redundantType, \
redundantVoidReturnType, \
semicolons, \
sortedImports, \
sortedSwitchCases, \
sortImports, \
sortSwitchCases, \
spaceAroundBraces, \
spaceAroundBrackets, \
spaceAroundComments, \
Expand Down Expand Up @@ -101,4 +101,9 @@ strongifiedSelf

--exclude Pods,**/UNTESTED_TODO,vendor,fastlane

# https://github.com/NoemiRozpara/Google-SwiftFormat-Config
# https://github.com/NoemiRozpara/Google-SwiftFormat-Config

# vChewing-specific settings:

--disable preferForLoop

1,150 changes: 772 additions & 378 deletions Sources/Tekkon/Tekkon_Constants.swift

Large diffs are not rendered by default.

39 changes: 25 additions & 14 deletions Sources/Tekkon/Tekkon_Phonabets.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@

infix operator <~: AssignmentPrecedence

public extension Tekkon {
extension Tekkon {
// MARK: - Dynamic Constants and Basic Enums

/// 定義注音符號的種類
enum PhoneType: Int, Codable, Hashable {
public enum PhoneType: Int, Codable, Hashable {
case null = 0 // 假
case consonant = 1 // 聲
case semivowel = 2 // 介
Expand All @@ -21,7 +21,7 @@ public extension Tekkon {
}

/// 定義注音排列的類型
enum MandarinParser: Int, Codable, Hashable {
public enum MandarinParser: Int, Codable, Hashable {
case ofDachen = 0
case ofDachen26 = 1
case ofETen = 2
Expand All @@ -40,6 +40,8 @@ public extension Tekkon {
case ofUniversalPinyin = 104
case ofWadeGilesPinyin = 105

// MARK: Internal

var name: String {
switch self {
case .ofDachen:
Expand Down Expand Up @@ -87,23 +89,32 @@ public extension Tekkon {
/// 如果遇到被設為多個字符、或者字符不對的情況的話,value 會被清空、PhoneType 會變成 null。
/// 賦值時最好直接重新 init 且一直用 let 來初期化 Phonabet。
/// 其實 value 對外只讀,對內的話另有 valueStorage 代為存儲內容。這樣比較安全一些。
@frozen struct Phonabet: Equatable, Codable, Hashable {
public var type: PhoneType = .null
private var valueStorage = ""
public var value: String { valueStorage }
public var isEmpty: Bool { value.isEmpty }
public var isValid: Bool { type != .null }
@frozen
public struct Phonabet: Equatable, Codable, Hashable {
// MARK: Lifecycle

/// 初期化,會根據傳入的 input 字串參數來自動判定自身的 PhoneType 類型屬性值。
public init(_ input: String = "") {
if !input.isEmpty {
if allowedPhonabets.contains(String(input.reversed()[0])) {
valueStorage = String(input.reversed()[0])
self.valueStorage = String(input.reversed()[0])
ensureType()
}
}
}

// MARK: Public

public var type: PhoneType = .null

public var value: String { valueStorage }
public var isEmpty: Bool { value.isEmpty }
public var isValid: Bool { type != .null }

public static func <~ (_ lhs: inout Tekkon.Phonabet, _ newValue: String) {
lhs.setValue(newValue)
}

/// 自我清空內容。
public mutating func clear() {
valueStorage = ""
Expand All @@ -124,10 +135,6 @@ public extension Tekkon {
ensureType()
}

public static func <~ (_ lhs: inout Tekkon.Phonabet, _ newValue: String) {
lhs.setValue(newValue)
}

/// 用來自動更新自身的屬性值的函式。
public mutating func ensureType() {
if Tekkon.allowedConsonants.contains(value) {
Expand All @@ -143,5 +150,9 @@ public extension Tekkon {
valueStorage = ""
}
}

// MARK: Private

private var valueStorage = ""
}
}
170 changes: 98 additions & 72 deletions Sources/Tekkon/Tekkon_SyllableComposer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
// marks, or product names of Contributor, except as required to fulfill notice
// requirements defined in MIT License.

public extension Tekkon {
// MARK: - Tekkon.Composer

extension Tekkon {
// MARK: - Syllable Composer

/// 注音並擊處理的對外介面以注拼槽(Syllable Composer)的形式存在。
Expand All @@ -15,7 +17,42 @@ public extension Tekkon {
///
/// 因為是 String Literal,所以初期化時可以藉由 @input 參數指定初期已經傳入的按鍵訊號。
/// 還可以在初期化時藉由 @arrange 參數來指定注音排列(預設為「.ofDachen」大千佈局)。
@frozen struct Composer: Equatable, Codable, Hashable, ExpressibleByStringLiteral {
@frozen
public struct Composer: Equatable, Codable, Hashable, ExpressibleByStringLiteral {
// MARK: Lifecycle

// MARK: 注拼槽對外處理函式

/// 初期化一個新的注拼槽。可以藉由 @input 參數指定初期已經傳入的按鍵訊號。
/// 還可以在初期化時藉由 @arrange 參數來指定注音排列(預設為「.ofDachen」大千佈局)。
/// - Parameters:
/// - input: 傳入的 String 內容,用以處理單個字符。
/// - arrange: 要使用的注音排列。
/// - correction: 是否對錯誤的注音讀音組合做出自動糾正處理。
public init(
_ input: String = "",
arrange parser: MandarinParser = .ofDachen,
correction: Bool = false
) {
self.phonabetCombinationCorrectionEnabled = correction
ensureParser(arrange: parser)
receiveKey(fromString: input)
}

public init(stringLiteral value: String) {
self.init(value)
}

public init(unicodeScalarLiteral value: String) {
self.init(stringLiteral: value)
}

public init(extendedGraphemeClusterLiteral value: String) {
self.init(stringLiteral: value)
}

// MARK: Public

/// 聲母。
public var consonant: Phonabet = .init()

Expand Down Expand Up @@ -47,6 +84,25 @@ public extension Tekkon {
/// 當前注拼槽是否處於拼音模式。
public var isPinyinMode: Bool { parser.rawValue >= 100 }

/// 注拼槽內容是否為空。
public var isEmpty: Bool {
guard !isPinyinMode else { return intonation.isEmpty && romajiBuffer.isEmpty }
return intonation.isEmpty && vowel.isEmpty && semivowel.isEmpty && consonant.isEmpty
}

/// 注拼槽內容是否可唸。
public var isPronounceable: Bool {
!vowel.isEmpty || !semivowel.isEmpty || !consonant.isEmpty
}

// MARK: - Misc Definitions

/// 這些內容用來滿足 "Equatable, Hashable, ExpressibleByStringLiteral" 需求。

public static func == (lhs: Composer, rhs: Composer) -> Bool {
lhs.value == rhs.value
}

/// 統計有效的聲介韻(調)個數。
/// - Parameter withIntonation: 是否統計聲調。
/// - Returns: 統計出的有效 Phonabet 個數。
Expand All @@ -60,14 +116,19 @@ public extension Tekkon {
/// - Parameters:
/// - isHanyuPinyin: 是否將輸出結果轉成漢語拼音。
/// - isTextBookStyle: 是否將輸出的注音/拼音結果轉成教科書排版格式。
public func getComposition(isHanyuPinyin: Bool = false, isTextBookStyle: Bool = false) -> String {
public func getComposition(
isHanyuPinyin: Bool = false,
isTextBookStyle: Bool = false
)
-> String {
switch isHanyuPinyin {
case false: // 注音輸出的場合
let valReturnZhuyin = value.swapping(" ", with: "")
return isTextBookStyle ? cnvPhonaToTextbookStyle(target: valReturnZhuyin) : valReturnZhuyin
case true: // 拼音輸出的場合
let valReturnPinyin = Tekkon.cnvPhonaToHanyuPinyin(targetJoined: value)
return isTextBookStyle ? Tekkon.cnvHanyuPinyinToTextbookStyle(targetJoined: valReturnPinyin) : valReturnPinyin
return isTextBookStyle ? Tekkon
.cnvHanyuPinyinToTextbookStyle(targetJoined: valReturnPinyin) : valReturnPinyin
}
}

Expand All @@ -88,31 +149,6 @@ public extension Tekkon {
return romajiBuffer.swapping("v", with: "ü") + toneReturned
}

/// 注拼槽內容是否為空。
public var isEmpty: Bool {
guard !isPinyinMode else { return intonation.isEmpty && romajiBuffer.isEmpty }
return intonation.isEmpty && vowel.isEmpty && semivowel.isEmpty && consonant.isEmpty
}

/// 注拼槽內容是否可唸。
public var isPronounceable: Bool {
!vowel.isEmpty || !semivowel.isEmpty || !consonant.isEmpty
}

// MARK: 注拼槽對外處理函式

/// 初期化一個新的注拼槽。可以藉由 @input 參數指定初期已經傳入的按鍵訊號。
/// 還可以在初期化時藉由 @arrange 參數來指定注音排列(預設為「.ofDachen」大千佈局)。
/// - Parameters:
/// - input: 傳入的 String 內容,用以處理單個字符。
/// - arrange: 要使用的注音排列。
/// - correction: 是否對錯誤的注音讀音組合做出自動糾正處理。
public init(_ input: String = "", arrange parser: MandarinParser = .ofDachen, correction: Bool = false) {
phonabetCombinationCorrectionEnabled = correction
ensureParser(arrange: parser)
receiveKey(fromString: input)
}

/// 清除自身的內容,就是將聲介韻調全部清空。
/// 嚴格而言,「注音排列」這個屬性沒有需要清空的概念,只能用 ensureParser 參數變更之。
public mutating func clear() {
Expand Down Expand Up @@ -166,33 +202,11 @@ public extension Tekkon {
return Tekkon.mapAlvinLiuStaticKeys[input] != nil
case .ofWadeGilesPinyin:
return Tekkon.mapWadeGilesPinyinKeys.has(string: input)
case .ofHanyuPinyin, .ofSecondaryPinyin, .ofYalePinyin, .ofHualuoPinyin, .ofUniversalPinyin:
case .ofHanyuPinyin, .ofHualuoPinyin, .ofSecondaryPinyin, .ofUniversalPinyin, .ofYalePinyin:
return Tekkon.mapArayuruPinyin.has(string: input)
}
}

/// 按需更新拼音組音區的內容顯示。
mutating func updateRomajiBuffer() {
romajiBuffer = Tekkon.cnvPhonaToHanyuPinyin(targetJoined: consonant.value + semivowel.value + vowel.value)
}

/// 自我變換單個注音資料值。
/// - Parameters:
/// - strOf: 要取代的內容。
/// - strWith: 要取代成的內容。
mutating func fixValue(_ strOf: String, _ strWith: String = "") {
guard !strOf.isEmpty, !strWith.isEmpty else { return }
let theOld = Phonabet(strOf)
switch theOld {
case consonant: consonant.clear()
case semivowel: semivowel.clear()
case vowel: vowel.clear()
case intonation: intonation.clear()
default: return
}
receiveKey(fromPhonabet: strWith)
}

/// 接受傳入的按鍵訊號時的處理,處理對象為 String。
/// 另有同名函式可處理 UniChar 訊號。
///
Expand Down Expand Up @@ -285,7 +299,12 @@ public extension Tekkon {
/// - givenSequence: 傳入的 String 內容,用以處理一整串擊鍵輸入。
/// - isRomaji: 如果輸入的字串是諸如漢語拼音這樣的西文字母拼音的話,請啟用此選項。
/// - Returns: 處理之後的結果。
@discardableResult public mutating func receiveSequence(_ givenSequence: String = "", isRomaji: Bool = false) -> String {
@discardableResult
public mutating func receiveSequence(
_ givenSequence: String = "",
isRomaji: Bool = false
)
-> String {
clear()
guard isRomaji else {
givenSequence.forEach { receiveKey(fromString: $0.description) }
Expand Down Expand Up @@ -420,7 +439,9 @@ public extension Tekkon {

/// 所有動態注音排列都會用到的共用糾錯處理步驟。
/// - Parameter incomingPhonabet: 傳入的注音 Phonabet。
public mutating func commonFixWhenHandlingDynamicArrangeInputs(target incomingPhonabet: Phonabet) {
public mutating func commonFixWhenHandlingDynamicArrangeInputs(
target incomingPhonabet: Phonabet
) {
// 處理特殊情形。
switch incomingPhonabet.type {
case .semivowel:
Expand Down Expand Up @@ -642,7 +663,7 @@ public extension Tekkon {
case (_, ""):
vowel.clear()
strReturn = ""
case ("", ""), _:
case _, ("", ""):
strReturn = (!semivowel.isEmpty || !"ㄐㄑㄒ".doesHave(consonant.value)) ? "" : ""
}
case "u":
Expand Down Expand Up @@ -722,37 +743,42 @@ public extension Tekkon {
return strReturn
}

// MARK: - Misc Definitions

/// 這些內容用來滿足 "Equatable, Hashable, ExpressibleByStringLiteral" 需求。

public static func == (lhs: Composer, rhs: Composer) -> Bool {
lhs.value == rhs.value
}

public func hash(into hasher: inout Hasher) {
hasher.combine(consonant)
hasher.combine(semivowel)
hasher.combine(vowel)
hasher.combine(intonation)
}

public init(stringLiteral value: String) {
self.init(value)
}
// MARK: Internal

public init(unicodeScalarLiteral value: String) {
self.init(stringLiteral: value)
/// 按需更新拼音組音區的內容顯示。
mutating func updateRomajiBuffer() {
romajiBuffer = Tekkon
.cnvPhonaToHanyuPinyin(targetJoined: consonant.value + semivowel.value + vowel.value)
}

public init(extendedGraphemeClusterLiteral value: String) {
self.init(stringLiteral: value)
/// 自我變換單個注音資料值。
/// - Parameters:
/// - strOf: 要取代的內容。
/// - strWith: 要取代成的內容。
mutating func fixValue(_ strOf: String, _ strWith: String = "") {
guard !strOf.isEmpty, !strWith.isEmpty else { return }
let theOld = Phonabet(strOf)
switch theOld {
case consonant: consonant.clear()
case semivowel: semivowel.clear()
case vowel: vowel.clear()
case intonation: intonation.clear()
default: return
}
receiveKey(fromPhonabet: strWith)
}
}
}

private extension String {
func doesHave(_ target: String) -> Bool {
extension String {
fileprivate func doesHave(_ target: String) -> Bool {
has(string: target)
}
}
Loading

0 comments on commit 1ee42f8

Please sign in to comment.