Skip to content

Commit

Permalink
Minor fixes & allow inputting pronunciation
Browse files Browse the repository at this point in the history
  • Loading branch information
CryZe committed Oct 12, 2020
1 parent b689768 commit 47149dc
Show file tree
Hide file tree
Showing 11 changed files with 161 additions and 76 deletions.
12 changes: 8 additions & 4 deletions crates/cli/src/main.rs
@@ -1,7 +1,7 @@
use std::env;

use anyhow::{Context, Result};
use phonetics_to_hangul::{darpabet, ipa_to_hangul, word_lookup};
use phonetics_to_hangul::{arpabet, ipa_to_hangul, word_lookup};
use structopt::StructOpt;

/// Turns a word's pronunciation into 한글 with pronunciation as close as
Expand All @@ -23,7 +23,7 @@ fn try_run() -> Result<()> {
let opt: Opt = StructOpt::from_args();

if !opt.online {
let dictionary = darpabet::Dictionary::parse(darpabet::CMUDICT_07B)
let dictionary = arpabet::Dictionary::parse(arpabet::CMUDICT_07B)
.context("Failed parsing the dictionary.")?;

let pronunciation = dictionary
Expand All @@ -38,7 +38,10 @@ fn try_run() -> Result<()> {
}
println!();

println!("한글: {}", ipa_to_hangul::convert(pronunciation));
println!(
"한글: {}",
ipa_to_hangul::convert(&mut Default::default(), pronunciation).collect::<String>()
);
} else {
let user = env::var("DICT_USER").context(
"For online usage, you need to provide the \
Expand All @@ -56,7 +59,8 @@ fn try_run() -> Result<()> {
.lookup(&opt.word, &opt.lang)
.context("Failed looking up the word.")?;

let hangul = ipa_to_hangul::convert(word.pronunciation.chars());
let hangul = ipa_to_hangul::convert(&mut Default::default(), word.pronunciation.chars())
.collect::<String>();

println!("Word: {}", word.word);
println!("Pronunciation: {}", word.pronunciation);
Expand Down
10 changes: 6 additions & 4 deletions crates/gui/src/main.rs
Expand Up @@ -6,11 +6,12 @@ use iui::{
controls::{Entry, Label, VerticalBox},
prelude::*,
};
use phonetics_to_hangul::{darpabet, ipa_to_hangul};
use phonetics_to_hangul::{arpabet, hangul_builder, ipa_to_hangul};
use LayoutStrategy::Compact;

struct State {
dictionary: darpabet::Dictionary<'static>,
dictionary: arpabet::Dictionary<'static>,
builder: hangul_builder::Builder,
ui: UI,
hangul: Entry,
pronunciation: Entry,
Expand All @@ -30,7 +31,7 @@ impl State {

if let Some(pronunciation) = self.dictionary.look_up(word) {
pronunciations.extend(pronunciation.clone());
hanguls.push_str(&ipa_to_hangul::convert(pronunciation));
hanguls.extend(ipa_to_hangul::convert(&mut self.builder, pronunciation));
} else {
pronunciations.push('?');
hanguls.push('?');
Expand All @@ -43,7 +44,7 @@ impl State {
}

fn main() {
let dictionary = darpabet::Dictionary::parse(darpabet::CMUDICT_07B).unwrap();
let dictionary = arpabet::Dictionary::parse(arpabet::CMUDICT_07B).unwrap();

let ui = UI::init().unwrap();
let mut win = Window::new(&ui, "Phonetics to 한글", 300, 100, WindowType::NoMenubar);
Expand All @@ -56,6 +57,7 @@ fn main() {

let state = Rc::new(RefCell::new(State {
dictionary,
builder: hangul_builder::Builder::new(),
ui: ui.clone(),
hangul: hangul.clone(),
pronunciation: pronunciation.clone(),
Expand Down
138 changes: 99 additions & 39 deletions crates/web/src/lib.rs
@@ -1,33 +1,107 @@
use phonetics_to_hangul::{darpabet, ipa_to_hangul};
#![recursion_limit = "256"]

use phonetics_to_hangul::{arpabet, hangul_builder, ipa_to_hangul};
use wasm_bindgen::prelude::*;
use yew::prelude::*;

struct Model {
struct State {
link: ComponentLink<Self>,
dictionary: darpabet::Dictionary<'static>,
dictionary: arpabet::Dictionary<'static>,
builder: hangul_builder::Builder,
pronunciations: String,
hanguls: String,
word: String,
}

enum Message {
WordChanged(InputData),
PronunciationChanged(InputData),
}

impl State {
fn recalc_from_word(&mut self) {
self.pronunciations.clear();
self.hanguls.clear();

let word = if self.word.is_empty() {
"Example Text"
} else {
&self.word
};

for (i, word) in word.split_whitespace().enumerate() {
if i != 0 {
self.pronunciations.push(' ');
self.hanguls.push(' ');
}

if let Some(pronunciation) = self.dictionary.look_up(word) {
self.pronunciations.extend(pronunciation.clone());
self.hanguls
.extend(ipa_to_hangul::convert(&mut self.builder, pronunciation));
} else {
self.pronunciations.push('?');
self.hanguls.push('?');
}
}
}

fn recalc_from_pronunciation(&mut self) {
self.word.clear();
self.hanguls.clear();

let pronunciations = if self.pronunciations.is_empty() {
"ɪɡzæmpʌl tɛkst"
} else {
&self.pronunciations
};

for (i, pronunciation) in pronunciations.split_whitespace().enumerate() {
if i != 0 {
self.hanguls.push(' ');
}

self.hanguls.extend(ipa_to_hangul::convert(
&mut self.builder,
pronunciation.chars(),
));
}
}
}

impl Component for Model {
impl Component for State {
type Message = Message;

type Properties = ();

fn create((): (), link: ComponentLink<Self>) -> Self {
let dictionary = darpabet::Dictionary::parse(darpabet::CMUDICT_07B).unwrap();
Self {
let dictionary = arpabet::Dictionary::parse(arpabet::CMUDICT_07B).unwrap();
let mut state = Self {
link,
dictionary,
builder: hangul_builder::Builder::new(),
pronunciations: String::new(),
hanguls: String::new(),
word: String::new(),
}
};
state.recalc_from_word();
state
}

fn update(&mut self, Message::WordChanged(change): Message) -> ShouldRender {
self.word = change.value;
fn update(&mut self, message: Message) -> ShouldRender {
match message {
Message::WordChanged(change) => {
self.word.clear();
self.word.push_str(&change.value);
self.recalc_from_word();
}
Message::PronunciationChanged(change) => {
self.pronunciations.clear();
self.pronunciations.push_str(&change.value);
self.recalc_from_pronunciation();
}
}

true
}

Expand All @@ -36,34 +110,10 @@ impl Component for Model {
}

fn view(&self) -> Html {
let mut pronunciations = String::new();
let mut hanguls = String::new();

let word = if self.word.is_empty() {
"Example Text"
} else {
&self.word
};

for (i, word) in word.split_whitespace().enumerate() {
if i != 0 {
pronunciations.push(' ');
hanguls.push(' ');
}

if let Some(pronunciation) = self.dictionary.look_up(word) {
pronunciations.extend(pronunciation.clone());
hanguls.push_str(&ipa_to_hangul::convert(pronunciation));
} else {
pronunciations.push('?');
hanguls.push('?');
}
}

html! {
<div>
<p>
{"English Text: "}
{"English Text:"}
<div class="result">
<input
type="text"
Expand All @@ -74,15 +124,25 @@ impl Component for Model {
</div>
</p>
<p>
{"Pronunciation (IPA): "}
{"Pronunciation (IPA):"}
<div class="result">
{&pronunciations}
<input
type="text"
placeholder="ɪɡzæmpʌl tɛkst"
value={&self.pronunciations}
oninput=self.link.callback(|w| Message::PronunciationChanged(w))
/>
</div>
</p>
<p>
{"한글: "}
{"한글:"}
<div class="result">
{&hanguls}
<input
type="text"
placeholder="익샘펄 댘슽"
value={&self.hanguls}
readonly=true
/>
</div>
</p>
</div>
Expand All @@ -93,5 +153,5 @@ impl Component for Model {
#[wasm_bindgen(start)]
pub fn main() {
yew::initialize();
App::<Model>::new().mount_to_body();
App::<State>::new().mount_to_body();
}
26 changes: 13 additions & 13 deletions docs/pkg/web.js
Expand Up @@ -276,6 +276,18 @@ async function init(input) {
imports.wbg.__wbindgen_object_drop_ref = function(arg0) {
takeObject(arg0);
};
imports.wbg.__wbg_removeEventListener_9ffcd175e0916270 = handleError(function(arg0, arg1, arg2, arg3, arg4) {
getObject(arg0).removeEventListener(getStringFromWasm0(arg1, arg2), getObject(arg3), arg4 !== 0);
});
imports.wbg.__wbindgen_cb_drop = function(arg0) {
const obj = takeObject(arg0).original;
if (obj.cnt-- == 1) {
obj.a = 0;
return true;
}
var ret = false;
return ret;
};
imports.wbg.__wbg_new_59cb74e423758ede = function() {
var ret = new Error();
return addHeapObject(ret);
Expand Down Expand Up @@ -344,18 +356,6 @@ async function init(input) {
var ret = getObject(arg0).removeChild(getObject(arg1));
return addHeapObject(ret);
});
imports.wbg.__wbg_removeEventListener_9ffcd175e0916270 = handleError(function(arg0, arg1, arg2, arg3, arg4) {
getObject(arg0).removeEventListener(getStringFromWasm0(arg1, arg2), getObject(arg3), arg4 !== 0);
});
imports.wbg.__wbindgen_cb_drop = function(arg0) {
const obj = takeObject(arg0).original;
if (obj.cnt-- == 1) {
obj.a = 0;
return true;
}
var ret = false;
return ret;
};
imports.wbg.__wbg_value_91d41b8dbd0b2f0b = function(arg0, arg1) {
var ret = getObject(arg1).value;
var ptr0 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
Expand Down Expand Up @@ -471,7 +471,7 @@ async function init(input) {
getInt32Memory0()[arg0 / 4 + 1] = len0;
getInt32Memory0()[arg0 / 4 + 0] = ptr0;
};
imports.wbg.__wbindgen_closure_wrapper1312 = function(arg0, arg1, arg2) {
imports.wbg.__wbindgen_closure_wrapper1321 = function(arg0, arg1, arg2) {
var ret = makeMutClosure(arg0, arg1, 29, __wbg_adapter_16);
return addHeapObject(ret);
};
Expand Down
Binary file modified docs/pkg/web_bg.wasm
Binary file not shown.
6 changes: 3 additions & 3 deletions docs/style.css
Expand Up @@ -20,10 +20,9 @@ body > div {

div.result {
border-bottom: 2px solid rgba(255, 255, 255, 0.8);
color: white;
margin-top: 15px;
margin-top: 12px;
padding-bottom: 5px;
margin-bottom: 40px;
margin-bottom: 35px;
padding-left: 5px;
padding-right: 5px;
}
Expand All @@ -35,6 +34,7 @@ input {
color: white;
font-family: 'Fira Sans', 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
font-size: 20px;
height: 30px;
font-weight: 300;
}

Expand Down
File renamed without changes.
10 changes: 8 additions & 2 deletions src/hangul_builder.rs
Expand Up @@ -248,8 +248,14 @@ impl Builder {
self.pos.advance();
}

pub fn finish(mut self) -> String {
pub fn finish(&mut self) -> impl Iterator<Item = char> + '_ {
self.finish_syllable();
self.buf.nfc().collect()
self.buf.nfc()
}

pub fn restart(&mut self) {
self.buf.clear();
self.buffered_cons = None;
self.pos = Position::InitialConsonant;
}
}
29 changes: 21 additions & 8 deletions src/ipa_to_hangul.rs
@@ -1,7 +1,10 @@
use crate::hangul_builder::{self, Consonant, Position, Vowel};

pub fn convert(phonetics: impl IntoIterator<Item = char>) -> String {
let mut builder = hangul_builder::Builder::new();
pub fn convert(
builder: &mut hangul_builder::Builder,
phonetics: impl IntoIterator<Item = char>,
) -> impl Iterator<Item = char> + '_ {
builder.restart();

let mut chars = phonetics.into_iter().peekable();

Expand Down Expand Up @@ -91,13 +94,23 @@ pub fn convert(phonetics: impl IntoIterator<Item = char>) -> String {
}
'ʃ' | 'ʒ' => {
builder.push_consonant(Consonant::S);
// TODO: Suboptimal af
if !matches!(
chars.peek().copied(),
Some('j') | Some('ɪ') | Some('y') | Some('i')
) {
builder.push_vowel(Vowel::I)
let mut vowel = Vowel::I;
if let Some(c) = chars.peek() {
if let Some(v) = match c {
'ɛ' | 'æ' => Some(Vowel::Yae),
'a' | 'ɐ' => Some(Vowel::Ya),
'ʌ' | 'ɔ' | 'ɒ' | 'ɑ' => Some(Vowel::Yeo),
'e' => Some(Vowel::Ye),
'o' => Some(Vowel::Yo),
'ʊ' | 'u' => Some(Vowel::Yu),
'j' | 'ɪ' | 'y' | 'i' => Some(Vowel::I),
_ => None,
} {
chars.next();
vowel = v;
}
}
builder.push_vowel(vowel);
}
'w' | 'v' => {
if let Some(c) = chars.peek() {
Expand Down

0 comments on commit 47149dc

Please sign in to comment.