defmodule Mojiex do
@moduledoc """
Japanese strings - Wide/Half "Kana" charactors Conversion Library for Elixir lang.
"""
@doc """
Japanese strings - Wide/Half "Kana" charactors Conversion Library for Elixir lang
## option combination
|atom |kind | |atom |kind |
|------|--------------|---|-----|--------------|
|:zk |全角カタカナ | ↔ |:hk | 半角カタカナ |
|:ze |全角英数 | ↔ |:he | 半角英数 |
|:he |ひらがな | ↔ |:kk | カタカナ |
|:zs |全角SPACE | ↔ |:hs | 半角SPACE |
## Examples
iex> Mojiex.convert("ABCD 01234あいうアイウABCD 01234アイウ", {:hk, :zk})
"ABCD 01234あいうアイウABCD 01234アイウ"
"""
@zenhan_list [
# 全角英数
ze: [start: 0xFF01, end: 0xFF5E],
# 半角英数
he: [start: 0x0021, end: 0x007E],
# ひらがな
hg: [start: 0x3041, end: 0x3096],
# カタカナ
kk: [start: 0x30A1, end: 0x30F6],
zs: [{" ", " "}],
zk: [
{"。", "。"},
{"「", "「"},
{"」", "」"},
{"、", "、"},
{"・", "・"},
{"ヲ", "ヲ"},
{"ァ", "ァ"},
{"ィ", "ィ"},
{"ゥ", "ゥ"},
{"ェ", "ェ"},
{"ォ", "ォ"},
{"ャ", "ャ"},
{"ュ", "ュ"},
{"ョ", "ョ"},
{"ッ", "ッ"},
{"ー", "ー"},
{"ア", "ア"},
{"イ", "イ"},
{"ウ", "ウ"},
{"エ", "エ"},
{"オ", "オ"},
{"カ", "カ"},
{"キ", "キ"},
{"ク", "ク"},
{"ケ", "ケ"},
{"コ", "コ"},
{"サ", "サ"},
{"シ", "シ"},
{"ス", "ス"},
{"セ", "セ"},
{"ソ", "ソ"},
{"タ", "タ"},
{"チ", "チ"},
{"ツ", "ツ"},
{"テ", "テ"},
{"ト", "ト"},
{"ナ", "ナ"},
{"ニ", "ニ"},
{"ヌ", "ヌ"},
{"ネ", "ネ"},
{"ノ", "ノ"},
{"ハ", "ハ"},
{"ヒ", "ヒ"},
{"フ", "フ"},
{"ヘ", "ヘ"},
{"ホ", "ホ"},
{"マ", "マ"},
{"ミ", "ミ"},
{"ム", "ム"},
{"メ", "メ"},
{"モ", "モ"},
{"ヤ", "ヤ"},
{"ユ", "ユ"},
{"ヨ", "ヨ"},
{"ラ", "ラ"},
{"リ", "リ"},
{"ル", "ル"},
{"レ", "レ"},
{"ロ", "ロ"},
{"ワ", "ワ"},
{"ン", "ン"},
{"゛", "゙"},
{"゜", "゚"},
{"ヺ", "ヺ"},
{"ヴ", "ヴ"},
{"ガ", "ガ"},
{"ギ", "ギ"},
{"グ", "グ"},
{"ゲ", "ゲ"},
{"ゴ", "ゴ"},
{"ザ", "ザ"},
{"ジ", "ジ"},
{"ズ", "ズ"},
{"ゼ", "ゼ"},
{"ゾ", "ゾ"},
{"ダ", "ダ"},
{"ヂ", "ヂ"},
{"ヅ", "ヅ"},
{"デ", "デ"},
{"ド", "ド"},
{"バ", "バ"},
{"パ", "パ"},
{"ビ", "ビ"},
{"ピ", "ピ"},
{"ブ", "ブ"},
{"プ", "プ"},
{"ベ", "ベ"},
{"ペ", "ペ"},
{"ボ", "ボ"},
{"ポ", "ポ"},
{"ヷ", "ヷ"}
]
]
@type zh_pair :: {atom(), atom()}
@spec convert(binary, zh_pair()) :: binary
def convert(str, {:zk, :hk}), do: zh_map(&ch_zk_hk/1, str)
def convert(str, {:hk, :zk}), do: zh_map(&ch_hk_zk/1, str)
def convert(str, {:hs, :zs}), do: zh_map(&ch_hs_zs/1, str)
def convert(str, {:zs, :hs}), do: zh_map(&ch_zs_hs/1, str)
def convert(str, {:ze, :he} = {from, to}), do: conv_range(str, from, to)
def convert(str, {:he, :ze} = {from, to}), do: conv_range(str, from, to)
def convert(str, {:hg, :kk} = {from, to}), do: conv_range(str, from, to)
def convert(str, {:kk, :hg} = {from, to}), do: conv_range(str, from, to)
# def convert(str, _), do: str
@spec conv_range(binary, atom(), atom()) :: binary
defp conv_range(str, from_kind, to_kind) do
dist = @zenhan_list[from_kind][:start] - @zenhan_list[to_kind][:start]
start_ch = @zenhan_list[from_kind][:start]
to_charlist(str)
|> Enum.map(fn c ->
if c >= start_ch && c <= @zenhan_list[from_kind][:end] do
c - dist
else
c
end
end)
|> to_string
end
@spec zh_map(fun(), binary) :: binary
defp zh_map(map_fn, str) do
to_charlist(str)
|> Enum.map(&map_fn.(<<&1::utf8>>))
|> to_string
end
@spec ch_zk_hk(binary) :: binary
defp ch_zk_hk(code) do
List.keyfind(@zenhan_list[:zk], code, 0, {nil, code}) |> elem(1)
end
@spec ch_hk_zk(binary) :: binary
defp ch_hk_zk(code) do
List.keyfind(@zenhan_list[:zk], code, 1, {code, nil}) |> elem(0)
end
@spec ch_zs_hs(binary) :: binary
def ch_zs_hs(code) do
List.keyfind(@zenhan_list[:zs], code, 0, {nil, code}) |> elem(1)
end
@spec ch_hs_zs(binary) :: binary
defp ch_hs_zs(code) do
List.keyfind(@zenhan_list[:zs], code, 1, {code, nil}) |> elem(0)
end
@spec list :: list()
def list do
@zenhan_list
end
end