diff --git a/build/bundle.js b/build/bundle.js index e0c866c2..71f0dd8f 100644 --- a/build/bundle.js +++ b/build/bundle.js @@ -392,147 +392,10 @@ process.binding = function (name) { }); -require.define("/async.js",function(require,module,exports,__dirname,__filename,process,global){var GLOBAL = require('./constants').GLOBAL; - -var Animation = Backbone.Model.extend({ - defaults: { - duration: 300, - closure: null - }, - - validateAtInit: function() { - if (!this.get('closure')) { - throw new Error('give me a closure!'); - } - }, - - initialize: function(options) { - this.validateAtInit(); - }, - - run: function() { - this.get('closure')(); - } -}); - -var AnimationQueue = Backbone.Model.extend({ - defaults: { - animations: null, - index: 0, - callback: null, - defer: false - }, - - initialize: function(options) { - this.set('animations', []); - if (!options.callback) { - console.warn('no callback'); - } - }, - - add: function(animation) { - if (!animation instanceof Animation) { - throw new Error("Need animation not something else"); - } - - this.get('animations').push(animation); - }, - - start: function() { - this.set('index', 0); - - // set the global lock that we are animating - GLOBAL.isAnimating = true; - this.next(); - }, - - finish: function() { - // release lock here - GLOBAL.isAnimating = false; - this.get('callback')(); - }, - - next: function() { - // ok so call the first animation, and then set a timeout to call the next - // TODO: animations with callbacks!! - var animations = this.get('animations'); - var index = this.get('index'); - if (index >= animations.length) { - this.finish(); - return; - } - - var next = animations[index]; - var duration = next.get('duration'); - - next.run(); - - this.set('index', index + 1); - setTimeout(_.bind(function() { - this.next(); - }, this), duration); - } -}); - -exports.Animation = Animation; -exports.AnimationQueue = AnimationQueue; - - -}); - -require.define("/constants.js",function(require,module,exports,__dirname,__filename,process,global){/** - * Constants....!!! - */ -var TIME = { - betweenCommandsDelay: 400 -}; - -// useful for locks, etc -var GLOBAL = { - isAnimating: false -}; - -var GRAPHICS = { - arrowHeadSize: 8, - - nodeRadius: 17, - curveControlPointOffset: 50, - defaultEasing: 'easeInOut', - defaultAnimationTime: 400, - - //rectFill: '#FF3A3A', - rectFill: 'hsb(0.8816909813322127,0.7,1)', - headRectFill: '#2831FF', - rectStroke: '#FFF', - rectStrokeWidth: '3', - - multiBranchY: 20, - upstreamHeadOpacity: 0.5, - upstreamNoneOpacity: 0.2, - edgeUpstreamHeadOpacity: 0.4, - edgeUpstreamNoneOpacity: 0.15, - - visBranchStrokeWidth: 2, - visBranchStrokeColorNone: '#333', - - defaultNodeFill: 'hsba(0.5,0.8,0.7,1)', - defaultNodeStrokeWidth: 2, - defaultNodeStroke: '#FFF', - - orphanNodeFill: 'hsb(0.5,0.8,0.7)' -}; - -exports.GLOBAL = GLOBAL; -exports.TIME = TIME; -exports.GRAPHICS = GRAPHICS; - - -}); - -require.define("/git.js",function(require,module,exports,__dirname,__filename,process,global){var AnimationFactoryModule = require('./animationFactory'); +require.define("/git.js",function(require,module,exports,__dirname,__filename,process,global){var AnimationFactoryModule = require('./animation/animationFactory'); var animationFactory = new AnimationFactoryModule.AnimationFactory(); var Main = require('./app/main'); -var AnimationQueue = require('./async').AnimationQueue; +var AnimationQueue = require('./animation').AnimationQueue; var InteractiveRebaseView = require('./miscViews').InteractiveRebaseView; var Errors = require('./errors'); @@ -2179,7 +2042,7 @@ exports.Ref = Ref; }); -require.define("/animationFactory.js",function(require,module,exports,__dirname,__filename,process,global){/****************** +require.define("/animation/animationFactory.js",function(require,module,exports,__dirname,__filename,process,global){/****************** * This class is responsible for a lot of the heavy lifting around creating an animation at a certain state in time. * The tricky thing is that when a new commit has to be "born," say in the middle of a rebase * or something, it must animate out from the parent position to it's birth position. @@ -2189,8 +2052,8 @@ require.define("/animationFactory.js",function(require,module,exports,__dirname, * and then essentially animate the entire tree too. */ -var Animation = require('./async').Animation; -var GRAPHICS = require('./constants').GRAPHICS; +var Animation = require('./index').Animation; +var GRAPHICS = require('../constants').GRAPHICS; // essentially a static class var AnimationFactory = function() { @@ -2436,6 +2299,143 @@ AnimationFactory.prototype.genFromToSnapshotAnimation = function( exports.AnimationFactory = AnimationFactory; +}); + +require.define("/animation/index.js",function(require,module,exports,__dirname,__filename,process,global){var GLOBAL = require('../constants').GLOBAL; + +var Animation = Backbone.Model.extend({ + defaults: { + duration: 300, + closure: null + }, + + validateAtInit: function() { + if (!this.get('closure')) { + throw new Error('give me a closure!'); + } + }, + + initialize: function(options) { + this.validateAtInit(); + }, + + run: function() { + this.get('closure')(); + } +}); + +var AnimationQueue = Backbone.Model.extend({ + defaults: { + animations: null, + index: 0, + callback: null, + defer: false + }, + + initialize: function(options) { + this.set('animations', []); + if (!options.callback) { + console.warn('no callback'); + } + }, + + add: function(animation) { + if (!animation instanceof Animation) { + throw new Error("Need animation not something else"); + } + + this.get('animations').push(animation); + }, + + start: function() { + this.set('index', 0); + + // set the global lock that we are animating + GLOBAL.isAnimating = true; + this.next(); + }, + + finish: function() { + // release lock here + GLOBAL.isAnimating = false; + this.get('callback')(); + }, + + next: function() { + // ok so call the first animation, and then set a timeout to call the next + // TODO: animations with callbacks!! + var animations = this.get('animations'); + var index = this.get('index'); + if (index >= animations.length) { + this.finish(); + return; + } + + var next = animations[index]; + var duration = next.get('duration'); + + next.run(); + + this.set('index', index + 1); + setTimeout(_.bind(function() { + this.next(); + }, this), duration); + } +}); + +exports.Animation = Animation; +exports.AnimationQueue = AnimationQueue; + + +}); + +require.define("/constants.js",function(require,module,exports,__dirname,__filename,process,global){/** + * Constants....!!! + */ +var TIME = { + betweenCommandsDelay: 400 +}; + +// useful for locks, etc +var GLOBAL = { + isAnimating: false +}; + +var GRAPHICS = { + arrowHeadSize: 8, + + nodeRadius: 17, + curveControlPointOffset: 50, + defaultEasing: 'easeInOut', + defaultAnimationTime: 400, + + //rectFill: '#FF3A3A', + rectFill: 'hsb(0.8816909813322127,0.7,1)', + headRectFill: '#2831FF', + rectStroke: '#FFF', + rectStrokeWidth: '3', + + multiBranchY: 20, + upstreamHeadOpacity: 0.5, + upstreamNoneOpacity: 0.2, + edgeUpstreamHeadOpacity: 0.4, + edgeUpstreamNoneOpacity: 0.15, + + visBranchStrokeWidth: 2, + visBranchStrokeColorNone: '#333', + + defaultNodeFill: 'hsba(0.5,0.8,0.7,1)', + defaultNodeStrokeWidth: 2, + defaultNodeStroke: '#FFF', + + orphanNodeFill: 'hsb(0.5,0.8,0.7)' +}; + +exports.GLOBAL = GLOBAL; +exports.TIME = TIME; +exports.GRAPHICS = GRAPHICS; + + }); require.define("/app/main.js",function(require,module,exports,__dirname,__filename,process,global){/** @@ -5306,355 +5306,6 @@ exports.LevelEngine = LevelEngine; }); -require.define("/animationFactory.js",function(require,module,exports,__dirname,__filename,process,global){/****************** - * This class is responsible for a lot of the heavy lifting around creating an animation at a certain state in time. - * The tricky thing is that when a new commit has to be "born," say in the middle of a rebase - * or something, it must animate out from the parent position to it's birth position. - - * These two positions though may not be where the commit finally ends up. So we actually need to take a snapshot of the tree, - * store all those positions, take a snapshot of the tree after a layout refresh afterwards, and then animate between those two spots. - * and then essentially animate the entire tree too. - */ - -var Animation = require('./async').Animation; -var GRAPHICS = require('./constants').GRAPHICS; - -// essentially a static class -var AnimationFactory = function() { - -}; - -AnimationFactory.prototype.genCommitBirthAnimation = function(animationQueue, commit, gitVisuals) { - if (!animationQueue) { - throw new Error("Need animation queue to add closure to!"); - } - - var time = GRAPHICS.defaultAnimationTime * 1.0; - var bounceTime = time * 2; - - // essentially refresh the entire tree, but do a special thing for the commit - var visNode = commit.get('visNode'); - - var animation = function() { - // this takes care of refs and all that jazz, and updates all the positions - gitVisuals.refreshTree(time); - - visNode.setBirth(); - visNode.parentInFront(); - gitVisuals.visBranchesFront(); - - visNode.animateUpdatedPosition(bounceTime, 'bounce'); - visNode.animateOutgoingEdges(time); - }; - - animationQueue.add(new Animation({ - closure: animation, - duration: Math.max(time, bounceTime) - })); -}; - -AnimationFactory.prototype.overrideOpacityDepth2 = function(attr, opacity) { - opacity = (opacity === undefined) ? 1 : opacity; - - var newAttr = {}; - - _.each(attr, function(partObj, partName) { - newAttr[partName] = {}; - _.each(partObj, function(val, key) { - if (key == 'opacity') { - newAttr[partName][key] = opacity; - } else { - newAttr[partName][key] = val; - } - }); - }); - return newAttr; -}; - -AnimationFactory.prototype.overrideOpacityDepth3 = function(snapShot, opacity) { - var newSnap = {}; - - _.each(snapShot, function(visObj, visID) { - newSnap[visID] = this.overrideOpacityDepth2(visObj, opacity); - }, this); - return newSnap; -}; - -AnimationFactory.prototype.genCommitBirthClosureFromSnapshot = function(step, gitVisuals) { - var time = GRAPHICS.defaultAnimationTime * 1.0; - var bounceTime = time * 1.5; - - var visNode = step.newCommit.get('visNode'); - var afterAttrWithOpacity = this.overrideOpacityDepth2(step.afterSnapshot[visNode.getID()]); - var afterSnapWithOpacity = this.overrideOpacityDepth3(step.afterSnapshot); - - var animation = function() { - visNode.setBirthFromSnapshot(step.beforeSnapshot); - visNode.parentInFront(); - gitVisuals.visBranchesFront(); - - visNode.animateToAttr(afterAttrWithOpacity, bounceTime, 'bounce'); - visNode.animateOutgoingEdgesToAttr(afterSnapWithOpacity, bounceTime); - }; - - return animation; -}; - -AnimationFactory.prototype.refreshTree = function(animationQueue, gitVisuals) { - animationQueue.add(new Animation({ - closure: function() { - gitVisuals.refreshTree(); - } - })); -}; - -AnimationFactory.prototype.rebaseAnimation = function(animationQueue, rebaseResponse, - gitEngine, gitVisuals) { - - this.rebaseHighlightPart(animationQueue, rebaseResponse, gitEngine); - this.rebaseBirthPart(animationQueue, rebaseResponse, gitEngine, gitVisuals); -}; - -AnimationFactory.prototype.rebaseHighlightPart = function(animationQueue, rebaseResponse, gitEngine) { - var fullTime = GRAPHICS.defaultAnimationTime * 0.66; - var slowTime = fullTime * 2.0; - - // we want to highlight all the old commits - var oldCommits = rebaseResponse.toRebaseArray; - // we are either highlighting to a visBranch or a visNode - var visBranch = rebaseResponse.destinationBranch.get('visBranch'); - if (!visBranch) { - // in the case where we rebase onto a commit - visBranch = rebaseResponse.destinationBranch.get('visNode'); - } - - _.each(oldCommits, function(oldCommit) { - var visNode = oldCommit.get('visNode'); - animationQueue.add(new Animation({ - closure: function() { - visNode.highlightTo(visBranch, slowTime, 'easeInOut'); - }, - duration: fullTime * 1.5 - })); - - }, this); - - this.delay(animationQueue, fullTime * 2); -}; - -AnimationFactory.prototype.rebaseBirthPart = function(animationQueue, rebaseResponse, - gitEngine, gitVisuals) { - var rebaseSteps = rebaseResponse.rebaseSteps; - - var newVisNodes = []; - _.each(rebaseSteps, function(step) { - var visNode = step.newCommit.get('visNode'); - - newVisNodes.push(visNode); - visNode.setOpacity(0); - visNode.setOutgoingEdgesOpacity(0); - }, this); - - var previousVisNodes = []; - _.each(rebaseSteps, function(rebaseStep, index) { - var toOmit = newVisNodes.slice(index + 1); - - var snapshotPart = this.genFromToSnapshotAnimation( - rebaseStep.beforeSnapshot, - rebaseStep.afterSnapshot, - toOmit, - previousVisNodes, - gitVisuals - ); - var birthPart = this.genCommitBirthClosureFromSnapshot(rebaseStep, gitVisuals); - - var animation = function() { - snapshotPart(); - birthPart(); - }; - - animationQueue.add(new Animation({ - closure: animation, - duration: GRAPHICS.defaultAnimationTime * 1.5 - })); - - previousVisNodes.push(rebaseStep.newCommit.get('visNode')); - }, this); - - // need to delay to let bouncing finish - this.delay(animationQueue); - - this.refreshTree(animationQueue, gitVisuals); -}; - -AnimationFactory.prototype.delay = function(animationQueue, time) { - time = time || GRAPHICS.defaultAnimationTime; - animationQueue.add(new Animation({ - closure: function() { }, - duration: time - })); -}; - -AnimationFactory.prototype.genSetAllCommitOpacities = function(visNodes, opacity) { - // need to slice for closure - var nodesToAnimate = visNodes.slice(0); - - return function() { - _.each(nodesToAnimate, function(visNode) { - visNode.setOpacity(opacity); - visNode.setOutgoingEdgesOpacity(opacity); - }); - }; -}; - -AnimationFactory.prototype.stripObjectsFromSnapshot = function(snapShot, toOmit) { - var ids = []; - _.each(toOmit, function(obj) { - ids.push(obj.getID()); - }); - - var newSnapshot = {}; - _.each(snapShot, function(val, key) { - if (_.include(ids, key)) { - // omit - return; - } - newSnapshot[key] = val; - }, this); - return newSnapshot; -}; - -AnimationFactory.prototype.genFromToSnapshotAnimation = function( - beforeSnapshot, - afterSnapshot, - commitsToOmit, - commitsToFixOpacity, - gitVisuals) { - - // we want to omit the commit outgoing edges - var toOmit = []; - _.each(commitsToOmit, function(visNode) { - toOmit.push(visNode); - toOmit = toOmit.concat(visNode.get('outgoingEdges')); - }); - - var fixOpacity = function(obj) { - if (!obj) { return; } - _.each(obj, function(attr, partName) { - obj[partName].opacity = 1; - }); - }; - - // HORRIBLE loop to fix opacities all throughout the snapshot - _.each([beforeSnapshot, afterSnapshot], function(snapShot) { - _.each(commitsToFixOpacity, function(visNode) { - fixOpacity(snapShot[visNode.getID()]); - _.each(visNode.get('outgoingEdges'), function(visEdge) { - fixOpacity(snapShot[visEdge.getID()]); - }); - }); - }); - - return function() { - gitVisuals.animateAllFromAttrToAttr(beforeSnapshot, afterSnapshot, toOmit); - }; -}; - -exports.AnimationFactory = AnimationFactory; - - -}); -require("/animationFactory.js"); - -require.define("/async.js",function(require,module,exports,__dirname,__filename,process,global){var GLOBAL = require('./constants').GLOBAL; - -var Animation = Backbone.Model.extend({ - defaults: { - duration: 300, - closure: null - }, - - validateAtInit: function() { - if (!this.get('closure')) { - throw new Error('give me a closure!'); - } - }, - - initialize: function(options) { - this.validateAtInit(); - }, - - run: function() { - this.get('closure')(); - } -}); - -var AnimationQueue = Backbone.Model.extend({ - defaults: { - animations: null, - index: 0, - callback: null, - defer: false - }, - - initialize: function(options) { - this.set('animations', []); - if (!options.callback) { - console.warn('no callback'); - } - }, - - add: function(animation) { - if (!animation instanceof Animation) { - throw new Error("Need animation not something else"); - } - - this.get('animations').push(animation); - }, - - start: function() { - this.set('index', 0); - - // set the global lock that we are animating - GLOBAL.isAnimating = true; - this.next(); - }, - - finish: function() { - // release lock here - GLOBAL.isAnimating = false; - this.get('callback')(); - }, - - next: function() { - // ok so call the first animation, and then set a timeout to call the next - // TODO: animations with callbacks!! - var animations = this.get('animations'); - var index = this.get('index'); - if (index >= animations.length) { - this.finish(); - return; - } - - var next = animations[index]; - var duration = next.get('duration'); - - next.run(); - - this.set('index', index + 1); - setTimeout(_.bind(function() { - this.next(); - }, this), duration); - } -}); - -exports.Animation = Animation; -exports.AnimationQueue = AnimationQueue; - - -}); -require("/async.js"); - require.define("/collections.js",function(require,module,exports,__dirname,__filename,process,global){var Commit = require('./git').Commit; var Branch = require('./git').Branch; @@ -6217,8 +5868,8 @@ require.define("/debug.js",function(require,module,exports,__dirname,__filename, Levels: require('./levels'), Constants: require('./constants'), Collections: require('./collections'), - Async: require('./async'), - AnimationFactory: require('./animationFactory'), + Async: require('./animation'), + AnimationFactory: require('./animation/animationFactory'), Main: require('./app/main') }; @@ -6281,10 +5932,10 @@ var GitError = exports.GitError = MyError.extend({ }); require("/errors.js"); -require.define("/git.js",function(require,module,exports,__dirname,__filename,process,global){var AnimationFactoryModule = require('./animationFactory'); +require.define("/git.js",function(require,module,exports,__dirname,__filename,process,global){var AnimationFactoryModule = require('./animation/animationFactory'); var animationFactory = new AnimationFactoryModule.AnimationFactory(); var Main = require('./app/main'); -var AnimationQueue = require('./async').AnimationQueue; +var AnimationQueue = require('./animation').AnimationQueue; var InteractiveRebaseView = require('./miscViews').InteractiveRebaseView; var Errors = require('./errors'); diff --git a/src/animationFactory.js b/src/animation/animationFactory.js similarity index 98% rename from src/animationFactory.js rename to src/animation/animationFactory.js index c9aa8884..bd04afac 100644 --- a/src/animationFactory.js +++ b/src/animation/animationFactory.js @@ -8,8 +8,8 @@ * and then essentially animate the entire tree too. */ -var Animation = require('./async').Animation; -var GRAPHICS = require('./constants').GRAPHICS; +var Animation = require('./index').Animation; +var GRAPHICS = require('../constants').GRAPHICS; // essentially a static class var AnimationFactory = function() { diff --git a/src/async.js b/src/animation/index.js similarity index 97% rename from src/async.js rename to src/animation/index.js index f8d6747a..492d99d4 100644 --- a/src/async.js +++ b/src/animation/index.js @@ -1,4 +1,4 @@ -var GLOBAL = require('./constants').GLOBAL; +var GLOBAL = require('../constants').GLOBAL; var Animation = Backbone.Model.extend({ defaults: { diff --git a/src/app/main.js b/src/app/main.js new file mode 100644 index 00000000..2f5df65a --- /dev/null +++ b/src/app/main.js @@ -0,0 +1,53 @@ +/** + * Globals + */ +var events = _.clone(Backbone.Events); +var ui = null; +var mainVis = null; + +/////////////////////////////////////////////////////////////////////// + +$(document).ready(function(){ + var Visuals = require('../visuals'); + + ui = new UI(); + mainVis = new Visuals.Visualization({ + el: $('#canvasWrapper')[0] + }); + + if (/\?demo/.test(window.location.href)) { + setTimeout(function() { + events.trigger('submitCommandValueFromEvent', "gc; git checkout HEAD~1; git commit; git checkout -b bugFix; gc; gc; git rebase master; git checkout master; gc; gc; git merge bugFix"); + }, 500); + } +}); + +function UI() { + var Collections = require('../collections'); + var CommandViews = require('../commandViews'); + + this.commandCollection = new Collections.CommandCollection(); + + this.commandBuffer = new Collections.CommandBuffer({ + collection: this.commandCollection + }); + + this.commandPromptView = new CommandViews.CommandPromptView({ + el: $('#commandLineBar'), + collection: this.commandCollection + }); + this.commandLineHistoryView = new CommandViews.CommandLineHistoryView({ + el: $('#commandLineHistory'), + collection: this.commandCollection + }); + + $('#commandTextField').focus(); +} + +exports.getEvents = function() { + return events; +}; +exports.getUI = function() { + return ui; +}; + diff --git a/src/debug.js b/src/debug.js index b8c5baf3..1641d57c 100644 --- a/src/debug.js +++ b/src/debug.js @@ -6,8 +6,8 @@ var toGlobalize = { Levels: require('./levels'), Constants: require('./constants'), Collections: require('./collections'), - Async: require('./async'), - AnimationFactory: require('./animationFactory'), + Async: require('./animation'), + AnimationFactory: require('./animation/animationFactory'), Main: require('./app/main') }; diff --git a/src/git.js b/src/git.js index 36f8463e..3d658389 100644 --- a/src/git.js +++ b/src/git.js @@ -1,7 +1,7 @@ -var AnimationFactoryModule = require('./animationFactory'); +var AnimationFactoryModule = require('./animation/animationFactory'); var animationFactory = new AnimationFactoryModule.AnimationFactory(); var Main = require('./app/main'); -var AnimationQueue = require('./async').AnimationQueue; +var AnimationQueue = require('./animation').AnimationQueue; var InteractiveRebaseView = require('./miscViews').InteractiveRebaseView; var Errors = require('./errors'); diff --git a/src/models/commandModel.js b/src/models/commandModel.js new file mode 100644 index 00000000..dcb2bca5 --- /dev/null +++ b/src/models/commandModel.js @@ -0,0 +1,372 @@ +var Errors = require('../errors'); + +var CommandProcessError = Errors.CommandProcessError; +var GitError = Errors.GitError; +var Warning = Errors.Warning; +var CommandResult = Errors.CommandResult; + +var Command = Backbone.Model.extend({ + defaults: { + status: 'inqueue', + rawStr: null, + result: '', + + error: null, + warnings: null, + + generalArgs: null, + supportedMap: null, + options: 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()); + } + + + this.on('change:error', this.errorChanged, this); + // catch errors on init + if (this.get('error')) { + this.errorChanged(); + } + }, + + setResult: function(msg) { + this.set('result', msg); + }, + + addWarning: function(msg) { + this.get('warnings').push(msg); + // change numWarnings so the change event fires. This is bizarre -- Backbone can't + // detect if an array changes, so adding an element does nothing + this.set('numWarnings', this.get('numWarnings') ? this.get('numWarnings') + 1 : 1); + }, + + getFormattedWarnings: function() { + if (!this.get('warnings').length) { + return ''; + } + var i = ''; + return '
' + i + this.get('warnings').join('
' + i) + '
'; + }, + + initialize: function() { + this.validateAtInit(); + this.parseOrCatch(); + }, + + parseOrCatch: function() { + try { + this.parse(); + } catch (err) { + if (err instanceof CommandProcessError || + err instanceof GitError || + err instanceof CommandResult || + err instanceof Warning) { + // errorChanged() will handle status and all of that + this.set('error', err); + } else { + throw err; + } + } + }, + + errorChanged: function() { + var err = this.get('error'); + if (err instanceof CommandProcessError || + err instanceof GitError) { + this.set('status', 'error'); + } else if (err instanceof CommandResult) { + this.set('status', 'finished'); + } else if (err instanceof Warning) { + this.set('status', 'warning'); + } + this.formatError(); + }, + + formatError: function() { + this.set('result', this.get('error').toResult()); + }, + + getShortcutMap: function() { + return { + 'git commit': /^gc($|\s)/, + 'git add': /^ga($|\s)/, + 'git checkout': /^gchk($|\s)/, + 'git rebase': /^gr($|\s)/, + 'git branch': /^gb($|\s)/ + }; + }, + + 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)/ + }; + }, + + getSandboxCommands: function() { + return [ + [/^ls/, function() { + throw new CommandResult({ + msg: "DontWorryAboutFilesInThisDemo.txt" + }); + }], + [/^cd/, function() { + throw new CommandResult({ + 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', + '