mirror of
https://github.com/pcottle/learnGitBranching.git
synced 2025-07-01 18:24:28 +02:00
command queue working
This commit is contained in:
parent
2a84ebe36d
commit
5ee115872d
6 changed files with 151 additions and 101 deletions
Binary file not shown.
80
src/async.js
80
src/async.js
|
@ -3,67 +3,23 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Particle System AsyncEngine
|
|
||||||
*
|
|
||||||
* Handles async stuff like adding the edges, etc
|
|
||||||
*/
|
|
||||||
function AsyncEngine() {
|
|
||||||
this.addEdgeTimeout = null;
|
|
||||||
this.edgeClosures = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
AsyncEngine.prototype.addEdge = function(node1, node2) {
|
|
||||||
this.touchEdgeTimer();
|
|
||||||
|
|
||||||
this.edgeClosures.push(this.edgeClosureFactory(node1, node2));
|
|
||||||
};
|
|
||||||
|
|
||||||
AsyncEngine.prototype.edgeClosureFactory = function(node1, node2) {
|
|
||||||
var c = function() {
|
|
||||||
var e = sys.addEdge(node1, node2);
|
var e = sys.addEdge(node1, node2);
|
||||||
};
|
*/
|
||||||
return c;
|
|
||||||
};
|
|
||||||
|
|
||||||
AsyncEngine.prototype.touchEdgeTimer = function(key) {
|
function Scheduler(closures, options) {
|
||||||
if (this.addEdgeTimeout) {
|
if (!closures || !closures.length) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var _this = this;
|
|
||||||
this.addEdgeTimeout = setTimeout(function() {
|
|
||||||
_this.startEdgeScheduler();
|
|
||||||
}, 100);
|
|
||||||
};
|
|
||||||
|
|
||||||
AsyncEngine.prototype.startEdgeScheduler = function() {
|
|
||||||
// start scheduler
|
|
||||||
var s = new Scheduler(this.edgeClosures, time.edgeAddInterval, 'add_edge');
|
|
||||||
s.start();
|
|
||||||
|
|
||||||
this.resetEdges();
|
|
||||||
};
|
|
||||||
|
|
||||||
AsyncEngine.prototype.resetEdges = function() {
|
|
||||||
this.edgeClosures = [];
|
|
||||||
this.addEdgeTimeout = null;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
function Scheduler(closures, interval, type) {
|
|
||||||
if (!closures || !closures.length || !interval || !type) {
|
|
||||||
throw new Error('invalid params');
|
throw new Error('invalid params');
|
||||||
}
|
}
|
||||||
|
|
||||||
this.done = false;
|
|
||||||
this.closures = closures;
|
this.closures = closures;
|
||||||
this.interval = interval;
|
|
||||||
this.type = type;
|
this.options = options || {};
|
||||||
|
this.interval = this.options.interval || 400;
|
||||||
|
|
||||||
|
this.done = false;
|
||||||
this.timeOut = null;
|
this.timeOut = null;
|
||||||
this.index = 0;
|
this.index = 0;
|
||||||
|
|
||||||
ee.addListener('scheduler_stop', this.stopSchedule, this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Scheduler.prototype.start = function() {
|
Scheduler.prototype.start = function() {
|
||||||
|
@ -80,12 +36,13 @@ Scheduler.prototype.setNext = function(interval) {
|
||||||
interval || this.interval);
|
interval || this.interval);
|
||||||
};
|
};
|
||||||
|
|
||||||
Scheduler.prototype.stopSchedule = function(type) {
|
Scheduler.prototype.finish = function() {
|
||||||
console.log('received event signal');
|
|
||||||
if (type == 'all' || type == this.type) {
|
|
||||||
// either of these should work...
|
|
||||||
this.done = true;
|
this.done = true;
|
||||||
clearTimeout(this.timeOut);
|
clearTimeout(this.timeOut);
|
||||||
|
this.timeOut = null;
|
||||||
|
|
||||||
|
if (this.options.callback) {
|
||||||
|
this.options.callback();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -98,7 +55,7 @@ Scheduler.prototype.step = function() {
|
||||||
this.index++;
|
this.index++;
|
||||||
|
|
||||||
if (results.done || this.index >= this.closures.length) {
|
if (results.done || this.index >= this.closures.length) {
|
||||||
this.done = true;
|
this.finish();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.setNext(results.interval);
|
this.setNext(results.interval);
|
||||||
|
@ -123,10 +80,9 @@ function Breather(closure, baseline, delta, period, wait) {
|
||||||
this.interpolationFunction = TWEEN.Easing.Cubic.EaseInOut;
|
this.interpolationFunction = TWEEN.Easing.Cubic.EaseInOut;
|
||||||
|
|
||||||
if (wait) {
|
if (wait) {
|
||||||
var _this = this;
|
setTimeout(_.bind(function() {
|
||||||
setTimeout(function() {
|
this.start();
|
||||||
_this.start();
|
}, this), wait);
|
||||||
}, wait);
|
|
||||||
} else {
|
} else {
|
||||||
this.start();
|
this.start();
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
* @desc A parser for commands given
|
* @desc A parser for commands given
|
||||||
*/
|
*/
|
||||||
function Command(str) {
|
function Command(str) {
|
||||||
this.rawCommand = str;
|
|
||||||
this.results = {
|
this.results = {
|
||||||
msgs: []
|
msgs: []
|
||||||
};
|
};
|
||||||
|
@ -14,26 +13,32 @@ function Command(str) {
|
||||||
|
|
||||||
Command.prototype.getShortcutMap = function() {
|
Command.prototype.getShortcutMap = function() {
|
||||||
return {
|
return {
|
||||||
gc: 'git commit',
|
'git commit': /^gc/,
|
||||||
ga: 'git add',
|
'git add': /^ga/,
|
||||||
gchk: 'git checkout',
|
'git checkout': /^gchk/,
|
||||||
gr: 'git rebase'
|
'git rebase': /^gr/
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
Command.prototype.getRegexMap = function() {
|
Command.prototype.getRegexMap = function() {
|
||||||
return {
|
return {
|
||||||
commit: /^commit /,
|
commit: /^commit\s*/,
|
||||||
add: /^add /,
|
add: /^add\s*/,
|
||||||
checkout: /^checkout /,
|
checkout: /^checkout\s*/,
|
||||||
rebase: /^rebase /,
|
rebase: /^rebase\s*/,
|
||||||
reset: /^reset /
|
reset: /^reset\s*/
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
Command.prototype.parse = function(str) {
|
Command.prototype.parse = function(str) {
|
||||||
// first check if shortcut exists, and replace
|
// first check if shortcut exists, and replace, but
|
||||||
str = this.getShortcutMap()[str] || str;
|
// preserve options
|
||||||
|
_.each(this.getShortcutMap(), function(regex, method) {
|
||||||
|
var results = regex.exec(str);
|
||||||
|
if (results) {
|
||||||
|
str = method + str.slice(results[0].length);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// see if begins with git
|
// see if begins with git
|
||||||
if (str.slice(0,3) !== 'git') {
|
if (str.slice(0,3) !== 'git') {
|
||||||
|
@ -43,18 +48,21 @@ Command.prototype.parse = function(str) {
|
||||||
// now slice off command part
|
// now slice off command part
|
||||||
this.command = str.slice(4);
|
this.command = str.slice(4);
|
||||||
|
|
||||||
//TODO: underscore.js here
|
var matched = false;
|
||||||
_.each(this.getRegexMap(), function(regex, method) {
|
_.each(this.getRegexMap(), function(regex, method) {
|
||||||
if (regex.exec(this.command)) {
|
if (regex.exec(this.command)) {
|
||||||
this.options = this.command.slice(method.length + 1);
|
this.options = this.command.slice(method.length + 1);
|
||||||
// break out here
|
|
||||||
this[method]();
|
this[method]();
|
||||||
return false;
|
// we should stop iterating, but the regex will only match
|
||||||
|
// one command in practice
|
||||||
|
matched = true;
|
||||||
}
|
}
|
||||||
}, this);
|
}, this);
|
||||||
|
|
||||||
|
if (!matched) {
|
||||||
this.results.msgs.push('The git command "' + this.command +
|
this.results.msgs.push('The git command "' + this.command +
|
||||||
'" is not supported, sorry!');
|
'" is not supported, sorry!');
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Command.prototype.nonGitCommand = function() {
|
Command.prototype.nonGitCommand = function() {
|
||||||
|
|
95
src/git.js
95
src/git.js
|
@ -6,6 +6,30 @@ GitEngine.prototype.commit = function() {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
GitEngine.prototype.execute = function(command, callback) {
|
||||||
|
// execute command, and when it's finished, call the callback
|
||||||
|
// we still need to figure this out
|
||||||
|
|
||||||
|
var closures = this.getClosuresForCommand(command);
|
||||||
|
// make a scheduler based on all the closures, and pass in our callback
|
||||||
|
var s = new Scheduler(closures, {
|
||||||
|
callback: callback
|
||||||
|
});
|
||||||
|
s.start();
|
||||||
|
};
|
||||||
|
|
||||||
|
GitEngine.prototype.getClosuresForCommand = function(command) {
|
||||||
|
var numbers = [1,2,3,4,5,6,7,8,9,10];
|
||||||
|
var closures = [];
|
||||||
|
_.each(numbers, function(num) {
|
||||||
|
var c = function() {
|
||||||
|
console.log(num);
|
||||||
|
};
|
||||||
|
closures.push(c);
|
||||||
|
});
|
||||||
|
return closures;
|
||||||
|
};
|
||||||
|
|
||||||
var Commit = Backbone.Model.extend({
|
var Commit = Backbone.Model.extend({
|
||||||
initialize: function() {
|
initialize: function() {
|
||||||
// validation / defaults
|
// validation / defaults
|
||||||
|
@ -15,7 +39,76 @@ var Commit = Backbone.Model.extend({
|
||||||
if (!this.get('parent') && !this.get('rootCommit')) {
|
if (!this.get('parent') && !this.get('rootCommit')) {
|
||||||
throw new Error('needs parent commit');
|
throw new Error('needs parent commit');
|
||||||
}
|
}
|
||||||
|
// make a node and start drawing? this is a major TODO
|
||||||
|
},
|
||||||
|
|
||||||
|
draw: function() {
|
||||||
|
|
||||||
// make a node and start drawing?
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
function CommandQueue() {
|
||||||
|
this.commands = [];
|
||||||
|
this.consumeTimeout = null;
|
||||||
|
|
||||||
|
this.initialDelay = 400;
|
||||||
|
}
|
||||||
|
|
||||||
|
CommandQueue.prototype.add = function(command) {
|
||||||
|
this.commands.push(command);
|
||||||
|
this.touchTimer();
|
||||||
|
};
|
||||||
|
|
||||||
|
CommandQueue.prototype.touchTimer = function() {
|
||||||
|
if (this.consumeTimeout) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.consumeTimeout = setTimeout(_.bind(function() {
|
||||||
|
this.next();
|
||||||
|
}, this), this.initialDelay);
|
||||||
|
};
|
||||||
|
|
||||||
|
CommandQueue.prototype.reset = function() {
|
||||||
|
this.consumeTimeout = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
CommandQueue.prototype.next = function() {
|
||||||
|
if (this.commands.length == 0) {
|
||||||
|
this.reset();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// execute the top command by passing it into the engine
|
||||||
|
var toExecute = this.commands.shift(0);
|
||||||
|
var callback = _.bind(function() {
|
||||||
|
this.next();
|
||||||
|
}, this);
|
||||||
|
gitEngine.execute(toExecute, callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/******************
|
||||||
|
* Planning:
|
||||||
|
|
||||||
|
here is the major flow:
|
||||||
|
|
||||||
|
someone types in a command ->
|
||||||
|
make a new command object. if error, give immediate feedback, dont append to queue
|
||||||
|
if not error ->
|
||||||
|
append command object to queue
|
||||||
|
|
||||||
|
|
||||||
|
Command Queue ->
|
||||||
|
consume commands at a certain rate (either instantly if just added, or with an interval
|
||||||
|
Execute command -> (usually a git engine thing)
|
||||||
|
Wait for git engine command to finish
|
||||||
|
when done, execute next command (if more)
|
||||||
|
|
||||||
|
so two levels of Async-ness:
|
||||||
|
command queue slowly consumes commands
|
||||||
|
|
||||||
|
GitEngine executes commands, which will have async bits to them (such as popping off commits for a
|
||||||
|
rebase)
|
||||||
|
*/
|
||||||
|
|
|
@ -96,11 +96,7 @@ Renderer = function(canvas) {
|
||||||
return that;
|
return that;
|
||||||
}
|
}
|
||||||
|
|
||||||
var Maps = function(elt){
|
function addRandom() {
|
||||||
sys = arbor.ParticleSystem(4000, 500, 0.5, false, 55, 0.005, 'verlet');
|
|
||||||
sys.renderer = Renderer("#viewport");
|
|
||||||
// our newly created renderer will have its .init() method called shortly by sys...
|
|
||||||
|
|
||||||
// Add some random nodes and edges to the graph!
|
// Add some random nodes and edges to the graph!
|
||||||
nodes = [];
|
nodes = [];
|
||||||
for (var i = 0; i < 15; i++) {
|
for (var i = 0; i < 15; i++) {
|
||||||
|
@ -123,13 +119,13 @@ var Maps = function(elt){
|
||||||
while (node1 === node2) {
|
while (node1 === node2) {
|
||||||
node2 = randNode();
|
node2 = randNode();
|
||||||
}
|
}
|
||||||
engine.addEdge(node1, node2);
|
sys.addEdge(node1, node2);
|
||||||
}
|
}
|
||||||
for (var i = 0; i < nodes.length; i++) {
|
for (var i = 0; i < nodes.length; i++) {
|
||||||
var node2 = randNode();
|
var node2 = randNode();
|
||||||
while (nodes[i] === node2) {
|
while (nodes[i] === node2) {
|
||||||
node2 = randNode();
|
node2 = randNode();
|
||||||
}
|
}
|
||||||
engine.addEdge(nodes[i], node2);
|
sys.addEdge(nodes[i], node2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,17 +3,15 @@
|
||||||
*/
|
*/
|
||||||
var ee = null;
|
var ee = null;
|
||||||
var sys = null;
|
var sys = null;
|
||||||
var engine = null;
|
|
||||||
var graphicsEffects = {};
|
var graphicsEffects = {};
|
||||||
var gitEngine = null;
|
var gitEngine = null;
|
||||||
|
|
||||||
$(document).ready(function(){
|
$(document).ready(function(){
|
||||||
if (false) {
|
|
||||||
engine = new AsyncEngine();
|
|
||||||
ee = new EventEmitter();
|
|
||||||
gitEngine = new GitEngine();
|
gitEngine = new GitEngine();
|
||||||
|
ee = new EventEmitter();
|
||||||
|
|
||||||
var mcp = Maps("#maps");
|
sys = arbor.ParticleSystem(4000, 500, 0.5, false, 55, 0.005, 'verlet');
|
||||||
|
sys.renderer = Renderer('#viewport');
|
||||||
|
|
||||||
var repulsionBreathe = function(r) {
|
var repulsionBreathe = function(r) {
|
||||||
sys.parameters({repulsion: r});
|
sys.parameters({repulsion: r});
|
||||||
|
@ -21,7 +19,6 @@ $(document).ready(function(){
|
||||||
var b = new Breather(repulsionBreathe, 6050, 4000);
|
var b = new Breather(repulsionBreathe, 6050, 4000);
|
||||||
|
|
||||||
graphicsEffects.edgeStrokeEffect = new GraphicsEffect('edgeStroke', {wait: 1000});
|
graphicsEffects.edgeStrokeEffect = new GraphicsEffect('edgeStroke', {wait: 1000});
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue