From 5ea65fe246e4859c941487eb3d7bfe92696d4098 Mon Sep 17 00:00:00 2001 From: Peter Xiao Date: Tue, 13 Aug 2013 16:51:12 -0700 Subject: [PATCH] Add in expansion rules to speak more like how code is read. --- lib/ace/ext/chromevox.js | 99 +++++++++++++++++++++++++++++----------- 1 file changed, 73 insertions(+), 26 deletions(-) diff --git a/lib/ace/ext/chromevox.js b/lib/ace/ext/chromevox.js index e51800a4..8c8656ef 100644 --- a/lib/ace/ext/chromevox.js +++ b/lib/ace/ext/chromevox.js @@ -123,6 +123,17 @@ var NO_MATCH_EARCON = 'INVALID_KEYPRESS'; var INSERT_MODE_STATE = 'insertMode'; var COMMAND_MODE_STATE = 'start'; +var REPLACE_LIST = [ + { + substr: ';', + newSubstr: ' semicolon ' + }, + { + substr: ':', + newSubstr: ' colon ' + } +]; + /** * Context menu commands. */ @@ -265,14 +276,59 @@ var isWord = function(cursor) { }; /** - * A mapping of syntax type to speech properties. + * A mapping of syntax type to speech properties / expanding rules. */ var rules = { - 'constant': CONSTANT_PROP, - 'entity': ENTITY_PROP, - 'keyword': KEYWORD_PROP, - 'storage': STORAGE_PROP, - 'variable': VARIABLE_PROP + 'constant': { + prop: CONSTANT_PROP + }, + 'entity': { + prop: ENTITY_PROP + }, + 'keyword': { + prop: KEYWORD_PROP + }, + 'storage': { + prop: STORAGE_PROP + }, + 'variable': { + prop: VARIABLE_PROP + }, + 'meta': { + prop: DEFAULT_PROP, + replace: [ + { + substr: '<', + newSubstr: ' tag start ' + }, + { + substr: '>', + newSubstr: ' tag end ' + } + ] + } +}; + +/** + * Default rule to be used. + */ +var DEFAULT_RULE = { + prop: DEFAULT_RULE +}; + +/** + * Expands substrings to how they are read based on the given rules. + * @param {string} value Text to be expanded. + * @param {Array.} replaceRules Rules to determine expansion. + * @return {string} New expanded value. + */ +var expand = function(value, replaceRules) { + var newValue = value; + for (var i = 0; i < replaceRules.length; i++) { + var replaceRule = replaceRules[i]; + newValue = newValue.replace(replaceRule.substr, replaceRule.newSubstr); + } + return newValue; }; /** @@ -307,7 +363,7 @@ var mergeLikeTokens = function(tokens) { for (var i = 1; i < tokens.length; i++) { var lastLikeToken = tokens[lastLikeIndex]; var currToken = tokens[i]; - if (getTokenProp(lastLikeToken) !== getTokenProp(currToken)) { + if (getTokenRule(lastLikeToken) !== getTokenRule(currToken)) { newTokens.push(mergeTokens(tokens, lastLikeIndex, i)); lastLikeIndex = i; } @@ -360,7 +416,7 @@ var speakTokenQueue = function(token) { * @param {!cvoxAce.Token} token Token to speak. * Get the token speech property. */ -var getTokenProp = function(token) { +var getTokenRule = function(token) { /* Types are period delimited. In this case, we only syntax speak the outer * most type of token. */ if (!token || !token.type) { @@ -371,11 +427,11 @@ var getTokenProp = function(token) { return; } var type = split[0]; - var prop = rules[type]; - if (!prop) { - prop = DEFAULT_PROP; + var rule = rules[type]; + if (!rule) { + return DEFAULT_RULE; } - return prop; + return rule; }; /** @@ -385,21 +441,12 @@ var getTokenProp = function(token) { * @param {number} queue Queue mode. */ var speakToken_ = function(token, queue) { - /* Types are period delimited. In this case, we only syntax speak the outer - * most type of token. */ - if (!token || !token.type) { - return; + var rule = getTokenRule(token); + var value = expand(token.value, REPLACE_LIST); + if (rule.replace) { + value = expand(value, rule.replace); } - var split = token.type.split('.'); - if (split.length === 0) { - return; - } - var type = split[0]; - var prop = rules[type]; - if (!prop) { - prop = DEFAULT_PROP; - } - cvox.Api.speak(token.value, queue, prop); + cvox.Api.speak(value, queue, rule.prop); }; /**