Permalink
Browse files

renaming to 'toaster', adding support for declarative dependencies wt…

…h '#<< ClassName, ClassNameB'
  • Loading branch information...
1 parent d8e3048 commit 0d460b6d8a32f101277ebbf757dcf8851d95d414 @arboleya committed Sep 11, 2011
View
2 bin/coffeepot → bin/toaster
@@ -4,4 +4,4 @@ var path = require('path');
var fs = require('fs');
var lib = path.join(path.dirname(fs.realpathSync(__filename)), '../lib');
-require(lib + '/coffeepot').run()
+require(lib + '/toaster').run()
View
192 lib/coffeepot.js → lib/toaster.js
@@ -16,7 +16,6 @@
this.basepath = path.resolve(".");
argv = process.argv.slice(2);
if (argv.length && argv[0] === "new") {
- this.base;
new Machine().make(this.basepath, argv);
} else {
if (argv.length) {
@@ -48,62 +47,94 @@
}
};
Toaster.prototype.compile = function(module) {
- var contents;
- contents = this.clean(this.reorder(this.collect(module.src)));
- fs.writeFileSync(module.release, contents);
- exec("coffee -c " + module.release, __bind(function(error, stdout, stderr) {
- console.log("Toasted with love:\r\n\t" + module.release);
- if (!module.watcher) {
- return module.watcher = new Watcher(this, module);
- }
+ return this.collect(module, __bind(function(files) {
+ var contents;
+ contents = this.clean(this.reorder(files, true));
+ fs.writeFileSync(module.release, contents);
+ return exec("coffee -c " + module.release, __bind(function(error, stdout, stderr) {
+ console.log("Toasted with love:\r\n\t" + module.release);
+ if (!module.watcher) {
+ return module.watcher = new Watcher(this, module);
+ }
+ }, this));
}, this));
- return true;
};
- Toaster.prototype.collect = function(path, buffer) {
- var ext, file, filepath, name, raw, _i, _len, _ref;
- if (buffer == null) {
+ Toaster.prototype.collect = function(module, fn) {
+ return this.findall(module.src, false, __bind(function(files) {
+ var buffer, dependencies, file, item, name, raw, requirements, _i, _j, _len, _len2;
buffer = [];
- }
- _ref = fs.readdirSync(path);
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
- file = _ref[_i];
- filepath = pn("" + path + "/" + file);
- if (fs.statSync(filepath).isDirectory()) {
- this.collect(filepath, buffer);
- } else if (filepath.substr(-6 === "coffee")) {
- raw = fs.readFileSync(filepath, "utf-8");
- name = /(class\s)([\S]+)/g.exec(raw)[2];
+ for (_i = 0, _len = files.length; _i < _len; _i++) {
+ file = files[_i];
+ raw = fs.readFileSync(file, "utf-8");
+ dependencies = [];
+ if (/(class\s)([\S]+)/g.test(raw)) {
+ name = /(class\s)([\S]+)/g.exec(raw)[2];
+ }
+ if (this.find(buffer, name)) {
+ continue;
+ }
if (/(extends\s)([\S]+)/g.test(raw)) {
- ext = /(extends\s)([\S]+)/g.exec(raw)[2];
+ dependencies.push(/(extends\s)([\S]+)/g.exec(raw)[2]);
}
- if (!this.find(buffer, name)) {
- buffer.push({
- name: name,
- ext: ext,
- raw: raw
- });
+ if (/(#<<\s)(.*)/g.test(raw)) {
+ requirements = raw.match(/(#<<\s)(.*)/g);
+ for (_j = 0, _len2 = requirements.length; _j < _len2; _j++) {
+ item = requirements[_j];
+ item = /(#<<\s)(.*)/.exec(item)[2];
+ item = item.replace(/\s/g, "");
+ item = [].concat(item.split(","));
+ dependencies = dependencies.concat(item);
+ }
}
+ buffer.push({
+ name: name,
+ dependencies: dependencies,
+ raw: raw
+ });
}
- }
- return buffer;
+ return fn(buffer);
+ }, this));
};
- Toaster.prototype.reorder = function(classes) {
- var i, initd, klass, result, _len;
+ Toaster.prototype.reorder = function(classes, debug) {
+ var dependency, i, index, initd, klass, result, _len, _len2, _ref;
+ if (debug == null) {
+ debug = false;
+ }
initd = {};
for (i = 0, _len = classes.length; i < _len; i++) {
klass = classes[i];
initd["" + klass.name] = 1;
- if (klass.ext) {
- if (!initd["" + klass.ext]) {
- result = this.find(classes, klass.ext);
- classes.splice(i, 0, result.item);
- classes.splice(result.index + 1, 1);
- classes = this.reorder(classes);
+ if (klass.dependencies.length) {
+ _ref = klass.dependencies;
+ for (index = 0, _len2 = _ref.length; index < _len2; index++) {
+ dependency = _ref[index];
+ if (!initd[dependency]) {
+ result = this.find(classes, dependency);
+ classes.splice(index, 0, result.item);
+ classes.splice(result.index + 1, 1);
+ classes = this.reorder(classes);
+ }
}
}
}
return classes;
};
+ Toaster.prototype.findall = function(path, search_folders, fn) {
+ var query;
+ query = search_folders ? "-type d" : "-name '*.coffee'";
+ return exec("find " + path + " " + query, __bind(function(error, stdout, stderr) {
+ var buffer, item, items, _i, _len, _ref;
+ buffer = [];
+ _ref = items = stdout.trim().split("\n");
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ item = _ref[_i];
+ if (item !== "." && item !== "..") {
+ buffer.push(item);
+ }
+ }
+ return fn(buffer);
+ }, this));
+ };
Toaster.prototype.find = function(classes, name) {
var i, j, _len;
for (i = 0, _len = classes.length; i < _len; i++) {
@@ -130,34 +161,6 @@
};
return Toaster;
})();
- Watcher = (function() {
- function Watcher(toaster, module) {
- this.toaster = toaster;
- this.module = module;
- console.log("Watching:");
- exec("find " + this.module.src + " -name '*.coffee'", __bind(function(error, stdout, stderr) {
- var file, filepath, files, _i, _len, _ref;
- _ref = files = stdout.trim().split("\n");
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
- file = _ref[_i];
- filepath = pn(file);
- console.log("... \t" + filepath);
- fs.watchFile(filepath, {
- interval: 250
- }, __bind(function(curr, prev) {
- var ctime, mtime;
- mtime = curr.mtime.valueOf() !== prev.mtime.valueOf();
- ctime = curr.ctime.valueOf() !== prev.ctime.valueOf();
- if (mtime || ctime) {
- return this.toaster.compile(this.module);
- }
- }, this));
- }
- return console.log("--------------------------------------------------");
- }, this));
- }
- return Watcher;
- })();
Machine = (function() {
function Machine() {}
Machine.prototype.tpl = "modules = \r\n\tname: '%name'\r\n\tsrc: '%src'\r\n\trelease: '%release'";
@@ -206,8 +209,8 @@
console.log(". First, consider this as your basepath: " + this.basepath);
console.log(". Now tell me:");
return this.ask("\tWhat's your app name? (none)", /.+/, __bind(function(name) {
- return this.ask("\tWhere's its src folder? (i.e. src)", /.*/, __bind(function(src) {
- return this.ask("\tWhere do you want your release file? (i.e. release/app.js)", /.*/, __bind(function(release) {
+ return this.ask("\tWhere's its src folder? (i.e. src)", /.+/, __bind(function(src) {
+ return this.ask("\tWhere do you want your release file? (i.e. release/app.js)", /.+/, __bind(function(release) {
var toaster;
path = pn("" + this.basepath + "/toaster.coffee");
toaster = this.tpl.replace("%name", name);
@@ -239,4 +242,53 @@
};
return Machine;
})();
+ Watcher = (function() {
+ function Watcher(toaster, module) {
+ this.toaster = toaster;
+ this.module = module;
+ console.log("Watching:");
+ this.toaster.findall(this.module.src, false, __bind(function(files) {
+ var file, _i, _len, _results;
+ _results = [];
+ for (_i = 0, _len = files.length; _i < _len; _i++) {
+ file = files[_i];
+ _results.push(this.watch_file(file));
+ }
+ return _results;
+ }, this));
+ this.toaster.findall(this.module.src, true, __bind(function(folders) {
+ var folder, _i, _len, _results;
+ _results = [];
+ for (_i = 0, _len = folders.length; _i < _len; _i++) {
+ folder = folders[_i];
+ _results.push(this.watch_folder(folder));
+ }
+ return _results;
+ }, this));
+ }
+ Watcher.prototype.watch_file = function(path) {
+ path = pn(path);
+ console.log("...file: \t" + path);
+ return fs.watchFile(path, {
+ interval: 250
+ }, __bind(function(curr, prev) {
+ var ctime, mtime;
+ mtime = curr.mtime.valueOf() !== prev.mtime.valueOf();
+ ctime = curr.ctime.valueOf() !== prev.ctime.valueOf();
+ if (mtime || ctime) {
+ return this.toaster.compile(this.module);
+ }
+ }, this));
+ };
+ Watcher.prototype.watch_folder = function(path) {
+ path = pn(path);
+ console.log("...folder: \t" + path);
+ return fs.watchFile(path, {
+ interval: 250
+ }, __bind(function(curr, prev) {
+ return console.log(curr, prev);
+ }, this));
+ };
+ return Watcher;
+ })();
}).call(this);
View
7 node_modules/.bin/cake
@@ -0,0 +1,7 @@
+#!/usr/bin/env node
+
+var path = require('path');
+var fs = require('fs');
+var lib = path.join(path.dirname(fs.realpathSync(__filename)), '../lib');
+
+require(lib + '/cake').run();
View
1 node_modules/.bin/cake
View
7 node_modules/.bin/coffee
@@ -0,0 +1,7 @@
+#!/usr/bin/env node
+
+var path = require('path');
+var fs = require('fs');
+var lib = path.join(path.dirname(fs.realpathSync(__filename)), '../lib');
+
+require(lib + '/command').run();
View
1 node_modules/.bin/coffee
View
19 package.json
@@ -1,20 +1,19 @@
{
- "author": "Anderson Arboleya <me@nybras.com> (TODO: add url)",
- "name": "coffee-pot",
- "description": "Minimalist build system for coffee-script projects.",
+ "author": "Anderson Arboleya <me@nybras.com>",
+ "name": "coffee-toaster",
+ "description": "Minimalist inheritance-aware build system for coffee-script projects.",
"version": "0.0.1",
"homepage": "TODO: add homepage",
"repository": {
"type": "git",
"url": "TODO: add repository"
},
- "main": "main.js",
- "directories" : {
- "lib" : "./lib/"
+ "main": "./lib/toaster",
+ "directories": {
+ "lib": "./lib/"
},
- "main" : "./lib/coffeepot",
- "bin": {
- "coffeepot": "./bin/coffeepot"
+ "bin": {
+ "toaster": "./bin/toaster"
},
"scripts": {
"test": "test.js"
@@ -27,4 +26,4 @@
},
"devDependencies": {
}
-}
+}
View
152 src/coffeepot.coffee → src/toaster.coffee
@@ -1,6 +1,3 @@
-# toaster new /path/fo/folder
-# toaster
-
fs = require "fs"
path = require "path"
pn = path.normalize
@@ -10,16 +7,14 @@ exec = (require "child_process").exec
exports.run =->
toaster = new Toaster
+#<< Machine, Watcher
class Toaster
-
constructor:->
@basepath = path.resolve(".")
-
argv = process.argv[2..]
if argv.length && argv[0] == "new"
- @base
new Machine().make @basepath, argv
else
@basepath += "/#{argv[0]}" if argv.length
@@ -39,44 +34,64 @@ class Toaster
new Machine().toast @basepath
compile:(module)->
- contents = @clean( @reorder( @collect( module.src ) ) )
- fs.writeFileSync module.release, contents
-
- exec "coffee -c #{module.release}", (error, stdout, stderr)=>
- console.log "Toasted with love:\r\n\t#{module.release}"
- if !module.watcher
- module.watcher = new Watcher( this, module )
-
- true
+ @collect module, (files)=>
+ contents = @clean( @reorder( files, true ) )
+ fs.writeFileSync module.release, contents
+ exec "coffee -c #{module.release}", (error, stdout, stderr)=>
+ console.log "Toasted with love:\r\n\t#{module.release}"
+ module.watcher = new Watcher( this, module ) if !module.watcher
- collect:(path, buffer = [])->
- for file in fs.readdirSync path
- filepath = pn "#{path}/#{file}"
- if fs.statSync( filepath ).isDirectory()
- @collect filepath, buffer
- else if filepath.substr -6 == "coffee"
- raw = fs.readFileSync( filepath, "utf-8" )
- name = /(class\s)([\S]+)/g.exec( raw )[ 2 ]
+ collect:(module, fn)->
+ @findall module.src, false, (files)=>
+ buffer = []
+ for file in files
+ raw = fs.readFileSync file, "utf-8"
+ dependencies = []
+
+ # class name
+ if /(class\s)([\S]+)/g.test raw
+ name = /(class\s)([\S]+)/g.exec( raw )[ 2 ]
+ if @find buffer, name
+ continue
+
+ # class dependencies
if /(extends\s)([\S]+)/g.test raw
- ext = /(extends\s)([\S]+)/g.exec( raw )[ 2 ]
+ dependencies.push /(extends\s)([\S]+)/g.exec( raw )[ 2 ]
+
+ if /(#<<\s)(.*)/g.test raw
+ requirements = raw.match /(#<<\s)(.*)/g
+ for item in requirements
+ item = /(#<<\s)(.*)/.exec( item )[ 2 ]
+ item = item.replace /\s/g, ""
+ item = [].concat item.split ","
+ dependencies = dependencies.concat item
- if !@find buffer, name
- buffer.push {name: name, ext:ext, raw:raw}
- buffer
+ buffer.push {name:name, dependencies:dependencies, raw:raw}
+ fn buffer
- reorder:(classes)->
+ reorder:(classes, debug = false)->
initd = {}
for klass, i in classes
initd["#{klass.name}"] = 1
- if klass.ext
- if !initd["#{klass.ext}"]
- result = @find classes, klass.ext
- classes.splice( i, 0, result.item )
- classes.splice( result.index + 1, 1 )
- classes = @reorder( classes )
+
+ if klass.dependencies.length
+ for dependency, index in klass.dependencies
+ if !initd[dependency]
+ result = @find classes, dependency
+ classes.splice( index, 0, result.item )
+ classes.splice( result.index + 1, 1 )
+ classes = @reorder( classes )
classes
+ findall:(path, search_folders, fn)->
+ query = if search_folders then "-type d" else "-name '*.coffee'"
+ exec "find #{path} #{query}", (error, stdout, stderr)=>
+ buffer = []
+ for item in items = stdout.trim().split "\n"
+ buffer.push item if item != "." && item != ".."
+ fn buffer
+
find:(classes, name)->
for j, i in classes
return {item: j, index: i} if j.name == name
@@ -86,63 +101,47 @@ class Toaster
-class Watcher
-
- constructor:(@toaster, @module)->
- console.log "Watching:"
- exec "find #{@module.src} -name '*.coffee'", (error, stdout, stderr)=>
- for file in files = stdout.trim().split("\n")
- filepath = pn file
- console.log "... \t#{filepath}"
- fs.watchFile filepath, {interval : 250}, (curr,prev)=>
- mtime = curr.mtime.valueOf() != prev.mtime.valueOf()
- ctime = curr.ctime.valueOf() != prev.ctime.valueOf()
- @toaster.compile @module if mtime || ctime
- console.log "--------------------------------------------------"
-
-
-
class Machine
-
+
tpl: "modules = \r\n\tname: '%name'\r\n\tsrc: '%src'\r\n\trelease: '%release'"
-
+
make:(@basepath, argv)->
-
+
[action, target] = [argv[0] if argv[0], argv[1] if argv[1]]
if target == undefined
console.log "You need to inform a target path!"
return console.log "toaster new myawesomeapp"
-
+
if target.substr( 0, 1 ) != "/"
target = path.normalize( "#{@basepath}/#{target}" )
-
+
console.log ". Wonderful! Let's toast this sly little project! :)"
console.log ". First, consider this as your basepath: #{target}"
console.log ". Now tell me:"
@ask "\tWhat's your app name? (none)", /.+/, (name)=>
@ask "\tWhere's its src folder? (src)", /.*/, (src)=>
@ask "\tWhere do you want your release file? (release/app.js)", /.*/, (release)=>
-
+
srcdir = src || "src"
releasefile = release || "release/app.js"
releasedir = releasefile.split("/").slice( 0, 1).join "/"
-
+
# config file
toaster = "#{target}/toaster.coffee"
contents = @tpl.replace "%name", name
contents = contents.replace "%src", srcdir
contents = contents.replace "%release", releasefile
-
+
fs.mkdirSync target, 0755
fs.mkdirSync "#{target}/#{srcdir}", 0755
fs.mkdirSync "#{target}/#{releasedir}", 0755
fs.writeFileSync toaster, contents
-
+
process.exit()
-
+
toast:(@basepath)->
console.log "It seems this project hasn't been toasted yet."
-
+
@ask "Do you wanna toast it? (Y/n)", /.*/, (data)=>
if data != "" && data.toLowerCase != "y"
return process.exit()
@@ -152,15 +151,15 @@ class Machine
console.log ". Now tell me:"
@ask "\tWhat's your app name? (none)", /.+/, (name)=>
- @ask "\tWhere's its src folder? (i.e. src)", /.*/, (src)=>
- @ask "\tWhere do you want your release file? (i.e. release/app.js)", /.*/, (release)=>
+ @ask "\tWhere's its src folder? (i.e. src)", /.+/, (src)=>
+ @ask "\tWhere do you want your release file? (i.e. release/app.js)", /.+/, (release)=>
path = pn "#{@basepath}/toaster.coffee"
toaster = @tpl.replace "%name", name
toaster = toaster.replace "%src", src
toaster = toaster.replace "%release", release
fs.writeFileSync path, toaster
process.exit()
-
+
ask:(question, format, fn)->
stdin = process.stdin
stdout = process.stdout
@@ -174,4 +173,27 @@ class Machine
fn data
else
stdout.write "It should match: #{format}\n"
- @ask question, format, fn
+ @ask question, format, fn
+
+class Watcher
+
+ constructor:(@toaster, @module)->
+ console.log "Watching:"
+ @toaster.findall @module.src, false, (files)=>
+ @watch_file file for file in files
+ @toaster.findall @module.src, true, (folders)=>
+ @watch_folder folder for folder in folders
+
+ watch_file:(path)->
+ path = pn path
+ console.log "...file: \t#{path}"
+ fs.watchFile path, {interval : 250}, (curr,prev)=>
+ mtime = curr.mtime.valueOf() != prev.mtime.valueOf()
+ ctime = curr.ctime.valueOf() != prev.ctime.valueOf()
+ @toaster.compile @module if mtime || ctime
+
+ watch_folder:(path)->
+ path = pn path
+ console.log "...folder: \t#{path}"
+ fs.watchFile path, {interval : 250}, (curr,prev)=>
+ console.log curr, prev
View
2 toaster.coffee
@@ -1,4 +1,4 @@
modules =
name: 'Coffee Toaster'
src: 'src'
- release: 'lib/coffepot.js'
+ release: 'lib/toaster.js'

0 comments on commit 0d460b6

Please sign in to comment.