How can I store diphthong vowel?

Hello!
Right now I’m creating keyboard for a tonal language but I’m new to the Keyman Developer program. So I asked AI(s) for help in creating rules.

Here is the context.

“a” + “b” > “ā”
“a” + “d” > “ǎ”
“a” + “g” > “ä”
“a” + “j” > “à”
“a” + “m” > “ã”
“a” + “s” > “â”
“a” + “v” > “á”
“e” + “b” > “ē”
“e” + “d” > “ě”
“e” + “g” > “ë”
“e” + “j” > “è”
“e” + “m” > “ẽ”
“e” + “s” > “ê”
“e” + “v” > “é”
“i” + “b” > “ī”
“i” + “d” > “ǐ”
“i” + “g” > “ï”
“i” + “j” > “ì”
“i” + “m” > “ĩ”
“i” + “s” > “î”
“i” + “v” > “í”
“o” + “b” > “ō”
“o” + “d” > “ǒ”
“o” + “g” > “ö”
“o” + “j” > “ò”
“o” + “m” > “õ”
“o” + “s” > “ô”
“o” + “v” > “ó”
“u” + “b” > “ū”
“u” + “d” > “ǔ”
“u” + “g” > “ü”
“u” + “j” > “ù”
“u” + “m” > “ũ”
“u” + “s” > “û”
“u” + “v” > “ú”
“w” + “b” > “w̄”
“w” + “d” > “w̌”
“w” + “g” > “ẅ”
“w” + “j” > “ẁ”
“w” + “m” > “w̃”
“w” + “s” > “ŵ”
“w” + “v” > “ẃ”

So far, it’s doing super well. “for single vowel with diacritic”

(Rules created by AI)
store(tones) ‘bdgjmsv’
store(vowels) ‘aeiouw’
store(output) ‘̄̌̈̀̃̂́’ c Corresponding tone marks for each tone in ‘tones’

c General rule to combine vowels with tones using index lookup
any(vowels) + any(tones) > context index(output, 1)

But I’m struggling to make diphthong vowels work. I tried to apply the rule from the AI above, but I don’t know how to store diphthong vowels. I want to do something bellow this, but the problem is that space also counts as a character. So, the rules did not work correctly.

store(tones) ‘bdgjmsv’
store(vowels) ‘ai au aw’
store(output) ‘̄̌̈̀̃̂́’ c Corresponding tone marks for each tone in ‘tones’
c General rule to combine vowels with tones using index lookup
any(vowels) + any(tones) > context index(output, 1)

(diacritics should go to the first vowel).
“ai” + “b” > “āi”
“ai” + “d” > “ǎi”
“ai” + “g” > “äi”
“ai” + “j” > “ài”
“ai” + “m” > “ãi”
“ai” + “s” > “âi”
“ai” + “v” > “ái”
“au” + “b” > “āu”
“au” + “d” > “ǎu”
“au” + “g” > “äu”
“au” + “j” > “àu”
“au” + “m” > “ãu”
“au” + “s” > “âu”
“au” + “v” > “áu”
“aw” + “b” > “āw”
“aw” + “d” > “ǎw”
“aw” + “g” > “äw”
“aw” + “j” > “àw”
“aw” + “m” > “ãw”
“aw” + “s” > “âw”
“aw” + “v” > “áw”

Thank you in advance! _/||_

I believe this is a limitation in the language, that you cannot set up a store like an array and use index to retrieve a desired multi-character unit.

Won’t the rules for single vowel with diacritic work for diphthongs, if the user presses the key for tone before the second vowel?
If the user presses “a” “b” “i” won’t it give you “āi” ?

1 Like

Thank you for answer my question.
And yes the rule for single vowel dose apply to diphthongs as well if pressed in that order “a” “b” “i” it will give “āi”. But I just don’t wanna change the way people type. I guess I may have to manually give each rule for the diphthongs.

Off the top of my head I think this might work:

