mirror of
https://github.com/mii443/AzooKeyKanaKanjiConverter.git
synced 2025-08-22 15:05:26 +00:00
315 lines
10 KiB
Swift
315 lines
10 KiB
Swift
//
|
|
// extension Character.swift
|
|
// Keyboard
|
|
//
|
|
// Created by ensan on 2020/09/03.
|
|
// Copyright © 2020 ensan. All rights reserved.
|
|
//
|
|
|
|
import Foundation
|
|
|
|
public enum CharacterUtils {
|
|
/// 小書きのかなカナ集合
|
|
private static let kogakiKana: Set<Character> = [
|
|
"ぁ", "ぃ", "ぅ", "ぇ", "ぉ", "ゕ", "ゖ", "っ", "ゃ", "ゅ", "ょ", "ゎ",
|
|
"ァ", "ィ", "ゥ", "ェ", "ォ", "ヵ", "ヶ", "ッ", "ャ", "ュ", "ョ", "ヮ"
|
|
]
|
|
/// 濁点付きのかなカナ集合
|
|
private static let dakutenKana: Set<Character> = [
|
|
"ゔ", "が", "ぎ", "ぐ", "げ", "ご", "ざ", "じ", "ず", "ぜ", "ぞ", "だ", "ぢ", "づ", "で", "ど", "ば", "び", "ぶ", "べ", "ぼ",
|
|
"ヴ", "ガ", "ギ", "グ", "ゲ", "ゴ", "ザ", "ジ", "ズ", "ゼ", "ゾ", "ダ", "ヂ", "ヅ", "デ", "ド", "バ", "ビ", "ブ", "ベ", "ボ"
|
|
]
|
|
|
|
/// 小書きかなか否か
|
|
static func isKogana(_ character: Character) -> Bool {
|
|
kogakiKana.contains(character)
|
|
}
|
|
|
|
/// ローマ字(a-z, A-Zか否か)
|
|
@inlinable public static func isRomanLetter(_ character: Character) -> Bool {
|
|
character.isASCII && character.isCased
|
|
}
|
|
|
|
/// 自分が小書きであれば該当する文字を返す。
|
|
public static func kogaki(_ character: Character) -> Character {
|
|
switch character {
|
|
case "あ": return "ぁ"
|
|
case "い": return "ぃ"
|
|
case "う": return "ぅ"
|
|
case "え": return "ぇ"
|
|
case "お": return "ぉ"
|
|
case "か": return "ゕ"
|
|
case "け": return "ゖ"
|
|
case "つ": return "っ"
|
|
case "や": return "ゃ"
|
|
case "ゆ": return "ゅ"
|
|
case "よ": return "ょ"
|
|
case "わ": return "ゎ"
|
|
case "ア": return "ァ"
|
|
case "イ": return "ィ"
|
|
case "ウ": return "ゥ"
|
|
case "エ": return "ェ"
|
|
case "オ": return "ォ"
|
|
case "カ": return "ヵ"
|
|
case "ケ": return "ヶ"
|
|
case "ツ": return "ッ"
|
|
case "ヤ": return "ャ"
|
|
case "ユ": return "ュ"
|
|
case "ヨ": return "ョ"
|
|
case "ワ": return "ヮ"
|
|
default: return character
|
|
}
|
|
}
|
|
|
|
/// 小書きから大書きを返す
|
|
public static func ogaki(_ character: Character) -> Character {
|
|
switch character {
|
|
case "ぁ": return "あ"
|
|
case "ぃ": return "い"
|
|
case "ぅ": return "う"
|
|
case "ぇ": return "え"
|
|
case "ぉ": return "お"
|
|
case "ゕ": return "か"
|
|
case "ゖ": return "け"
|
|
case "っ": return "つ"
|
|
case "ゃ": return "や"
|
|
case "ゅ": return "ゆ"
|
|
case "ょ": return "よ"
|
|
case "ゎ": return "わ"
|
|
case "ァ": return "ア"
|
|
case "ィ": return "イ"
|
|
case "ゥ": return "ウ"
|
|
case "ェ": return "エ"
|
|
case "ォ": return "オ"
|
|
case "ヵ": return "カ"
|
|
case "ヶ": return "ケ"
|
|
case "ッ": return "ツ"
|
|
case "ャ": return "ヤ"
|
|
case "ュ": return "ユ"
|
|
case "ョ": return "ヨ"
|
|
case "ヮ": return "ワ"
|
|
default: return character
|
|
}
|
|
}
|
|
|
|
/// 濁点付きか否か
|
|
public static func isDakuten(_ character: Character) -> Bool {
|
|
dakutenKana.contains(character)
|
|
}
|
|
/// 濁点をつけて返す
|
|
public static func dakuten(_ character: Character) -> Character {
|
|
switch character {
|
|
case"う": return "ゔ"
|
|
case"か": return "が"
|
|
case"き": return "ぎ"
|
|
case"く": return "ぐ"
|
|
case"け": return "げ"
|
|
case"こ": return "ご"
|
|
case"さ": return "ざ"
|
|
case"し": return "じ"
|
|
case"す": return "ず"
|
|
case"せ": return "ぜ"
|
|
case"そ": return "ぞ"
|
|
case"た": return "だ"
|
|
case"ち": return "ぢ"
|
|
case"つ": return "づ"
|
|
case"て": return "で"
|
|
case"と": return "ど"
|
|
case"は": return "ば"
|
|
case"ひ": return "び"
|
|
case"ふ": return "ぶ"
|
|
case"へ": return "べ"
|
|
case"ほ": return "ぼ"
|
|
case"ウ": return "ヴ"
|
|
case"カ": return "ガ"
|
|
case"キ": return "ギ"
|
|
case"ク": return "グ"
|
|
case"ケ": return "ゲ"
|
|
case"コ": return "ゴ"
|
|
case"サ": return "ザ"
|
|
case"シ": return "ジ"
|
|
case"ス": return "ズ"
|
|
case"セ": return "ゼ"
|
|
case"ソ": return "ゾ"
|
|
case"タ": return "ダ"
|
|
case"チ": return "ヂ"
|
|
case"ツ": return "ヅ"
|
|
case"テ": return "デ"
|
|
case"ト": return "ド"
|
|
case"ハ": return "バ"
|
|
case"ヒ": return "ビ"
|
|
case"フ": return "ブ"
|
|
case"ヘ": return "ベ"
|
|
case"ホ": return "ボ"
|
|
default: return character
|
|
}
|
|
}
|
|
/// 濁点を外して返す
|
|
public static func mudakuten(_ character: Character) -> Character {
|
|
switch character {
|
|
case"ゔ": return "う"
|
|
case"が": return "か"
|
|
case"ぎ": return "き"
|
|
case"ぐ": return "く"
|
|
case"げ": return "け"
|
|
case"ご": return "こ"
|
|
case"ざ": return "さ"
|
|
case"じ": return "し"
|
|
case"ず": return "す"
|
|
case"ぜ": return "せ"
|
|
case"ぞ": return "そ"
|
|
case"だ": return "た"
|
|
case"ぢ": return "ち"
|
|
case"づ": return "つ"
|
|
case"で": return "て"
|
|
case"ど": return "と"
|
|
case"ば": return "は"
|
|
case"び": return "ひ"
|
|
case"ぶ": return "ふ"
|
|
case"べ": return "へ"
|
|
case"ぼ": return "ほ"
|
|
case"ヴ": return "ウ"
|
|
case"ガ": return "カ"
|
|
case"ギ": return "キ"
|
|
case"グ": return "ク"
|
|
case"ゲ": return "ケ"
|
|
case"ゴ": return "コ"
|
|
case"ザ": return "サ"
|
|
case"ジ": return "シ"
|
|
case"ズ": return "ス"
|
|
case"ゼ": return "セ"
|
|
case"ゾ": return "ソ"
|
|
case"ダ": return "タ"
|
|
case"ヂ": return "チ"
|
|
case"ヅ": return "ツ"
|
|
case"デ": return "テ"
|
|
case"ド": return "ト"
|
|
case"バ": return "ハ"
|
|
case"ビ": return "ヒ"
|
|
case"ブ": return "フ"
|
|
case"ベ": return "ヘ"
|
|
case"ボ": return "ホ"
|
|
default: return character
|
|
}
|
|
}
|
|
/// 半濁点かどうか
|
|
public static func isHandakuten(_ character: Character) -> Bool {
|
|
[
|
|
"ぱ", "ぴ", "ぷ", "ぺ", "ぽ",
|
|
"パ", "ピ", "プ", "ペ", "ポ"
|
|
].contains(character)
|
|
}
|
|
/// 半濁点をつけて返す
|
|
public static func handakuten(_ character: Character) -> Character {
|
|
switch character {
|
|
case"は": return "ぱ"
|
|
case"ひ": return "ぴ"
|
|
case"ふ": return "ぷ"
|
|
case"へ": return "ぺ"
|
|
case"ほ": return "ぽ"
|
|
case"ハ": return "パ"
|
|
case"ヒ": return "ピ"
|
|
case"フ": return "プ"
|
|
case"ヘ": return "ペ"
|
|
case"ホ": return "ポ"
|
|
default: return character
|
|
}
|
|
}
|
|
/// 半濁点を外して返す
|
|
public static func muhandakuten(_ character: Character) -> Character {
|
|
switch character {
|
|
case"ぱ": return "は"
|
|
case"ぴ": return "ひ"
|
|
case"ぷ": return "ふ"
|
|
case"ぺ": return "へ"
|
|
case"ぽ": return "ほ"
|
|
case"パ": return "ハ"
|
|
case"ピ": return "ヒ"
|
|
case"プ": return "フ"
|
|
case"ペ": return "ヘ"
|
|
case"ポ": return "ホ"
|
|
default: return character
|
|
}
|
|
}
|
|
|
|
/// 濁点、小書き、半濁点などを相互に変換する関数。
|
|
public static func requestChange(_ character: Character) -> String {
|
|
if character.isLowercase {
|
|
return character.uppercased()
|
|
}
|
|
if character.isUppercase {
|
|
return character.lowercased()
|
|
}
|
|
|
|
if Set(["あ", "い", "え", "お", "や", "ゆ", "よ", "わ"]).contains(character) {
|
|
return String(kogaki(character))
|
|
}
|
|
|
|
if Set(["ぁ", "ぃ", "ぇ", "ぉ", "ゃ", "ゅ", "ょ", "ゎ"]).contains(character) {
|
|
return String(ogaki(character))
|
|
}
|
|
|
|
if Set(["か", "き", "く", "け", "こ", "さ", "し", "す", "せ", "そ", "た", "ち", "て", "と"]).contains(character) {
|
|
return String(dakuten(character))
|
|
}
|
|
|
|
if Set(["が", "ぎ", "ぐ", "げ", "ご", "ざ", "じ", "ず", "ぜ", "ぞ", "だ", "ぢ", "で", "ど"]).contains(character) {
|
|
return String(mudakuten(character))
|
|
}
|
|
|
|
if Set(["つ", "う"]).contains(character) {
|
|
return String(kogaki(character))
|
|
}
|
|
|
|
if Set(["っ", "ぅ"]).contains(character) {
|
|
return String(dakuten(ogaki(character)))
|
|
}
|
|
|
|
if Set(["づ", "ゔ"]).contains(character) {
|
|
return String(mudakuten(character))
|
|
}
|
|
|
|
if Set(["は", "ひ", "ふ", "へ", "ほ"]).contains(character) {
|
|
return String(dakuten(character))
|
|
}
|
|
|
|
if Set(["ば", "び", "ぶ", "べ", "ぼ"]).contains(character) {
|
|
return String(handakuten(mudakuten(character)))
|
|
}
|
|
|
|
if Set(["ぱ", "ぴ", "ぷ", "ぺ", "ぽ"]).contains(character) {
|
|
return String(muhandakuten(character))
|
|
}
|
|
|
|
return String(character)
|
|
}
|
|
}
|
|
|
|
public extension Character {
|
|
/// Returns the Katakanized version of the character.
|
|
@inlinable func toKatakana() -> Character {
|
|
if self.unicodeScalars.count != 1 {
|
|
return self
|
|
}
|
|
let scalar = self.unicodeScalars.first!
|
|
if 0x3041 <= scalar.value && scalar.value <= 0x3096 {
|
|
return Character(UnicodeScalar(scalar.value + 96)!)
|
|
} else {
|
|
return self
|
|
}
|
|
}
|
|
|
|
/// Returns the Hiraganized version of the character.
|
|
@inlinable func toHiragana() -> Character {
|
|
if self.unicodeScalars.count != 1 {
|
|
return self
|
|
}
|
|
let scalar = self.unicodeScalars.first!
|
|
if 0x30A1 <= scalar.value && scalar.value <= 0x30F6 {
|
|
return Character(UnicodeScalar(scalar.value - 96)!)
|
|
} else {
|
|
return self
|
|
}
|
|
}
|
|
}
|