Current section

Files

Jump to
pinyin lib pinyin.ex
Raw

lib/pinyin.ex

defmodule Pinyin do
import Ascii
data_path = Path.join(__DIR__, "data/Mandarin.dat")
codes = Enum.reduce File.stream!(data_path), [], fn(line, acc) ->
[code, pinyin] = String.split line, " "
[{code, pinyin} | acc]
end
for {code, pinyin} <- codes do
integer_code = String.to_integer(code, 16)
pinyins = pinyin |> String.rstrip |> String.split(",")
defp get_pinyin(unquote(integer_code)) do
unquote(List.first(pinyins))
end
end
defp get_pinyin(other) do
<< other :: utf8 >>
end
def pinyin(han) do
Enum.map(parse_codepoints(han), fn(ch) ->
if String.length(ch) == 1 do
<< codepoint :: utf8 >> = ch
get_pinyin(codepoint)
else
ch
end
end)
end
def letter_with_tone(han) do
pinyin(han) |>
Enum.map(fn(ch) -> pinyin_to_ascii_with_tone(ch) end)
end
def letter(han) do
pinyin(han) |>
Enum.map(fn(ch) -> pinyin_to_ascii(ch) end)
end
def permlink(han, sep \\ "-") do
pinyin(han)
|> Enum.map(fn(ch) -> pinyin_to_ascii(ch) end)
|> Enum.join sep
end
defp parse_codepoints(han) do
String.codepoints(han) |> classify_letter_number
end
# join letter codepoints in a word
# ["到", "阿", "a", "s", "d", "f", "a", "a", "s", "f"]
# transform =>
# ["到", "阿", "asdfaasf"]
defp classify_letter_number([]), do: []
defp classify_letter_number([a]), do: [a]
defp classify_letter_number(list) do
[a, b | rest] = list
cond do
!is_english_number?(b) -> [a, b | classify_letter_number(rest)]
!is_english_number?(a) -> [a | classify_letter_number([b | rest])]
true -> classify_letter_number([a <> b | rest])
end
end
defp is_english_number?(str) do
number = if String.length(str) == 1 do
<< val :: utf8 >> = str
val
else
<< val :: utf8 >> = String.last(str)
val
end
( number >= 97 and number <= 122 ) or # a-z
( number >= 65 and number <= 90 ) or # A-Z
( number >= 48 and number <= 57 ) # 0-9
end
end