store(vowels) ‘aeiouw’
store(dipthong) ‘iuw’
store(tones) ‘bdgjmsv’
store(output) U+0304 U+030C U+0308 U+0300 U+0303 U+0302 U+0301 c Corresponding tone marks for each tone in ‘tones’

any(vowels) any(dipthong) + any(tones) > index(vowels,1) index(output,3) index(dipthong,2)

When you are using index the two stores must have the same number of characters. So, tones and output must have the same number.

Your entry store(vowels) ‘ai au aw’ won’t work because you cannot have multiple characters in a store to be matched on.

1 Like

It works! Wow! Thank you so much!
I spent hours reading rule guides and asking every AI I could find.
One simple, brilliant rule did the trick! Thank you again. I’m absolutely going to apply this to my keyboard rules.

I worked on this for hours and managed a partial workaround. Here’s my clunky (but also working!) method, lol.

store(vowels) 'aeiouwAEIOUW'
store(tones) 'bdgjmsvBDGJMSV'
store(diacritics) U+0304 U+030C U+0308 U+0300 U+0303 U+0302 U+0301 U+0304 U+030C U+0308 U+0300 U+0303 U+0302 U+0301 U+0304 U+030C U+0308 U+0300 U+0303 U+0302 U+0301   c Corresponding diacritical marks (3x) for each tone in 'tones'

c Rules for double vowels to 'ng' endings
'aa' + any(tones) > context(1) index(diacritics, 3) 'ng'
'Aa' + any(tones) > context(1) index(diacritics, 3) 'ng'
'aA' + any(tones) > context(1) index(diacritics, 3) 'ng'
'AA' + any(tones) > context(1) index(diacritics, 3) 'NG'

'ee' + any(tones) > context(1) index(diacritics, 3) 'ng'
'Ee' + any(tones) > context(1) index(diacritics, 3) 'ng'
'eE' + any(tones) > context(1) index(diacritics, 3) 'ng'
'EE' + any(tones) > context(1) index(diacritics, 3) 'NG'

'oo' + any(tones) > context(1) index(diacritics, 3) 'ng'
'Oo' + any(tones) > context(1) index(diacritics, 3) 'ng'
'oO' + any(tones) > context(1) index(diacritics, 3) 'ng'
'OO' + any(tones) > context(1) index(diacritics, 3) 'NG'

'ww' + any(tones) > context(1) index(diacritics, 3) 'ng'
'Ww' + any(tones) > context(1) index(diacritics, 3) 'ng'
'wW' + any(tones) > context(1) index(diacritics, 3) 'ng'
'WW' + any(tones) > context(1) index(diacritics, 3) 'NG'

'ang' + any(tones) > context(1) index(diacritics, 4) 'ng'
'Ang' + any(tones) > context(1) index(diacritics, 4) 'ng'
'aNg' + any(tones) > context(1) index(diacritics, 4) 'ng'
'ANg' + any(tones) > context(1) index(diacritics, 4) 'ng'
'aNG' + any(tones) > context(1) index(diacritics, 4) 'ng'
'AnG' + any(tones) > context(1) index(diacritics, 4) 'ng'
'AgN' + any(tones) > context(1) index(diacritics, 4) 'ng'
'ANG' + any(tones) > context(1) index(diacritics, 4) 'NG'

'eng' + any(tones) > context(1) index(diacritics, 4) 'ng'
'Eng' + any(tones) > context(1) index(diacritics, 4) 'ng'
'eNg' + any(tones) > context(1) index(diacritics, 4) 'ng'
'ENg' + any(tones) > context(1) index(diacritics, 4) 'ng'
'enG' + any(tones) > context(1) index(diacritics, 4) 'ng'
'EnG' + any(tones) > context(1) index(diacritics, 4) 'ng'
'eNG' + any(tones) > context(1) index(diacritics, 4) 'ng'
'ENG' + any(tones) > context(1) index(diacritics, 4) 'NG'

'ong' + any(tones) > context(1) index(diacritics, 4) 'ng'
'Ong' + any(tones) > context(1) index(diacritics, 4) 'ng'
'oNg' + any(tones) > context(1) index(diacritics, 4) 'ng'
'ONg' + any(tones) > context(1) index(diacritics, 4) 'ng'
'onG' + any(tones) > context(1) index(diacritics, 4) 'ng'
'OnG' + any(tones) > context(1) index(diacritics, 4) 'ng'
'oNG' + any(tones) > context(1) index(diacritics, 4) 'ng'
'ONG' + any(tones) > context(1) index(diacritics, 4) 'NG'

'wng' + any(tones) > context(1) index(diacritics, 4) 'ng'
'Wng' + any(tones) > context(1) index(diacritics, 4) 'ng'
'wNg' + any(tones) > context(1) index(diacritics, 4) 'ng'
'WNg' + any(tones) > context(1) index(diacritics, 4) 'ng'
'wnG' + any(tones) > context(1) index(diacritics, 4) 'ng'
'WnG' + any(tones) > context(1) index(diacritics, 4) 'ng'
'wNG' + any(tones) > context(1) index(diacritics, 4) 'ng'
'WNG' + any(tones) > context(1) index(diacritics, 4) 'NG'

c Sorted rules by base vowel, then case variations
'ai' + any(tones) > context(1) index(diacritics, 3) context(2)
'Ai' + any(tones) > context(1) index(diacritics, 3) context(2)
'aI' + any(tones) > context(1) index(diacritics, 3) "i"
'AI' + any(tones) > context(1) index(diacritics, 3) context(2)

'au' + any(tones) > context(1) index(diacritics, 3) context(2)
'Au' + any(tones) > context(1) index(diacritics, 3) context(2)
'aU' + any(tones) > context(1) index(diacritics, 3) "u"
'AU' + any(tones) > context(1) index(diacritics, 3) context(2)

'aw' + any(tones) > context(1) index(diacritics, 3) context(2)
'Aw' + any(tones) > context(1) index(diacritics, 3) context(2)
'aW' + any(tones) > context(1) index(diacritics, 3) "w"
'AW' + any(tones) > context(1) index(diacritics, 3) context(2)

c Rule for all single vowels
any(vowels) + any(tones) > context index(diacritics, 2)


store(vowels) 'aeiouw'
store(dipthong) 'iuw'
store(tones) 'bdgjmsv'
store(output) U+0304 U+030C U+0308 U+0300 U+0303 U+0302 U+0301 c Corresponding tone marks for each tone in 'tones'

any(vowels) any(dipthong) + any(tones) > context(1) index(output, 3) context(2)

_/||_

1 Like

I’d like to show off a bit of what I learned today.
Thank you!
Also, how can I close this post again?

store(mixcase_double_vowel_A) 'aA'
store(mixcase_double_vowel_E) 'eE'
store(mixcase_double_vowel_O) 'oO'
store(mixcase_double_vowel_W) 'wW'

store(lowercase_dipthong_vowels) 'iuw'
store(uppercase_dipthong_vowels) 'IUW'

store(single_vowels) 'aeiouwAEIOUW'

store(tone_triggers) 'bdgjmsvBDGJMSV'
store(diacritical_marks) U+0304 U+030C U+0308 U+0300 U+0303 U+0302 U+0301 U+0304 U+030C U+0308 U+0300 U+0303 U+0302 U+0301 U+0304 U+030C U+0308 U+0300 U+0303 U+0302 U+0301 c Corresponding diacritical marks for each tone triggers

c Rule for all nasal vowels
'ANG' + any(tone_triggers) > context(1) index(diacritical_marks,4) 'NG'
any(mixcase_double_vowel_A) 'Ng' + any(tone_triggers) > context(1) index(diacritical_marks,4) 'NG'
any(mixcase_double_vowel_A) 'nG' + any(tone_triggers) > context(1) index(diacritical_marks,4) 'ng'
any(mixcase_double_vowel_A) 'ng' + any(tone_triggers) > context(1) index(diacritical_marks,4) 'ng'

