diff --git a/build/bundle.js b/build/bundle.js
index c75cb83d..3437416a 100644
--- a/build/bundle.js
+++ b/build/bundle.js
@@ -10996,7 +10996,7 @@ var Errors = require('../util/errors');
var GitCommands = require('../git/commands');
var GitOptionParser = GitCommands.GitOptionParser;
-var sandboxInstantCommands = require('../level/sandboxCommands').sandboxInstantCommands;
+var ParseWaterfall = require('../level/parseWaterfall').ParseWaterfall;
var CommandProcessError = Errors.CommandProcessError;
var GitError = Errors.GitError;
@@ -11008,38 +11008,47 @@ var Command = Backbone.Model.extend({
status: 'inqueue',
rawStr: null,
result: '',
+ createTime: null,
error: null,
warnings: null,
+ parseWaterfall: new ParseWaterfall(),
generalArgs: null,
supportedMap: null,
options: null,
- method: null,
+ method: null
- createTime: null
},
- validateAtInit: function() {
- // weird things happen with defaults if you dont
- // make new objects
- this.set('generalArgs', []);
- this.set('supportedMap', {});
- this.set('warnings', []);
-
- if (this.get('rawStr') === null) {
- throw new Error('Give me a string!');
- }
- if (!this.get('createTime')) {
- this.set('createTime', new Date().toString());
- }
-
+ initialize: function(options) {
+ this.initDefaults();
+ this.validateAtInit();
this.on('change:error', this.errorChanged, this);
// catch errors on init
if (this.get('error')) {
this.errorChanged();
}
+
+ this.parseOrCatch();
+ },
+
+ initDefaults: function() {
+ // weird things happen with defaults if you dont
+ // make new objects
+ this.set('generalArgs', []);
+ this.set('supportedMap', {});
+ this.set('warnings', []);
+ },
+
+ validateAtInit: function() {
+ if (this.get('rawStr') === null) {
+ throw new Error('Give me a string!');
+ }
+ if (!this.get('createTime')) {
+ this.set('createTime', new Date().toString());
+ }
},
setResult: function(msg) {
@@ -11061,19 +11070,26 @@ var Command = Backbone.Model.extend({
return '
' + i + this.get('warnings').join('
' + i) + '
';
},
- initialize: function() {
- this.validateAtInit();
- this.parseOrCatch();
- },
-
parseOrCatch: function() {
+ this.expandShortcuts(this.get('rawStr'));
try {
- this.parse();
+ this.processInstants();
} catch (err) {
Errors.filterError(err);
// errorChanged() will handle status and all of that
this.set('error', err);
}
+
+ if (this.parseAll()) {
+ // something in our parse waterfall succeeded
+ return;
+ }
+
+ // if we reach here, this command is not supported :-/
+ this.set('error', new CommandProcessError({
+ msg: 'The command "' + this.get('rawStr') + '" isn\'t supported, sorry!'
+ })
+ );
},
errorChanged: function() {
@@ -11093,65 +11109,35 @@ var Command = Backbone.Model.extend({
this.set('result', this.get('error').toResult());
},
- parse: function() {
+ expandShortcuts: function(str) {
+ str = this.get('parseWaterfall').expandAllShortcuts(str);
+ this.set('rawStr', str);
+ },
+
+ processInstants: function() {
var str = this.get('rawStr');
// first if the string is empty, they just want a blank line
if (!str.length) {
throw new CommandResult({msg: ""});
}
- str = GitCommands.expandShortcut(str);
- this.set('rawStr', str);
-
- // then check if it's one of our sandbox commands
- _.each(sandboxInstantCommands, function(tuple) {
- var regex = tuple[0];
- var results = regex.exec(str);
- if (results) {
- // this will throw a result
- tuple[1](results);
- }
- });
-
- // see if begins with git
- if (str.slice(0,3) !== 'git') {
- throw new CommandProcessError({
- msg: 'That command is not supported, sorry!'
- });
- }
-
- // ok, we have a (probably) valid command. actually parse it
- this.gitParse(str);
+ // then instant commands that will throw
+ this.get('parseWaterfall').processAllInstants(str);
},
- gitParse: function(str) {
- // now slice off command part
- var fullCommand = str.slice('git '.length);
+ parseAll: function() {
+ var str = this.get('rawStr');
+ var results = this.get('parseWaterfall').parseAll(str);
- // see if we support this particular command
- _.each(GitCommands.getRegexMap(), function(regex, method) {
- if (regex.exec(fullCommand)) {
- this.set('options', fullCommand.slice(method.length + 1));
- this.set('method', method);
- // we should stop iterating, but the regex will only match
- // one command in practice. we could stop iterating if we used
- // jqeurys for each but im using underscore (for no real reason other
- // than style)
- }
- }, this);
-
- if (!this.get('method')) {
- throw new CommandProcessError({
- msg: "Sorry, this demo does not support that git command: " + fullCommand
- });
+ if (!results) {
+ // nothing parsed successfully
+ return false;
}
- // parse off the options and assemble the map / general args
- var options = new GitOptionParser(this.get('method'), this.get('options'));
-
- // steal these away so we can be completely JSON
- this.set('generalArgs', options.generalArgs);
- this.set('supportedMap', options.supportedMap);
+ _.each(results.toSet, function(obj, key) {
+ this.set(key, obj);
+ }, this);
+ return true;
}
});
@@ -11177,44 +11163,92 @@ var GitError = Errors.GitError;
var Warning = Errors.Warning;
var CommandResult = Errors.CommandResult;
-var getRegexMap = function() {
- return {
- // ($|\s) means that we either have to end the string
- // after the command or there needs to be a space for options
- commit: /^commit($|\s)/,
- add: /^add($|\s)/,
- checkout: /^checkout($|\s)/,
- rebase: /^rebase($|\s)/,
- reset: /^reset($|\s)/,
- branch: /^branch($|\s)/,
- revert: /^revert($|\s)/,
- log: /^log($|\s)/,
- merge: /^merge($|\s)/,
- show: /^show($|\s)/,
- status: /^status($|\s)/,
- 'cherry-pick': /^cherry-pick($|\s)/
- };
+var shortcutMap = {
+ 'git commit': /^gc($|\s)/,
+ 'git add': /^ga($|\s)/,
+ 'git checkout': /^go($|\s)/,
+ 'git rebase': /^gr($|\s)/,
+ 'git branch': /^gb($|\s)/,
+ 'git status': /^gs($|\s)/,
+ 'git help': /^git$/
};
-var getShortcutMap = function() {
- return {
- 'git commit': /^gc($|\s)/,
- 'git add': /^ga($|\s)/,
- 'git checkout': /^go($|\s)/,
- 'git rebase': /^gr($|\s)/,
- 'git branch': /^gb($|\s)/,
- 'git status': /^gs($|\s)/
- };
+var instantCommands = [
+ [/^git help($|\s)/, function() {
+ var lines = [
+ 'Git Version PCOTTLE.1.0',
+ '
',
+ 'Usage:',
+ _.escape('\t git []'),
+ '
',
+ 'Supported commands:',
+ '
'
+ ];
+ var commands = GitOptionParser.prototype.getMasterOptionMap();
+
+ // build up a nice display of what we support
+ _.each(commands, function(commandOptions, command) {
+ lines.push('git ' + command);
+ _.each(commandOptions, function(vals, optionName) {
+ lines.push('\t ' + optionName);
+ }, this);
+ }, this);
+
+ // format and throw
+ var msg = lines.join('\n');
+ msg = msg.replace(/\t/g, ' ');
+ throw new CommandResult({
+ msg: msg
+ });
+ }]
+];
+
+var regexMap = {
+ // ($|\s) means that we either have to end the string
+ // after the command or there needs to be a space for options
+ commit: /^commit($|\s)/,
+ add: /^add($|\s)/,
+ checkout: /^checkout($|\s)/,
+ rebase: /^rebase($|\s)/,
+ reset: /^reset($|\s)/,
+ branch: /^branch($|\s)/,
+ revert: /^revert($|\s)/,
+ log: /^log($|\s)/,
+ merge: /^merge($|\s)/,
+ show: /^show($|\s)/,
+ status: /^status($|\s)/,
+ 'cherry-pick': /^cherry-pick($|\s)/
};
-var expandShortcut = function(commandStr) {
- _.each(getShortcutMap(), function(regex, method) {
- var results = regex.exec(commandStr);
- if (results) {
- commandStr = method + ' ' + commandStr.slice(results[0].length);
+var parse = function(str) {
+ // now slice off command part
+ var fullCommand = str.slice('git '.length);
+ var method;
+ var options;
+
+ // see if we support this particular command
+ _.each(regexMap, function(regex, thisMethod) {
+ if (regex.exec(fullCommand)) {
+ options = fullCommand.slice(thisMethod.length + 1);
+ method = thisMethod;
}
- });
- return commandStr;
+ }, this);
+
+ if (!method) {
+ return false;
+ }
+
+ // we support this command!
+ // parse off the options and assemble the map / general args
+ var parsedOptions = new GitOptionParser(method, options);
+ return {
+ toSet: {
+ generalArgs: parsedOptions.generalArgs,
+ supportedMap: parsedOptions.supportedMap,
+ method: method,
+ options: options
+ }
+ };
};
/**
@@ -11305,13 +11339,85 @@ GitOptionParser.prototype.explodeAndSet = function() {
}
};
-exports.getRegexMap = getRegexMap;
-exports.expandShortcut = expandShortcut;
-exports.GitOptionParser = GitOptionParser;
+exports.shortcutMap = shortcutMap;
+exports.instantCommands = instantCommands;
+exports.parse = parse;
+exports.regexMap = regexMap;
});
-require.define("/src/js/level/sandboxCommands.js",function(require,module,exports,__dirname,__filename,process,global){var _ = require('underscore');
+require.define("/src/js/level/parseWaterfall.js",function(require,module,exports,__dirname,__filename,process,global){var _ = require('underscore');
+
+var GitCommands = require('../git/commands');
+var SandboxCommands = require('../level/SandboxCommands');
+
+// more or less a static class
+function ParseWaterfall(options) {
+ this.shortcutWaterfall = [
+ GitCommands.shortcutMap
+ ];
+
+ this.instantWaterfall = [
+ GitCommands.instantCommands,
+ SandboxCommands.instantCommands
+ ];
+
+ this.parseWaterfall = [
+ GitCommands.parse
+ ];
+}
+
+ParseWaterfall.prototype.expandAllShortcuts = function(commandStr) {
+ _.each(this.shortcutWaterfall, function(shortcutMap) {
+ commandStr = this.expandShortcut(commandStr, shortcutMap);
+ }, this);
+ return commandStr;
+};
+
+ParseWaterfall.prototype.expandShortcut = function(commandStr, shortcutMap) {
+ _.each(shortcutMap, function(regex, method) {
+ var results = regex.exec(commandStr);
+ if (results) {
+ commandStr = method + ' ' + commandStr.slice(results[0].length);
+ }
+ });
+ return commandStr;
+};
+
+ParseWaterfall.prototype.processAllInstants = function(commandStr) {
+ _.each(this.instantWaterfall, function(instantCommands) {
+ this.processInstant(commandStr, instantCommands);
+ }, this);
+};
+
+ParseWaterfall.prototype.processInstant = function(commandStr, instantCommands) {
+ _.each(instantCommands, function(tuple) {
+ var regex = tuple[0];
+ var results = regex.exec(commandStr);
+ if (results) {
+ // this will throw a result
+ tuple[1](results);
+ }
+ });
+};
+
+ParseWaterfall.prototype.parseAll = function(commandStr) {
+ var toReturn = false;
+ _.each(this.parseWaterfall, function(parseFunc) {
+ var results = parseFunc(commandStr);
+ if (results) {
+ toReturn = results;
+ }
+ }, this);
+
+ return toReturn;
+};
+
+exports.ParseWaterfall = ParseWaterfall;
+
+});
+
+require.define("/src/js/level/SandboxCommands.js",function(require,module,exports,__dirname,__filename,process,global){var _ = require('underscore');
var GitCommands = require('../git/commands');
var GitOptionParser = GitCommands.GitOptionParser;
@@ -11322,7 +11428,7 @@ var GitError = Errors.GitError;
var Warning = Errors.Warning;
var CommandResult = Errors.CommandResult;
-var sandboxInstantCommands = [
+var instantCommands = [
[/^ls/, function() {
throw new CommandResult({
msg: "DontWorryAboutFilesInThisDemo.txt"
@@ -11333,45 +11439,6 @@ var sandboxInstantCommands = [
msg: "Directory Changed to '/directories/dont/matter/in/this/demo'"
});
}],
- [/^git help($|\s)/, function() {
- // sym link this to the blank git command
- var allCommands = Command.prototype.getSandboxCommands();
- // wow this is hacky :(
- var equivalent = 'git';
- _.each(allCommands, function(bits) {
- var regex = bits[0];
- if (regex.test(equivalent)) {
- bits[1]();
- }
- });
- }],
- [/^git$/, function() {
- var lines = [
- 'Git Version PCOTTLE.1.0',
- '
',
- 'Usage:',
- _.escape('\t git []'),
- '
',
- 'Supported commands:',
- '
'
- ];
- var commands = GitOptionParser.prototype.getMasterOptionMap();
-
- // build up a nice display of what we support
- _.each(commands, function(commandOptions, command) {
- lines.push('git ' + command);
- _.each(commandOptions, function(vals, optionName) {
- lines.push('\t ' + optionName);
- }, this);
- }, this);
-
- // format and throw
- var msg = lines.join('\n');
- msg = msg.replace(/\t/g, ' ');
- throw new CommandResult({
- msg: msg
- });
- }],
[/^refresh$/, function() {
var events = require('../app').getEvents();
@@ -11391,7 +11458,7 @@ var sandboxInstantCommands = [
}]
];
-exports.sandboxInstantCommands = sandboxInstantCommands;
+exports.instantCommands = instantCommands;
});
@@ -13776,7 +13843,6 @@ exports.VisEdge = VisEdge;
});
require.define("/src/js/level/inputWaterfall.js",function(require,module,exports,__dirname,__filename,process,global){var _ = require('underscore');
-var Backbone = require('backbone');
var Main = require('../app');
var GitCommands = require('../git/commands');
@@ -13832,6 +13898,7 @@ InputWaterfall.prototype.checkDisabledMap = function(command) {
try {
this.loopDisabledMap(command);
} catch(err) {
+ Errors.filterError(err);
command.set('error', err);
return true;
}
@@ -13841,7 +13908,7 @@ InputWaterfall.prototype.checkDisabledMap = function(command) {
InputWaterfall.prototype.loopDisabledMap = function(command) {
var toTest = this.sliceGitOff(command.get('rawStr'));
- var regexMap = GitCommands.getRegexMap();
+ var regexMap = GitCommands.regexMap;
_.each(this.disabledMap, function(val, disabledGitCommand) {
disabledGitCommand = this.sliceGitOff(disabledGitCommand);
@@ -14201,44 +14268,92 @@ var GitError = Errors.GitError;
var Warning = Errors.Warning;
var CommandResult = Errors.CommandResult;
-var getRegexMap = function() {
- return {
- // ($|\s) means that we either have to end the string
- // after the command or there needs to be a space for options
- commit: /^commit($|\s)/,
- add: /^add($|\s)/,
- checkout: /^checkout($|\s)/,
- rebase: /^rebase($|\s)/,
- reset: /^reset($|\s)/,
- branch: /^branch($|\s)/,
- revert: /^revert($|\s)/,
- log: /^log($|\s)/,
- merge: /^merge($|\s)/,
- show: /^show($|\s)/,
- status: /^status($|\s)/,
- 'cherry-pick': /^cherry-pick($|\s)/
- };
+var shortcutMap = {
+ 'git commit': /^gc($|\s)/,
+ 'git add': /^ga($|\s)/,
+ 'git checkout': /^go($|\s)/,
+ 'git rebase': /^gr($|\s)/,
+ 'git branch': /^gb($|\s)/,
+ 'git status': /^gs($|\s)/,
+ 'git help': /^git$/
};
-var getShortcutMap = function() {
- return {
- 'git commit': /^gc($|\s)/,
- 'git add': /^ga($|\s)/,
- 'git checkout': /^go($|\s)/,
- 'git rebase': /^gr($|\s)/,
- 'git branch': /^gb($|\s)/,
- 'git status': /^gs($|\s)/
- };
+var instantCommands = [
+ [/^git help($|\s)/, function() {
+ var lines = [
+ 'Git Version PCOTTLE.1.0',
+ '
',
+ 'Usage:',
+ _.escape('\t git []'),
+ '
',
+ 'Supported commands:',
+ '
'
+ ];
+ var commands = GitOptionParser.prototype.getMasterOptionMap();
+
+ // build up a nice display of what we support
+ _.each(commands, function(commandOptions, command) {
+ lines.push('git ' + command);
+ _.each(commandOptions, function(vals, optionName) {
+ lines.push('\t ' + optionName);
+ }, this);
+ }, this);
+
+ // format and throw
+ var msg = lines.join('\n');
+ msg = msg.replace(/\t/g, ' ');
+ throw new CommandResult({
+ msg: msg
+ });
+ }]
+];
+
+var regexMap = {
+ // ($|\s) means that we either have to end the string
+ // after the command or there needs to be a space for options
+ commit: /^commit($|\s)/,
+ add: /^add($|\s)/,
+ checkout: /^checkout($|\s)/,
+ rebase: /^rebase($|\s)/,
+ reset: /^reset($|\s)/,
+ branch: /^branch($|\s)/,
+ revert: /^revert($|\s)/,
+ log: /^log($|\s)/,
+ merge: /^merge($|\s)/,
+ show: /^show($|\s)/,
+ status: /^status($|\s)/,
+ 'cherry-pick': /^cherry-pick($|\s)/
};
-var expandShortcut = function(commandStr) {
- _.each(getShortcutMap(), function(regex, method) {
- var results = regex.exec(commandStr);
- if (results) {
- commandStr = method + ' ' + commandStr.slice(results[0].length);
+var parse = function(str) {
+ // now slice off command part
+ var fullCommand = str.slice('git '.length);
+ var method;
+ var options;
+
+ // see if we support this particular command
+ _.each(regexMap, function(regex, thisMethod) {
+ if (regex.exec(fullCommand)) {
+ options = fullCommand.slice(thisMethod.length + 1);
+ method = thisMethod;
}
- });
- return commandStr;
+ }, this);
+
+ if (!method) {
+ return false;
+ }
+
+ // we support this command!
+ // parse off the options and assemble the map / general args
+ var parsedOptions = new GitOptionParser(method, options);
+ return {
+ toSet: {
+ generalArgs: parsedOptions.generalArgs,
+ supportedMap: parsedOptions.supportedMap,
+ method: method,
+ options: options
+ }
+ };
};
/**
@@ -14329,9 +14444,10 @@ GitOptionParser.prototype.explodeAndSet = function() {
}
};
-exports.getRegexMap = getRegexMap;
-exports.expandShortcut = expandShortcut;
-exports.GitOptionParser = GitOptionParser;
+exports.shortcutMap = shortcutMap;
+exports.instantCommands = instantCommands;
+exports.parse = parse;
+exports.regexMap = regexMap;
});
require("/src/js/git/commands.js");
@@ -16194,7 +16310,6 @@ exports.TreeCompare = TreeCompare;
require("/src/js/git/treeCompare.js");
require.define("/src/js/level/inputWaterfall.js",function(require,module,exports,__dirname,__filename,process,global){var _ = require('underscore');
-var Backbone = require('backbone');
var Main = require('../app');
var GitCommands = require('../git/commands');
@@ -16250,6 +16365,7 @@ InputWaterfall.prototype.checkDisabledMap = function(command) {
try {
this.loopDisabledMap(command);
} catch(err) {
+ Errors.filterError(err);
command.set('error', err);
return true;
}
@@ -16259,7 +16375,7 @@ InputWaterfall.prototype.checkDisabledMap = function(command) {
InputWaterfall.prototype.loopDisabledMap = function(command) {
var toTest = this.sliceGitOff(command.get('rawStr'));
- var regexMap = GitCommands.getRegexMap();
+ var regexMap = GitCommands.regexMap;
_.each(this.disabledMap, function(val, disabledGitCommand) {
disabledGitCommand = this.sliceGitOff(disabledGitCommand);
@@ -16284,6 +16400,78 @@ exports.InputWaterfall = InputWaterfall;
});
require("/src/js/level/inputWaterfall.js");
+require.define("/src/js/level/parseWaterfall.js",function(require,module,exports,__dirname,__filename,process,global){var _ = require('underscore');
+
+var GitCommands = require('../git/commands');
+var SandboxCommands = require('../level/SandboxCommands');
+
+// more or less a static class
+function ParseWaterfall(options) {
+ this.shortcutWaterfall = [
+ GitCommands.shortcutMap
+ ];
+
+ this.instantWaterfall = [
+ GitCommands.instantCommands,
+ SandboxCommands.instantCommands
+ ];
+
+ this.parseWaterfall = [
+ GitCommands.parse
+ ];
+}
+
+ParseWaterfall.prototype.expandAllShortcuts = function(commandStr) {
+ _.each(this.shortcutWaterfall, function(shortcutMap) {
+ commandStr = this.expandShortcut(commandStr, shortcutMap);
+ }, this);
+ return commandStr;
+};
+
+ParseWaterfall.prototype.expandShortcut = function(commandStr, shortcutMap) {
+ _.each(shortcutMap, function(regex, method) {
+ var results = regex.exec(commandStr);
+ if (results) {
+ commandStr = method + ' ' + commandStr.slice(results[0].length);
+ }
+ });
+ return commandStr;
+};
+
+ParseWaterfall.prototype.processAllInstants = function(commandStr) {
+ _.each(this.instantWaterfall, function(instantCommands) {
+ this.processInstant(commandStr, instantCommands);
+ }, this);
+};
+
+ParseWaterfall.prototype.processInstant = function(commandStr, instantCommands) {
+ _.each(instantCommands, function(tuple) {
+ var regex = tuple[0];
+ var results = regex.exec(commandStr);
+ if (results) {
+ // this will throw a result
+ tuple[1](results);
+ }
+ });
+};
+
+ParseWaterfall.prototype.parseAll = function(commandStr) {
+ var toReturn = false;
+ _.each(this.parseWaterfall, function(parseFunc) {
+ var results = parseFunc(commandStr);
+ if (results) {
+ toReturn = results;
+ }
+ }, this);
+
+ return toReturn;
+};
+
+exports.ParseWaterfall = ParseWaterfall;
+
+});
+require("/src/js/level/parseWaterfall.js");
+
require.define("/src/js/level/sandboxCommands.js",function(require,module,exports,__dirname,__filename,process,global){var _ = require('underscore');
var GitCommands = require('../git/commands');
@@ -16295,7 +16483,7 @@ var GitError = Errors.GitError;
var Warning = Errors.Warning;
var CommandResult = Errors.CommandResult;
-var sandboxInstantCommands = [
+var instantCommands = [
[/^ls/, function() {
throw new CommandResult({
msg: "DontWorryAboutFilesInThisDemo.txt"
@@ -16306,45 +16494,6 @@ var sandboxInstantCommands = [
msg: "Directory Changed to '/directories/dont/matter/in/this/demo'"
});
}],
- [/^git help($|\s)/, function() {
- // sym link this to the blank git command
- var allCommands = Command.prototype.getSandboxCommands();
- // wow this is hacky :(
- var equivalent = 'git';
- _.each(allCommands, function(bits) {
- var regex = bits[0];
- if (regex.test(equivalent)) {
- bits[1]();
- }
- });
- }],
- [/^git$/, function() {
- var lines = [
- 'Git Version PCOTTLE.1.0',
- '
',
- 'Usage:',
- _.escape('\t git []'),
- '
',
- 'Supported commands:',
- '
'
- ];
- var commands = GitOptionParser.prototype.getMasterOptionMap();
-
- // build up a nice display of what we support
- _.each(commands, function(commandOptions, command) {
- lines.push('git ' + command);
- _.each(commandOptions, function(vals, optionName) {
- lines.push('\t ' + optionName);
- }, this);
- }, this);
-
- // format and throw
- var msg = lines.join('\n');
- msg = msg.replace(/\t/g, ' ');
- throw new CommandResult({
- msg: msg
- });
- }],
[/^refresh$/, function() {
var events = require('../app').getEvents();
@@ -16364,7 +16513,7 @@ var sandboxInstantCommands = [
}]
];
-exports.sandboxInstantCommands = sandboxInstantCommands;
+exports.instantCommands = instantCommands;
});
require("/src/js/level/sandboxCommands.js");
@@ -16486,7 +16635,7 @@ var Errors = require('../util/errors');
var GitCommands = require('../git/commands');
var GitOptionParser = GitCommands.GitOptionParser;
-var sandboxInstantCommands = require('../level/sandboxCommands').sandboxInstantCommands;
+var ParseWaterfall = require('../level/parseWaterfall').ParseWaterfall;
var CommandProcessError = Errors.CommandProcessError;
var GitError = Errors.GitError;
@@ -16498,38 +16647,47 @@ var Command = Backbone.Model.extend({
status: 'inqueue',
rawStr: null,
result: '',
+ createTime: null,
error: null,
warnings: null,
+ parseWaterfall: new ParseWaterfall(),
generalArgs: null,
supportedMap: null,
options: null,
- method: null,
+ method: null
- createTime: null
},
- validateAtInit: function() {
- // weird things happen with defaults if you dont
- // make new objects
- this.set('generalArgs', []);
- this.set('supportedMap', {});
- this.set('warnings', []);
-
- if (this.get('rawStr') === null) {
- throw new Error('Give me a string!');
- }
- if (!this.get('createTime')) {
- this.set('createTime', new Date().toString());
- }
-
+ initialize: function(options) {
+ this.initDefaults();
+ this.validateAtInit();
this.on('change:error', this.errorChanged, this);
// catch errors on init
if (this.get('error')) {
this.errorChanged();
}
+
+ this.parseOrCatch();
+ },
+
+ initDefaults: function() {
+ // weird things happen with defaults if you dont
+ // make new objects
+ this.set('generalArgs', []);
+ this.set('supportedMap', {});
+ this.set('warnings', []);
+ },
+
+ validateAtInit: function() {
+ if (this.get('rawStr') === null) {
+ throw new Error('Give me a string!');
+ }
+ if (!this.get('createTime')) {
+ this.set('createTime', new Date().toString());
+ }
},
setResult: function(msg) {
@@ -16551,19 +16709,26 @@ var Command = Backbone.Model.extend({
return '' + i + this.get('warnings').join('
' + i) + '
';
},
- initialize: function() {
- this.validateAtInit();
- this.parseOrCatch();
- },
-
parseOrCatch: function() {
+ this.expandShortcuts(this.get('rawStr'));
try {
- this.parse();
+ this.processInstants();
} catch (err) {
Errors.filterError(err);
// errorChanged() will handle status and all of that
this.set('error', err);
}
+
+ if (this.parseAll()) {
+ // something in our parse waterfall succeeded
+ return;
+ }
+
+ // if we reach here, this command is not supported :-/
+ this.set('error', new CommandProcessError({
+ msg: 'The command "' + this.get('rawStr') + '" isn\'t supported, sorry!'
+ })
+ );
},
errorChanged: function() {
@@ -16583,65 +16748,35 @@ var Command = Backbone.Model.extend({
this.set('result', this.get('error').toResult());
},
- parse: function() {
+ expandShortcuts: function(str) {
+ str = this.get('parseWaterfall').expandAllShortcuts(str);
+ this.set('rawStr', str);
+ },
+
+ processInstants: function() {
var str = this.get('rawStr');
// first if the string is empty, they just want a blank line
if (!str.length) {
throw new CommandResult({msg: ""});
}
- str = GitCommands.expandShortcut(str);
- this.set('rawStr', str);
-
- // then check if it's one of our sandbox commands
- _.each(sandboxInstantCommands, function(tuple) {
- var regex = tuple[0];
- var results = regex.exec(str);
- if (results) {
- // this will throw a result
- tuple[1](results);
- }
- });
-
- // see if begins with git
- if (str.slice(0,3) !== 'git') {
- throw new CommandProcessError({
- msg: 'That command is not supported, sorry!'
- });
- }
-
- // ok, we have a (probably) valid command. actually parse it
- this.gitParse(str);
+ // then instant commands that will throw
+ this.get('parseWaterfall').processAllInstants(str);
},
- gitParse: function(str) {
- // now slice off command part
- var fullCommand = str.slice('git '.length);
+ parseAll: function() {
+ var str = this.get('rawStr');
+ var results = this.get('parseWaterfall').parseAll(str);
- // see if we support this particular command
- _.each(GitCommands.getRegexMap(), function(regex, method) {
- if (regex.exec(fullCommand)) {
- this.set('options', fullCommand.slice(method.length + 1));
- this.set('method', method);
- // we should stop iterating, but the regex will only match
- // one command in practice. we could stop iterating if we used
- // jqeurys for each but im using underscore (for no real reason other
- // than style)
- }
- }, this);
-
- if (!this.get('method')) {
- throw new CommandProcessError({
- msg: "Sorry, this demo does not support that git command: " + fullCommand
- });
+ if (!results) {
+ // nothing parsed successfully
+ return false;
}
- // parse off the options and assemble the map / general args
- var options = new GitOptionParser(this.get('method'), this.get('options'));
-
- // steal these away so we can be completely JSON
- this.set('generalArgs', options.generalArgs);
- this.set('supportedMap', options.supportedMap);
+ _.each(results.toSet, function(obj, key) {
+ this.set(key, obj);
+ }, this);
+ return true;
}
});
diff --git a/src/js/git/commands.js b/src/js/git/commands.js
index fad35869..28e95cca 100644
--- a/src/js/git/commands.js
+++ b/src/js/git/commands.js
@@ -6,44 +6,92 @@ var GitError = Errors.GitError;
var Warning = Errors.Warning;
var CommandResult = Errors.CommandResult;
-var getRegexMap = function() {
- return {
- // ($|\s) means that we either have to end the string
- // after the command or there needs to be a space for options
- commit: /^commit($|\s)/,
- add: /^add($|\s)/,
- checkout: /^checkout($|\s)/,
- rebase: /^rebase($|\s)/,
- reset: /^reset($|\s)/,
- branch: /^branch($|\s)/,
- revert: /^revert($|\s)/,
- log: /^log($|\s)/,
- merge: /^merge($|\s)/,
- show: /^show($|\s)/,
- status: /^status($|\s)/,
- 'cherry-pick': /^cherry-pick($|\s)/
- };
+var shortcutMap = {
+ 'git commit': /^gc($|\s)/,
+ 'git add': /^ga($|\s)/,
+ 'git checkout': /^go($|\s)/,
+ 'git rebase': /^gr($|\s)/,
+ 'git branch': /^gb($|\s)/,
+ 'git status': /^gs($|\s)/,
+ 'git help': /^git$/
};
-var getShortcutMap = function() {
- return {
- 'git commit': /^gc($|\s)/,
- 'git add': /^ga($|\s)/,
- 'git checkout': /^go($|\s)/,
- 'git rebase': /^gr($|\s)/,
- 'git branch': /^gb($|\s)/,
- 'git status': /^gs($|\s)/
- };
+var instantCommands = [
+ [/^git help($|\s)/, function() {
+ var lines = [
+ 'Git Version PCOTTLE.1.0',
+ '
',
+ 'Usage:',
+ _.escape('\t git []'),
+ '
',
+ 'Supported commands:',
+ '
'
+ ];
+ var commands = GitOptionParser.prototype.getMasterOptionMap();
+
+ // build up a nice display of what we support
+ _.each(commands, function(commandOptions, command) {
+ lines.push('git ' + command);
+ _.each(commandOptions, function(vals, optionName) {
+ lines.push('\t ' + optionName);
+ }, this);
+ }, this);
+
+ // format and throw
+ var msg = lines.join('\n');
+ msg = msg.replace(/\t/g, ' ');
+ throw new CommandResult({
+ msg: msg
+ });
+ }]
+];
+
+var regexMap = {
+ // ($|\s) means that we either have to end the string
+ // after the command or there needs to be a space for options
+ commit: /^commit($|\s)/,
+ add: /^add($|\s)/,
+ checkout: /^checkout($|\s)/,
+ rebase: /^rebase($|\s)/,
+ reset: /^reset($|\s)/,
+ branch: /^branch($|\s)/,
+ revert: /^revert($|\s)/,
+ log: /^log($|\s)/,
+ merge: /^merge($|\s)/,
+ show: /^show($|\s)/,
+ status: /^status($|\s)/,
+ 'cherry-pick': /^cherry-pick($|\s)/
};
-var expandShortcut = function(commandStr) {
- _.each(getShortcutMap(), function(regex, method) {
- var results = regex.exec(commandStr);
- if (results) {
- commandStr = method + ' ' + commandStr.slice(results[0].length);
+var parse = function(str) {
+ // now slice off command part
+ var fullCommand = str.slice('git '.length);
+ var method;
+ var options;
+
+ // see if we support this particular command
+ _.each(regexMap, function(regex, thisMethod) {
+ if (regex.exec(fullCommand)) {
+ options = fullCommand.slice(thisMethod.length + 1);
+ method = thisMethod;
}
- });
- return commandStr;
+ }, this);
+
+ if (!method) {
+ return false;
+ }
+
+ // we support this command!
+ // parse off the options and assemble the map / general args
+ var parsedOptions = new GitOptionParser(method, options);
+ return {
+ toSet: {
+ generalArgs: parsedOptions.generalArgs,
+ supportedMap: parsedOptions.supportedMap,
+ method: method,
+ options: options
+ }
+ };
};
/**
@@ -134,6 +182,7 @@ GitOptionParser.prototype.explodeAndSet = function() {
}
};
-exports.getRegexMap = getRegexMap;
-exports.expandShortcut = expandShortcut;
-exports.GitOptionParser = GitOptionParser;
+exports.shortcutMap = shortcutMap;
+exports.instantCommands = instantCommands;
+exports.parse = parse;
+exports.regexMap = regexMap;
diff --git a/src/js/level/inputWaterfall.js b/src/js/level/inputWaterfall.js
index 54d413f0..bdc732f3 100644
--- a/src/js/level/inputWaterfall.js
+++ b/src/js/level/inputWaterfall.js
@@ -1,5 +1,4 @@
var _ = require('underscore');
-var Backbone = require('backbone');
var Main = require('../app');
var GitCommands = require('../git/commands');
@@ -55,6 +54,7 @@ InputWaterfall.prototype.checkDisabledMap = function(command) {
try {
this.loopDisabledMap(command);
} catch(err) {
+ Errors.filterError(err);
command.set('error', err);
return true;
}
@@ -64,7 +64,7 @@ InputWaterfall.prototype.checkDisabledMap = function(command) {
InputWaterfall.prototype.loopDisabledMap = function(command) {
var toTest = this.sliceGitOff(command.get('rawStr'));
- var regexMap = GitCommands.getRegexMap();
+ var regexMap = GitCommands.regexMap;
_.each(this.disabledMap, function(val, disabledGitCommand) {
disabledGitCommand = this.sliceGitOff(disabledGitCommand);
diff --git a/src/js/level/parseWaterfall.js b/src/js/level/parseWaterfall.js
new file mode 100644
index 00000000..60c14d76
--- /dev/null
+++ b/src/js/level/parseWaterfall.js
@@ -0,0 +1,68 @@
+var _ = require('underscore');
+
+var GitCommands = require('../git/commands');
+var SandboxCommands = require('../level/SandboxCommands');
+
+// more or less a static class
+function ParseWaterfall(options) {
+ this.shortcutWaterfall = [
+ GitCommands.shortcutMap
+ ];
+
+ this.instantWaterfall = [
+ GitCommands.instantCommands,
+ SandboxCommands.instantCommands
+ ];
+
+ this.parseWaterfall = [
+ GitCommands.parse
+ ];
+}
+
+ParseWaterfall.prototype.expandAllShortcuts = function(commandStr) {
+ _.each(this.shortcutWaterfall, function(shortcutMap) {
+ commandStr = this.expandShortcut(commandStr, shortcutMap);
+ }, this);
+ return commandStr;
+};
+
+ParseWaterfall.prototype.expandShortcut = function(commandStr, shortcutMap) {
+ _.each(shortcutMap, function(regex, method) {
+ var results = regex.exec(commandStr);
+ if (results) {
+ commandStr = method + ' ' + commandStr.slice(results[0].length);
+ }
+ });
+ return commandStr;
+};
+
+ParseWaterfall.prototype.processAllInstants = function(commandStr) {
+ _.each(this.instantWaterfall, function(instantCommands) {
+ this.processInstant(commandStr, instantCommands);
+ }, this);
+};
+
+ParseWaterfall.prototype.processInstant = function(commandStr, instantCommands) {
+ _.each(instantCommands, function(tuple) {
+ var regex = tuple[0];
+ var results = regex.exec(commandStr);
+ if (results) {
+ // this will throw a result
+ tuple[1](results);
+ }
+ });
+};
+
+ParseWaterfall.prototype.parseAll = function(commandStr) {
+ var toReturn = false;
+ _.each(this.parseWaterfall, function(parseFunc) {
+ var results = parseFunc(commandStr);
+ if (results) {
+ toReturn = results;
+ }
+ }, this);
+
+ return toReturn;
+};
+
+exports.ParseWaterfall = ParseWaterfall;
diff --git a/src/js/level/sandboxCommands.js b/src/js/level/sandboxCommands.js
index 5bb2116e..4e35259b 100644
--- a/src/js/level/sandboxCommands.js
+++ b/src/js/level/sandboxCommands.js
@@ -9,7 +9,7 @@ var GitError = Errors.GitError;
var Warning = Errors.Warning;
var CommandResult = Errors.CommandResult;
-var sandboxInstantCommands = [
+var instantCommands = [
[/^ls/, function() {
throw new CommandResult({
msg: "DontWorryAboutFilesInThisDemo.txt"
@@ -20,45 +20,6 @@ var sandboxInstantCommands = [
msg: "Directory Changed to '/directories/dont/matter/in/this/demo'"
});
}],
- [/^git help($|\s)/, function() {
- // sym link this to the blank git command
- var allCommands = Command.prototype.getSandboxCommands();
- // wow this is hacky :(
- var equivalent = 'git';
- _.each(allCommands, function(bits) {
- var regex = bits[0];
- if (regex.test(equivalent)) {
- bits[1]();
- }
- });
- }],
- [/^git$/, function() {
- var lines = [
- 'Git Version PCOTTLE.1.0',
- '
',
- 'Usage:',
- _.escape('\t git []'),
- '
',
- 'Supported commands:',
- '
'
- ];
- var commands = GitOptionParser.prototype.getMasterOptionMap();
-
- // build up a nice display of what we support
- _.each(commands, function(commandOptions, command) {
- lines.push('git ' + command);
- _.each(commandOptions, function(vals, optionName) {
- lines.push('\t ' + optionName);
- }, this);
- }, this);
-
- // format and throw
- var msg = lines.join('\n');
- msg = msg.replace(/\t/g, ' ');
- throw new CommandResult({
- msg: msg
- });
- }],
[/^refresh$/, function() {
var events = require('../app').getEvents();
@@ -78,4 +39,4 @@ var sandboxInstantCommands = [
}]
];
-exports.sandboxInstantCommands = sandboxInstantCommands;
+exports.instantCommands = instantCommands;
diff --git a/src/js/models/commandModel.js b/src/js/models/commandModel.js
index e698938a..421e9329 100644
--- a/src/js/models/commandModel.js
+++ b/src/js/models/commandModel.js
@@ -6,7 +6,7 @@ var Errors = require('../util/errors');
var GitCommands = require('../git/commands');
var GitOptionParser = GitCommands.GitOptionParser;
-var sandboxInstantCommands = require('../level/sandboxCommands').sandboxInstantCommands;
+var ParseWaterfall = require('../level/parseWaterfall').ParseWaterfall;
var CommandProcessError = Errors.CommandProcessError;
var GitError = Errors.GitError;
@@ -18,38 +18,47 @@ var Command = Backbone.Model.extend({
status: 'inqueue',
rawStr: null,
result: '',
+ createTime: null,
error: null,
warnings: null,
+ parseWaterfall: new ParseWaterfall(),
generalArgs: null,
supportedMap: null,
options: null,
- method: null,
+ method: null
- createTime: null
},
- validateAtInit: function() {
- // weird things happen with defaults if you dont
- // make new objects
- this.set('generalArgs', []);
- this.set('supportedMap', {});
- this.set('warnings', []);
-
- if (this.get('rawStr') === null) {
- throw new Error('Give me a string!');
- }
- if (!this.get('createTime')) {
- this.set('createTime', new Date().toString());
- }
-
+ initialize: function(options) {
+ this.initDefaults();
+ this.validateAtInit();
this.on('change:error', this.errorChanged, this);
// catch errors on init
if (this.get('error')) {
this.errorChanged();
}
+
+ this.parseOrCatch();
+ },
+
+ initDefaults: function() {
+ // weird things happen with defaults if you dont
+ // make new objects
+ this.set('generalArgs', []);
+ this.set('supportedMap', {});
+ this.set('warnings', []);
+ },
+
+ validateAtInit: function() {
+ if (this.get('rawStr') === null) {
+ throw new Error('Give me a string!');
+ }
+ if (!this.get('createTime')) {
+ this.set('createTime', new Date().toString());
+ }
},
setResult: function(msg) {
@@ -71,19 +80,26 @@ var Command = Backbone.Model.extend({
return '' + i + this.get('warnings').join('
' + i) + '
';
},
- initialize: function() {
- this.validateAtInit();
- this.parseOrCatch();
- },
-
parseOrCatch: function() {
+ this.expandShortcuts(this.get('rawStr'));
try {
- this.parse();
+ this.processInstants();
} catch (err) {
Errors.filterError(err);
// errorChanged() will handle status and all of that
this.set('error', err);
}
+
+ if (this.parseAll()) {
+ // something in our parse waterfall succeeded
+ return;
+ }
+
+ // if we reach here, this command is not supported :-/
+ this.set('error', new CommandProcessError({
+ msg: 'The command "' + this.get('rawStr') + '" isn\'t supported, sorry!'
+ })
+ );
},
errorChanged: function() {
@@ -103,65 +119,35 @@ var Command = Backbone.Model.extend({
this.set('result', this.get('error').toResult());
},
- parse: function() {
+ expandShortcuts: function(str) {
+ str = this.get('parseWaterfall').expandAllShortcuts(str);
+ this.set('rawStr', str);
+ },
+
+ processInstants: function() {
var str = this.get('rawStr');
// first if the string is empty, they just want a blank line
if (!str.length) {
throw new CommandResult({msg: ""});
}
- str = GitCommands.expandShortcut(str);
- this.set('rawStr', str);
-
- // then check if it's one of our sandbox commands
- _.each(sandboxInstantCommands, function(tuple) {
- var regex = tuple[0];
- var results = regex.exec(str);
- if (results) {
- // this will throw a result
- tuple[1](results);
- }
- });
-
- // see if begins with git
- if (str.slice(0,3) !== 'git') {
- throw new CommandProcessError({
- msg: 'That command is not supported, sorry!'
- });
- }
-
- // ok, we have a (probably) valid command. actually parse it
- this.gitParse(str);
+ // then instant commands that will throw
+ this.get('parseWaterfall').processAllInstants(str);
},
- gitParse: function(str) {
- // now slice off command part
- var fullCommand = str.slice('git '.length);
+ parseAll: function() {
+ var str = this.get('rawStr');
+ var results = this.get('parseWaterfall').parseAll(str);
- // see if we support this particular command
- _.each(GitCommands.getRegexMap(), function(regex, method) {
- if (regex.exec(fullCommand)) {
- this.set('options', fullCommand.slice(method.length + 1));
- this.set('method', method);
- // we should stop iterating, but the regex will only match
- // one command in practice. we could stop iterating if we used
- // jqeurys for each but im using underscore (for no real reason other
- // than style)
- }
- }, this);
-
- if (!this.get('method')) {
- throw new CommandProcessError({
- msg: "Sorry, this demo does not support that git command: " + fullCommand
- });
+ if (!results) {
+ // nothing parsed successfully
+ return false;
}
- // parse off the options and assemble the map / general args
- var options = new GitOptionParser(this.get('method'), this.get('options'));
-
- // steal these away so we can be completely JSON
- this.set('generalArgs', options.generalArgs);
- this.set('supportedMap', options.supportedMap);
+ _.each(results.toSet, function(obj, key) {
+ this.set(key, obj);
+ }, this);
+ return true;
}
});
diff --git a/todo.txt b/todo.txt
index 8b0191c0..a0ff3a0a 100644
--- a/todo.txt
+++ b/todo.txt
@@ -35,6 +35,10 @@ Big Bugs to fix:
Done things:
(I only started this on Dec 17th 2012 to get a better sense of what was done)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+[x] ok fuckit here is the deal. Command model has minimal logic -- it calls
+ to a parse waterfall that expands any shortcuts needed, handles any instant
+ commands, and then finally will handle the dispatching. I think this will be
+ really nice :D
[x] disabled map for levels
[x] better click events on branches and commits
[x] change to returning a promise for multiview