Topic Applying a Rule twice

We have two new locations for Keyman technical support:

The Tavultesoft Forums are now read only.

# Applying a Rule twice   2016-02-14 08:39:23.653
br Julian Griffin OSL
I’m asking for help with a complex problem in relation to 'Menus' as defined in the IPAMenu.kmn example.

   What I am seeking to do is have a Rule something like:
Any(Latin Letter) '=' [Specific Latin Letter] > Context(1) Index(StrickOuts,1)
                                                          Index(Sup_[the Specific Latin Letter],1)
This Rule is then repeated for each Specific Latin Letter ie a-z, A-Z.
Now this is simple enough; I have made it work in an early version of the keyboard.

   For some [Specific Latin Letters]{but not all} I want to display a menu, eg |1a 2A 3á 4Á|. I have made this work from the very helpful IPAMenu.kmn example.

   Now I need to join the two ideas together.
So, for example, if a user types, [e][=][a] Keyman should respond with:
e=|1a 2A 3á 4Á|. On selecting an option number, the menu is deleted and the appropriate symbol replaces the menu. eg If 3 is selected, Keyman gives e=á. Which I have also got to work nicely.

   However; and here’s the rub, I can see no way to apply the original Rule to this output. I now need a way to fire the original Rule:
Any(Latin Letter) '=' [Specific Latin Letter] > Context(1) Index(StrickOuts,1)
                                    `                        Index(Sup_á,1)
on the output text e=á.

That is to say, something like:
    'e' '=' + 'á' > Context(1) Index(StrickOuts,1) Index(Sup_á,1)

   My understanding is that Keyman only fires a Rule at a user’s input. So, I think I need, to not end after the menu option selection. Then a way to store the user entered Context eg 'e' and to store the output from the menu option selection eg 'á'.

   Giving a syntax of something like:
Original Entry + á > Original Entry Index(StrickOuts,Original Entry) Index(Sup_á,1)

   Resulting in a Latin Letter followed by two Unicode symbols.

   It is the use of a menu to select some of the trigger letters for Rules, that I cannot see how to resolve.

   But I feel it should be possible.

   Any thoughts would be greatly appreciated

Julian Griffin
# RE: Applying a Rule twice   2016-02-16 06:52:57.837
Marc Durdin
Tavultesoft Staff
Yes, this can be done, using multiple groups, with a context-only group. For example:

outs(a_menu) + '3' > 'á' use(pm)

any(latin_letter) '=á' > Context(1) Index(StrickOuts,1) Index(Sup_á,1)

Note that group(pm) does not have a using keys clause, so this shows it is working only on the context. The context is updated by the previous rule before entering the group, so this should do exactly what you are asking.

With a bit of planning, you can do all your processing just once in that second group.

You can learn more about multiple groups at
# RE: Applying a Rule twice   2016-02-19 00:48:44.363
br Julian Griffin OSL
Thank you for your clear response.

   But I having trouble getting the Context into the new Group.

   The snippet below, I hope, shows my problem.
group(a_Menu) using keys c Resolve menu to a character.
   + any(choices3) > index(a_char, 2) Use(Collapes)

   Store(First)  'a'
   Store(Second) '='
   Any(First) Any(Second) U+F002 > Context(1) Index(Strickout,1) Index(Sup_A-,1)
   Any(First) Any(Second) U+F003 > Context(1) Index(Strickout,1) Index(Sup_ar,1)
   Any(First) Any(Second) U+F004 > Context(1) Index(Strickout,1) Index(Sup_b,1)

So in use:
   Entering 'a=a' outputs 'a=[a1 A2 á3 Á4]'
   Entering '3', {Goes to 'Group(a-menu)', this resolves to} 'a=á'
   Then the 'Group(Collapse)' takes 'a=á' and outputs ‘a U+E061 U+F402’ {without the spaces}

   The 'a' is the model for the two unicodes: 'U+E061' & 'U+F402'. A different 'a' and 'á' eg 'b' & 's', gives different Unicodes.
   The '=' is the identifier that 'U+E061' & 'U+F402', and 'a' and 'á 'need to be resolved to ‘a U+E061 U+F402’, so is dropped from the output.

   Ok, this all works as expected. My problem is with the two Stores 'First' & ‘Second'. It only works for me if 'First' & ‘Second' are constants.

   So to my question, How do I get the Context {which should be 'a=á'} into the Group(Collapse)?

   Something like:
group(a_Menu) using keys
+ any(choices3) > index(a_char, 2) Set(First = Context(1)) Set(Second = Context(2)) Use(Collapse)

But this is not valid syntax.

Julian Griffin
# RE: Applying a Rule twice   2016-02-19 17:29:20.337
Marc Durdin
Tavultesoft Staff
I'm not entirely sure what you are getting at, sorry. You shouldn't need to pass context to the second group by hand as you are describing. Can you give me a little more detail on the stores that you are referencing (e.g. I don't know what a_char has in it) -- I assume the First and Second stores have more than just a single character in them?
# RE: Applying a Rule twice   2016-02-20 01:38:10.540
br Julian Griffin OSL
I can understand your confusion; the keyboard definition is now quite complex, with some 600 lines, more than 150 Store statements, and more than 200 Rules. It also makes extensive use of the Private Use Area of Unicode.

   Below are a number of snippets of code that I hope will better explain what I was waffling about in my post.

   I have also placed the complete 'TPA Keyboard' definition, and the font the keyboard is designed to work with, in a public folder on my OneDrive. There is also a couple of images of the input: 'a=a', and the output: a^a.

   The public link to TPA on my OneDrive is:
You are welcome to download the font (and use as you will) and the keyboard definition.

The functionality I am having trouble with is, in brief:
  • Three glyphs are typed or selected from a menu, are then converted to three other glyphs.

      o The first glyph is any Latin letter,
      o The second glyph is the equal's symbol '=', and
      o The third glyph is either a Latin letter or a glyph selected from a menu.

      o The ‘Collapse’ group's purpose is to collapse these three glyphs to a different set of three glyphs;
         • The first of these new glyphs is the same as the first glyph of the input string,
         • The second glyph is a zero width glyph that is selected from a set of glyphs {Store(Strickout)} to match the First glyph,
         • The third glyph is also a zero width glyph that is selected from a list of superscript glyphs {Store(Sup_A-)} to match the First glyph.

NB the only Rule/Group currently coded for this functionality are for the input
string:      ‘a=a’ giving:
followed by: ‘2’   giving:

   Below is the Group for handling the 'A' menu.
Group(a_Menu) using keys
   if(GlueFlag = 'No' ) + Any(Choices3) > Index(a_Char, 2) Use(Collapse)
   if(GlueFlag = 'Yes') + Any(Choices3) > Index(a_Char, 2) $TPAglue
   + [K_BKSP]                           > nul
   Nomatch                              > dk(a_err) use(MenuErrHandler)

   Below is the Collapse group. Only the first three lines of which are valid. This other lines will be added when the functionality is sorted out.
   Store(First)  'a'
   Any(First) '=' U+F002 > Context(1) Index(Strickout,1) Index(Sup_A-,1)
c More lines like the one above are added here eg
c Any(First) '=' U+F001 > Context(1) Index(Strickout,1) Index(Sup_a,1)
c Any(First) '=' U+F003 > Context(1) Index(Strickout,1) Index(Sup_er,1)
c Any(First) '=' U+F004 > Context(1) Index(Strickout,1) Index(Sup_b,1)
c .   :              :                   :                :
c Any(First) '=' U+F046 > Context(1) Index(Strickout,1) Index(Sup_z,1)
NB the Store(First) really is only one character because Index() needs to match with an Any().
(First) is the context that I cannot find in the Collapse group.

   Bellow is a list of Stores used in the code above.

c Builds the 'A' menu as it is to be displayed.
Store(a_Menu) $LeftMenu U+202F U+F001 $Opn1 U+00A0 U+F002 $Opn2 U+00A0 U+F003 $Opn3 U+202F $RightMenu

c Output glyphs for 'a' type graphemes.
Store(a_Char) U+F001 U+F002 U+F003

c The number of options on a menu.
Store(Choices3) '123'

c Subscript numbers used on the menu.
Store(Opn1) U+2081
Store(Opn2) U+2082
Store(Opn3) U+2083

c The glyph placed between each TPA grapheme.
Store(TPAglue) U+E010

c The glyphs for 'A' superscripts over Latin letters a-z & A-Z
Store(Sup_A-) U+F402 U+F402 U+F302 U+F402 U+F402 U+F102 U+F502 U+F502 U+F202 U+F102 U+F302 U+F202 U+F802 U+F502 U+F402 U+F402 U+F402 U+F202 U+F302 U+F302 U+F402 U+F302 U+F502 U+F302 U+F302 U+F302 U+F602 U+F602 U+F502 U+F702 U+F402 U+F402 U+F602 U+F702 U+F202 U+F202 U+F602 U+F402 U+F802 U+F702 U+F702 U+F502 U+F702 U+F602 U+F402 U+F402 U+F702 U+F602 U+F802 U+F502 U+F502 U+F502

c The glyphs for Stricking out Latin letters a-z & A-Z
Store(Strickout) U+E061 U+E062 U+E063 U+E064 U+E065 U+E066 U+E067 U+E068 U+E069 U+E06A U+E06B U+E06C U+E06D U+E06E U+E06F U+E070 U+E071 U+E072 U+E073 U+E074 U+E075 U+E076 U+E077 U+E078 U+E079 U+E07A U+E041 U+E042 U+E043 U+E044 U+E045 U+E046 U+E047 U+E048 U+E049 U+E04A U+E04B U+E04C U+E04D U+E04E U+E04F U+E050 U+E051 U+E052 U+E053 U+E054 U+E055 U+E056 U+E057 U+E058 U+E059 U+E05A

   All this works well up to the Collapse group It is the final resolution defined in the Collapse group that I am having trouble with. Indeed lines 220 to 280 of the complete keyboard definition cause a collapse to occur, but with the pressing [K_ENTER] key. This code would be deleted if the functionality outlined above can be achieved.

# RE: Applying a Rule twice   2016-02-22 20:21:07.797
Marc Durdin
Tavultesoft Staff
I've downloaded your keyboard and had a look - it's pretty impressive. I'm still not entirely sure what you are trying to achieve with the Collapse group that you haven't already achieved, though?

Is it more than this change below?

Any(LatinLetter) '=' U+F002 > Context(1) Index(Strickout,1) Index(Sup_A-,1)

# RE: Applying a Rule twice   2016-02-23 06:54:00.567
br Julian Griffin OSL
I am forever amazed at how I manage to miss the blatantly obvious.

   As soon as I saw suggestion, I knew it was exactly what I needed.

   I have been examining my thinking on this matter. I was thinking of a Group as if it were the same as a Function in other languages.

   By the time I was calling Group(Collapse) I knew exactly what the Context was, so I felt I needed to pass it to Group(Collapse) as parameters. But the Keyman Language does not work that way, it works on the Context of what has been 'Typed' / 'Is on screen', so does not need parameters forwarded to it.

   So once again, thank you for your help and patience. Hopefully this will give me a better grasp of the Keyman Language. A language that has very few commands, but these commands are very powerful and subtle.

Thank you.
God bless.
Julian Griffin
# RE: Applying a Rule twice   2016-02-24 08:08:35.363
Marc Durdin
Tavultesoft Staff
Great! Glad I was able to help :)