'ENG' + any(tone_triggers) > context(1) index(diacritical_marks,4) 'NG'
any(mixcase_double_vowel_E) 'Ng' + any(tone_triggers) > context(1) index(diacritical_marks,4) 'NG'
any(mixcase_double_vowel_E) 'nG' + any(tone_triggers) > context(1) index(diacritical_marks,4) 'ng'
any(mixcase_double_vowel_E) 'ng' + any(tone_triggers) > context(1) index(diacritical_marks,4) 'ng'

'ONG' + any(tone_triggers) > context(1) index(diacritical_marks,4) 'NG'
any(mixcase_double_vowel_O) 'Ng' + any(tone_triggers) > context(1) index(diacritical_marks,4) 'NG'
any(mixcase_double_vowel_O) 'nG' + any(tone_triggers) > context(1) index(diacritical_marks,4) 'ng'
any(mixcase_double_vowel_O) 'ng' + any(tone_triggers) > context(1) index(diacritical_marks,4) 'ng'

'WNG' + any(tone_triggers) > context(1) index(diacritical_marks,4) 'NG'
any(mixcase_double_vowel_W) 'Ng' + any(tone_triggers) > context(1) index(diacritical_marks,4) 'NG'
any(mixcase_double_vowel_W) 'nG' + any(tone_triggers) > context(1) index(diacritical_marks,4) 'ng'
any(mixcase_double_vowel_W) 'ng' + any(tone_triggers) > context(1) index(diacritical_marks,4) 'ng'

c Rule for all double vowels
'AA' + any(tone_triggers) > context(1) index(diacritical_marks, 3) 'NG'
any(mixcase_double_vowel_A) any(mixcase_double_vowel_A) + any(tone_triggers) > context(1) index(diacritical_marks,3) 'ng'

'EE' + any(tone_triggers) > context(1) index(diacritical_marks, 3) 'NG'
any(mixcase_double_vowel_E) any(mixcase_double_vowel_E) + any(tone_triggers) > context(1) index(diacritical_marks,3) 'ng'

'OO' + any(tone_triggers) > context(1) index(diacritical_marks, 3) 'NG'
any(mixcase_double_vowel_O) any(mixcase_double_vowel_O) + any(tone_triggers) > context(1) index(diacritical_marks,3) 'ng'

'WW' + any(tone_triggers) > context(1) index(diacritical_marks, 3) 'NG'
any(mixcase_double_vowel_W) any(mixcase_double_vowel_W) + any(tone_triggers) > context(1) index(diacritical_marks,3) 'ng'

c Rule for all dipthong_vowels with 'a' in front
"a" any(lowercase_dipthong_vowels) + any(tone_triggers) > context(1) index(diacritical_marks,3) index(lowercase_dipthong_vowels,2)
"a" any(uppercase_dipthong_vowels) + any(tone_triggers) > context(1) index(diacritical_marks,3) index(lowercase_dipthong_vowels,2)
"A" any(lowercase_dipthong_vowels) + any(tone_triggers) > context(1) index(diacritical_marks,3) index(lowercase_dipthong_vowels,2)
"A" any(uppercase_dipthong_vowels) + any(tone_triggers) > context(1) index(diacritical_marks,3) index(uppercase_dipthong_vowels,2)


c Rule for all single vowels
any(single_vowels) + any(tone_triggers) > context index(diacritical_marks, 2)

Feed the internet Feed machine!

1 Like

Nice!

Also, may be exciting for the future: the LDML keyboard standard (which Keyman currently supports on Windows, Linux, and macOS) does support the equivalent of multi-character store matches. We are working on mobile support this year (alongside graphical development tools, authoring documentation)

2 Likes

That’s fantastic! Great job to all of you!