Labs/Ubiquity/Parser 2 API Conversion Tutorial: Difference between revisions

no edit summary
No edit summary
 
(16 intermediate revisions by 5 users not shown)
Line 2: Line 2:


Ubiquity 0.5 introduces an updated command API, reflecting the changes in [[Labs/Ubiquity/Parser_2|the parser]] as well as the new [[Labs/Ubiquity/Ubiquity_0.5_Making_Commands_Localizable|ability to localize (some) commands]]. This tutorial will walk you through some of the key changes you will need to make. If you are interested in writing a new Ubiquity command from scratch, please refer to the [[Labs/Ubiquity/Ubiquity_Source_Tip_Author_Tutorial|updated Command Authoring Tutorial]].
Ubiquity 0.5 introduces an updated command API, reflecting the changes in [[Labs/Ubiquity/Parser_2|the parser]] as well as the new [[Labs/Ubiquity/Ubiquity_0.5_Making_Commands_Localizable|ability to localize (some) commands]]. This tutorial will walk you through some of the key changes you will need to make. If you are interested in writing a new Ubiquity command from scratch, please refer to the [[Labs/Ubiquity/Ubiquity_Source_Tip_Author_Tutorial|updated Command Authoring Tutorial]].
== Screencast Tutorial for Parser 2 API Conversion ==
A screencast walkthrough showing how to convert a command to Parser 2 format for Ubiquity 0.5 is available [http://mitcho.com/blog/projects/converting-your-ubiquity-command-to-ubiquity-0-5/ here]. If this is your first time converting a command, it is recommended that you first watch the walkthrough, as it provides a clear step-by-step visual explanation of what needs to be changed.


== A note on (backwards) compatibility ==
== A note on (backwards) compatibility ==
Line 20: Line 24:


We strongly encourage that all community commands be rewritten in Parser 2 format to take advantage of new (and upcoming) features.
We strongly encourage that all community commands be rewritten in Parser 2 format to take advantage of new (and upcoming) features.
=== Supporting both Parser 1 and Parser 2 in Your Command Feed ===
There is a property added to the Command API that allows you to present different commands to clients running Parser 1 and Parser 2, called CmdUtils.parserVersion.  A command can provide different options to CmdUtils.CreateCommand() and behave differently depending on this value, allowing a single command feed to cater to whatever parser the user is using.
  if (CmdUtils.parserVersion == 2) {
    //parser 2 command here
  } else {
    //parser 1 command here
  }


== Converting your command ==
== Converting your command ==


=== <code>names</code> ===
=== <code>names</code> ===
Where Parser 1 expected a single default verb name in the property <code>name</code> and possible synonyms in an optional <code>synonyms</code> property, Parser 2 requires that there be a single <code>names</code> property with an array of possible verb names.
'''Parser 1 (old) API:'''
  CmdUtils.CreateCommand({
    name: 'find',
    synonyms: ['look-for', 'search'],
    ...
'''Parser 2 (new) API:'''
  CmdUtils.CreateCommand({
    names: ['find', 'look for', 'search'],
    ...
Note also that command names may now include spaces. (Hurray!)


=== Specifying semantic roles ===
=== Specifying semantic roles ===
The biggest change in the Parser 2 API is that arguments are now specified using abstract ''semantic roles'' instead of language-specific markers. (See [[Labs/Ubiquity/Parser_2/Semantic_Roles|Semantic roles in Parser 2]] for further explanation of semantic roles and the rationale for this change.) Arguments which previously were specified in <code>takes</code>, direct objects, use the role "object". Arguments which were specified in <code>modifiers</code> are specified using different semantic roles, based on the grammatical function of the argument, instead of by its English preposition. For example, an argument introduced by "to" would now be marked with the role <code>goal</code>, and an argument introduced by "using" would be encoded as <code>instrument</code>. These arguments are then all specified together with their nountypes in an array as property <code>arguments</code>.
'''Parser 1 (old) API:'''
  CmdUtils.CreateCommand({
    ...
    takes: {query: noun_arb_text}
    modifiers: {'using': noun_type_searchengine}
    ...
'''Parser 2 (new) API:'''
  CmdUtils.CreateCommand({
    ...
    arguments: [ {role: 'object', nountype: noun_arb_text, label: 'query'},
                {role: 'instrument', nountype: noun_type_searchengine} ],
    ...
Please refer to [[Labs/Ubiquity/Parser_2/Semantic_Roles|Semantic roles in Parser 2]] for a list of supported semantic roles with examples of their use. Note that the <code>label</code> parameter (used in specifying the <code>object</code> argument above) is optional.
In addition, the old-style (but rare) <code>DOType</code> and <code>DOLabel</code> specifications are also no longer supported.


=== Using semantic roles in <code>preview</code> and <code>execute</code> ===
=== Using semantic roles in <code>preview</code> and <code>execute</code> ===
As arguments are specified using semantic roles, arguments are then passed to the <code>preview</code> and <code>execute</code> methods based on their arguments as well. Both methods are handed an object with the semantic roles as the keys, and the argument data as the values, e.g.
  { object:    { text: 'chicken',
                  data: 'chicken',
                  ... },
    instrument: { text: 'goo',
                  data: 'Google',
                  ... }
  }
Note that the structure of the argument data itself (with requisite properties <code>text</code>, <code>data</code>, and <code>html</code>) is the same as with the Parser 1 API.
Instead of handing the direct object's data and the other arguments' data separately to <code>preview</code> and <code>execute</code>, Parser 2 hands it to them together as one argument:
'''Parser 1 (old) API:'''
  CmdUtils.CreateCommand({
    ...
    preview: function(pblock, object, modifiers) {
      var data = {};
      data.query = object.text;
      data.engine = modifiers.using.text;
      pblock.innerHTML = CmdUtils.renderTemplate(
                          "Searching for ${query} using ${engine}.",
                          data );
    },
    execute: function(object, modifiers) {
      var data = {};
      data.query = object.text;
      data.engine = modifiers.using.text;
      displayMessage(CmdUtils.renderTemplate(
                      "Searching for ${query} using ${engine}.",
                      data );
    },
    ...
'''Parser 2 (new) API:'''
  CmdUtils.CreateCommand({
    ...
    preview: function(pblock, args) {
      var data = {};
      data.query = args.object.text;
      data.engine = args.instrument.text;
      pblock.innerHTML = CmdUtils.renderTemplate(
                          "Searching for ${query} using ${engine}.",
                          data );
    },
    execute: function(args) {
      var data = {};
      data.query = args.object.text;
      data.engine = args.instrument.text;
      displayMessage(CmdUtils.renderTemplate(
                      "Searching for ${query} using ${engine}.",
                      data );
    },
    ...
As always, it is best to first check whether the requisite arguments were filled in the parser before using it.


=== Making your command localizable ===
=== Making your command localizable ===
52

edits