Skip to content
This repository
Browse code

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

…h '#<< ClassName, ClassNameB'
  • Loading branch information...
commit 0d460b6d8a32f101277ebbf757dcf8851d95d414 1 parent d8e3048
Anderson Arboleya arboleya authored
2  bin/coffeepot → bin/toaster
@@ -4,4 +4,4 @@ var path = require('path');
4 4 var fs = require('fs');
5 5 var lib = path.join(path.dirname(fs.realpathSync(__filename)), '../lib');
6 6
7   -require(lib + '/coffeepot').run()
  7 +require(lib + '/toaster').run()
192 lib/coffeepot.js → lib/toaster.js
@@ -16,7 +16,6 @@
16 16 this.basepath = path.resolve(".");
17 17 argv = process.argv.slice(2);
18 18 if (argv.length && argv[0] === "new") {
19   - this.base;
20 19 new Machine().make(this.basepath, argv);
21 20 } else {
22 21 if (argv.length) {
@@ -48,62 +47,94 @@
48 47 }
49 48 };
50 49 Toaster.prototype.compile = function(module) {
51   - var contents;
52   - contents = this.clean(this.reorder(this.collect(module.src)));
53   - fs.writeFileSync(module.release, contents);
54   - exec("coffee -c " + module.release, __bind(function(error, stdout, stderr) {
55   - console.log("Toasted with love:\r\n\t" + module.release);
56   - if (!module.watcher) {
57   - return module.watcher = new Watcher(this, module);
58   - }
  50 + return this.collect(module, __bind(function(files) {
  51 + var contents;
  52 + contents = this.clean(this.reorder(files, true));
  53 + fs.writeFileSync(module.release, contents);
  54 + return exec("coffee -c " + module.release, __bind(function(error, stdout, stderr) {
  55 + console.log("Toasted with love:\r\n\t" + module.release);
  56 + if (!module.watcher) {
  57 + return module.watcher = new Watcher(this, module);
  58 + }
  59 + }, this));
59 60 }, this));
60   - return true;
61 61 };
62   - Toaster.prototype.collect = function(path, buffer) {
63   - var ext, file, filepath, name, raw, _i, _len, _ref;
64   - if (buffer == null) {
  62 + Toaster.prototype.collect = function(module, fn) {
  63 + return this.findall(module.src, false, __bind(function(files) {
  64 + var buffer, dependencies, file, item, name, raw, requirements, _i, _j, _len, _len2;
65 65 buffer = [];
66   - }
67   - _ref = fs.readdirSync(path);
68   - for (_i = 0, _len = _ref.length; _i < _len; _i++) {
69   - file = _ref[_i];
70   - filepath = pn("" + path + "/" + file);
71   - if (fs.statSync(filepath).isDirectory()) {
72   - this.collect(filepath, buffer);
73   - } else if (filepath.substr(-6 === "coffee")) {
74   - raw = fs.readFileSync(filepath, "utf-8");
75   - name = /(class\s)([\S]+)/g.exec(raw)[2];
  66 + for (_i = 0, _len = files.length; _i < _len; _i++) {
  67 + file = files[_i];
  68 + raw = fs.readFileSync(file, "utf-8");
  69 + dependencies = [];
  70 + if (/(class\s)([\S]+)/g.test(raw)) {
  71 + name = /(class\s)([\S]+)/g.exec(raw)[2];
  72 + }
  73 + if (this.find(buffer, name)) {
  74 + continue;
  75 + }
76 76 if (/(extends\s)([\S]+)/g.test(raw)) {
77   - ext = /(extends\s)([\S]+)/g.exec(raw)[2];
  77 + dependencies.push(/(extends\s)([\S]+)/g.exec(raw)[2]);
78 78 }
79   - if (!this.find(buffer, name)) {
80   - buffer.push({
81   - name: name,
82   - ext: ext,
83   - raw: raw
84   - });
  79 + if (/(#<<\s)(.*)/g.test(raw)) {
  80 + requirements = raw.match(/(#<<\s)(.*)/g);
  81 + for (_j = 0, _len2 = requirements.length; _j < _len2; _j++) {
  82 + item = requirements[_j];
  83 + item = /(#<<\s)(.*)/.exec(item)[2];
  84 + item = item.replace(/\s/g, "");
  85 + item = [].concat(item.split(","));
  86 + dependencies = dependencies.concat(item);
  87 + }
85 88 }
  89 + buffer.push({
  90 + name: name,
  91 + dependencies: dependencies,
  92 + raw: raw
  93 + });
86 94 }
87   - }
88   - return buffer;
  95 + return fn(buffer);
  96 + }, this));
89 97 };
90   - Toaster.prototype.reorder = function(classes) {
91   - var i, initd, klass, result, _len;
  98 + Toaster.prototype.reorder = function(classes, debug) {
  99 + var dependency, i, index, initd, klass, result, _len, _len2, _ref;
  100 + if (debug == null) {
  101 + debug = false;
  102 + }
92 103 initd = {};
93 104 for (i = 0, _len = classes.length; i < _len; i++) {
94 105 klass = classes[i];
95 106 initd["" + klass.name] = 1;
96   - if (klass.ext) {
97   - if (!initd["" + klass.ext]) {
98   - result = this.find(classes, klass.ext);
99   - classes.splice(i, 0, result.item);
100   - classes.splice(result.index + 1, 1);
101   - classes = this.reorder(classes);
  107 + if (klass.dependencies.length) {
  108 + _ref = klass.dependencies;
  109 + for (index = 0, _len2 = _ref.length; index < _len2; index++) {
  110 + dependency = _ref[index];
  111 + if (!initd[dependency]) {
  112 + result = this.find(classes, dependency);
  113 + classes.splice(index, 0, result.item);
  114 + classes.splice(result.index + 1, 1);
  115 + classes = this.reorder(classes);
  116 + }
102 117 }
103 118 }
104 119 }
105 120 return classes;
106 121 };
  122 + Toaster.prototype.findall = function(path, search_folders, fn) {
  123 + var query;
  124 + query = search_folders ? "-type d" : "-name '*.coffee'";
  125 + return exec("find " + path + " " + query, __bind(function(error, stdout, stderr) {
  126 + var buffer, item, items, _i, _len, _ref;
  127 + buffer = [];
  128 + _ref = items = stdout.trim().split("\n");
  129 + for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  130 + item = _ref[_i];
  131 + if (item !== "." && item !== "..") {
  132 + buffer.push(item);
  133 + }
  134 + }
  135 + return fn(buffer);
  136 + }, this));
  137 + };
107 138 Toaster.prototype.find = function(classes, name) {
108 139 var i, j, _len;
109 140 for (i = 0, _len = classes.length; i < _len; i++) {
@@ -130,34 +161,6 @@
130 161 };
131 162 return Toaster;
132 163 })();
133   - Watcher = (function() {
134   - function Watcher(toaster, module) {
135   - this.toaster = toaster;
136   - this.module = module;
137   - console.log("Watching:");
138   - exec("find " + this.module.src + " -name '*.coffee'", __bind(function(error, stdout, stderr) {
139   - var file, filepath, files, _i, _len, _ref;
140   - _ref = files = stdout.trim().split("\n");
141   - for (_i = 0, _len = _ref.length; _i < _len; _i++) {
142   - file = _ref[_i];
143   - filepath = pn(file);
144   - console.log("... \t" + filepath);
145   - fs.watchFile(filepath, {
146   - interval: 250
147   - }, __bind(function(curr, prev) {
148   - var ctime, mtime;
149   - mtime = curr.mtime.valueOf() !== prev.mtime.valueOf();
150   - ctime = curr.ctime.valueOf() !== prev.ctime.valueOf();
151   - if (mtime || ctime) {
152   - return this.toaster.compile(this.module);
153   - }
154   - }, this));
155   - }
156   - return console.log("--------------------------------------------------");
157   - }, this));
158   - }
159   - return Watcher;
160   - })();
161 164 Machine = (function() {
162 165 function Machine() {}
163 166 Machine.prototype.tpl = "modules = \r\n\tname: '%name'\r\n\tsrc: '%src'\r\n\trelease: '%release'";
@@ -206,8 +209,8 @@
206 209 console.log(". First, consider this as your basepath: " + this.basepath);
207 210 console.log(". Now tell me:");
208 211 return this.ask("\tWhat's your app name? (none)", /.+/, __bind(function(name) {
209   - return this.ask("\tWhere's its src folder? (i.e. src)", /.*/, __bind(function(src) {
210   - return this.ask("\tWhere do you want your release file? (i.e. release/app.js)", /.*/, __bind(function(release) {
  212 + return this.ask("\tWhere's its src folder? (i.e. src)", /.+/, __bind(function(src) {
  213 + return this.ask("\tWhere do you want your release file? (i.e. release/app.js)", /.+/, __bind(function(release) {
211 214 var toaster;
212 215 path = pn("" + this.basepath + "/toaster.coffee");
213 216 toaster = this.tpl.replace("%name", name);
@@ -239,4 +242,53 @@
239 242 };
240 243 return Machine;
241 244 })();
  245 + Watcher = (function() {
  246 + function Watcher(toaster, module) {
  247 + this.toaster = toaster;
  248 + this.module = module;
  249 + console.log("Watching:");
  250 + this.toaster.findall(this.module.src, false, __bind(function(files) {
  251 + var file, _i, _len, _results;
  252 + _results = [];
  253 + for (_i = 0, _len = files.length; _i < _len; _i++) {
  254 + file = files[_i];
  255 + _results.push(this.watch_file(file));
  256 + }
  257 + return _results;
  258 + }, this));
  259 + this.toaster.findall(this.module.src, true, __bind(function(folders) {
  260 + var folder, _i, _len, _results;
  261 + _results = [];
  262 + for (_i = 0, _len = folders.length; _i < _len; _i++) {
  263 + folder = folders[_i];
  264 + _results.push(this.watch_folder(folder));
  265 + }
  266 + return _results;
  267 + }, this));
  268 + }
  269 + Watcher.prototype.watch_file = function(path) {
  270 + path = pn(path);
  271 + console.log("...file: \t" + path);
  272 + return fs.watchFile(path, {
  273 + interval: 250
  274 + }, __bind(function(curr, prev) {
  275 + var ctime, mtime;
  276 + mtime = curr.mtime.valueOf() !== prev.mtime.valueOf();
  277 + ctime = curr.ctime.valueOf() !== prev.ctime.valueOf();
  278 + if (mtime || ctime) {
  279 + return this.toaster.compile(this.module);
  280 + }
  281 + }, this));
  282 + };
  283 + Watcher.prototype.watch_folder = function(path) {
  284 + path = pn(path);
  285 + console.log("...folder: \t" + path);
  286 + return fs.watchFile(path, {
  287 + interval: 250
  288 + }, __bind(function(curr, prev) {
  289 + return console.log(curr, prev);
  290 + }, this));
  291 + };
  292 + return Watcher;
  293 + })();
242 294 }).call(this);
7 node_modules/.bin/cake
... ... @@ -0,0 +1,7 @@
  1 +#!/usr/bin/env node
  2 +
  3 +var path = require('path');
  4 +var fs = require('fs');
  5 +var lib = path.join(path.dirname(fs.realpathSync(__filename)), '../lib');
  6 +
  7 +require(lib + '/cake').run();
1  node_modules/.bin/cake
7 node_modules/.bin/coffee
... ... @@ -0,0 +1,7 @@
  1 +#!/usr/bin/env node
  2 +
  3 +var path = require('path');
  4 +var fs = require('fs');
  5 +var lib = path.join(path.dirname(fs.realpathSync(__filename)), '../lib');
  6 +
  7 +require(lib + '/command').run();
1  node_modules/.bin/coffee
19 package.json
... ... @@ -1,20 +1,19 @@
1 1 {
2   - "author": "Anderson Arboleya <me@nybras.com> (TODO: add url)",
3   - "name": "coffee-pot",
4   - "description": "Minimalist build system for coffee-script projects.",
  2 + "author": "Anderson Arboleya <me@nybras.com>",
  3 + "name": "coffee-toaster",
  4 + "description": "Minimalist inheritance-aware build system for coffee-script projects.",
5 5 "version": "0.0.1",
6 6 "homepage": "TODO: add homepage",
7 7 "repository": {
8 8 "type": "git",
9 9 "url": "TODO: add repository"
10 10 },
11   - "main": "main.js",
12   - "directories" : {
13   - "lib" : "./lib/"
  11 + "main": "./lib/toaster",
  12 + "directories": {
  13 + "lib": "./lib/"
14 14 },
15   - "main" : "./lib/coffeepot",
16   - "bin": {
17   - "coffeepot": "./bin/coffeepot"
  15 + "bin": {
  16 + "toaster": "./bin/toaster"
18 17 },
19 18 "scripts": {
20 19 "test": "test.js"
@@ -27,4 +26,4 @@
27 26 },
28 27 "devDependencies": {
29 28 }
30   -}
  29 +}
152 src/coffeepot.coffee → src/toaster.coffee
... ... @@ -1,6 +1,3 @@
1   -# toaster new /path/fo/folder
2   -# toaster
3   -
4 1 fs = require "fs"
5 2 path = require "path"
6 3 pn = path.normalize
@@ -10,16 +7,14 @@ exec = (require "child_process").exec
10 7 exports.run =->
11 8 toaster = new Toaster
12 9
  10 +#<< Machine, Watcher
13 11
14 12 class Toaster
15 13
16   -
17 14 constructor:->
18 15 @basepath = path.resolve(".")
19   -
20 16 argv = process.argv[2..]
21 17 if argv.length && argv[0] == "new"
22   - @base
23 18 new Machine().make @basepath, argv
24 19 else
25 20 @basepath += "/#{argv[0]}" if argv.length
@@ -39,44 +34,64 @@ class Toaster
39 34 new Machine().toast @basepath
40 35
41 36 compile:(module)->
42   - contents = @clean( @reorder( @collect( module.src ) ) )
43   - fs.writeFileSync module.release, contents
44   -
45   - exec "coffee -c #{module.release}", (error, stdout, stderr)=>
46   - console.log "Toasted with love:\r\n\t#{module.release}"
47   - if !module.watcher
48   - module.watcher = new Watcher( this, module )
49   -
50   - true
  37 + @collect module, (files)=>
  38 + contents = @clean( @reorder( files, true ) )
  39 + fs.writeFileSync module.release, contents
  40 + exec "coffee -c #{module.release}", (error, stdout, stderr)=>
  41 + console.log "Toasted with love:\r\n\t#{module.release}"
  42 + module.watcher = new Watcher( this, module ) if !module.watcher
51 43
52   - collect:(path, buffer = [])->
53   - for file in fs.readdirSync path
54   - filepath = pn "#{path}/#{file}"
55   - if fs.statSync( filepath ).isDirectory()
56   - @collect filepath, buffer
57   - else if filepath.substr -6 == "coffee"
58   - raw = fs.readFileSync( filepath, "utf-8" )
59   - name = /(class\s)([\S]+)/g.exec( raw )[ 2 ]
  44 + collect:(module, fn)->
  45 + @findall module.src, false, (files)=>
  46 + buffer = []
  47 + for file in files
  48 + raw = fs.readFileSync file, "utf-8"
  49 + dependencies = []
  50 +
  51 + # class name
  52 + if /(class\s)([\S]+)/g.test raw
  53 + name = /(class\s)([\S]+)/g.exec( raw )[ 2 ]
60 54
  55 + if @find buffer, name
  56 + continue
  57 +
  58 + # class dependencies
61 59 if /(extends\s)([\S]+)/g.test raw
62   - ext = /(extends\s)([\S]+)/g.exec( raw )[ 2 ]
  60 + dependencies.push /(extends\s)([\S]+)/g.exec( raw )[ 2 ]
  61 +
  62 + if /(#<<\s)(.*)/g.test raw
  63 + requirements = raw.match /(#<<\s)(.*)/g
  64 + for item in requirements
  65 + item = /(#<<\s)(.*)/.exec( item )[ 2 ]
  66 + item = item.replace /\s/g, ""
  67 + item = [].concat item.split ","
  68 + dependencies = dependencies.concat item
63 69
64   - if !@find buffer, name
65   - buffer.push {name: name, ext:ext, raw:raw}
66   - buffer
  70 + buffer.push {name:name, dependencies:dependencies, raw:raw}
  71 + fn buffer
67 72
68   - reorder:(classes)->
  73 + reorder:(classes, debug = false)->
69 74 initd = {}
70 75 for klass, i in classes
71 76 initd["#{klass.name}"] = 1
72   - if klass.ext
73   - if !initd["#{klass.ext}"]
74   - result = @find classes, klass.ext
75   - classes.splice( i, 0, result.item )
76   - classes.splice( result.index + 1, 1 )
77   - classes = @reorder( classes )
  77 +
  78 + if klass.dependencies.length
  79 + for dependency, index in klass.dependencies
  80 + if !initd[dependency]
  81 + result = @find classes, dependency
  82 + classes.splice( index, 0, result.item )
  83 + classes.splice( result.index + 1, 1 )
  84 + classes = @reorder( classes )
78 85 classes
79 86
  87 + findall:(path, search_folders, fn)->
  88 + query = if search_folders then "-type d" else "-name '*.coffee'"
  89 + exec "find #{path} #{query}", (error, stdout, stderr)=>
  90 + buffer = []
  91 + for item in items = stdout.trim().split "\n"
  92 + buffer.push item if item != "." && item != ".."
  93 + fn buffer
  94 +
80 95 find:(classes, name)->
81 96 for j, i in classes
82 97 return {item: j, index: i} if j.name == name
@@ -86,63 +101,47 @@ class Toaster
86 101
87 102
88 103
89   -class Watcher
90   -
91   - constructor:(@toaster, @module)->
92   - console.log "Watching:"
93   - exec "find #{@module.src} -name '*.coffee'", (error, stdout, stderr)=>
94   - for file in files = stdout.trim().split("\n")
95   - filepath = pn file
96   - console.log "... \t#{filepath}"
97   - fs.watchFile filepath, {interval : 250}, (curr,prev)=>
98   - mtime = curr.mtime.valueOf() != prev.mtime.valueOf()
99   - ctime = curr.ctime.valueOf() != prev.ctime.valueOf()
100   - @toaster.compile @module if mtime || ctime
101   - console.log "--------------------------------------------------"
102   -
103   -
104   -
105 104 class Machine
106   -
  105 +
107 106 tpl: "modules = \r\n\tname: '%name'\r\n\tsrc: '%src'\r\n\trelease: '%release'"
108   -
  107 +
109 108 make:(@basepath, argv)->
110   -
  109 +
111 110 [action, target] = [argv[0] if argv[0], argv[1] if argv[1]]
112 111 if target == undefined
113 112 console.log "You need to inform a target path!"
114 113 return console.log "toaster new myawesomeapp"
115   -
  114 +
116 115 if target.substr( 0, 1 ) != "/"
117 116 target = path.normalize( "#{@basepath}/#{target}" )
118   -
  117 +
119 118 console.log ". Wonderful! Let's toast this sly little project! :)"
120 119 console.log ". First, consider this as your basepath: #{target}"
121 120 console.log ". Now tell me:"
122 121 @ask "\tWhat's your app name? (none)", /.+/, (name)=>
123 122 @ask "\tWhere's its src folder? (src)", /.*/, (src)=>
124 123 @ask "\tWhere do you want your release file? (release/app.js)", /.*/, (release)=>
125   -
  124 +
126 125 srcdir = src || "src"
127 126 releasefile = release || "release/app.js"
128 127 releasedir = releasefile.split("/").slice( 0, 1).join "/"
129   -
  128 +
130 129 # config file
131 130 toaster = "#{target}/toaster.coffee"
132 131 contents = @tpl.replace "%name", name
133 132 contents = contents.replace "%src", srcdir
134 133 contents = contents.replace "%release", releasefile
135   -
  134 +
136 135 fs.mkdirSync target, 0755
137 136 fs.mkdirSync "#{target}/#{srcdir}", 0755
138 137 fs.mkdirSync "#{target}/#{releasedir}", 0755
139 138 fs.writeFileSync toaster, contents
140   -
  139 +
141 140 process.exit()
142   -
  141 +
143 142 toast:(@basepath)->
144 143 console.log "It seems this project hasn't been toasted yet."
145   -
  144 +
146 145 @ask "Do you wanna toast it? (Y/n)", /.*/, (data)=>
147 146 if data != "" && data.toLowerCase != "y"
148 147 return process.exit()
@@ -152,15 +151,15 @@ class Machine
152 151 console.log ". Now tell me:"
153 152
154 153 @ask "\tWhat's your app name? (none)", /.+/, (name)=>
155   - @ask "\tWhere's its src folder? (i.e. src)", /.*/, (src)=>
156   - @ask "\tWhere do you want your release file? (i.e. release/app.js)", /.*/, (release)=>
  154 + @ask "\tWhere's its src folder? (i.e. src)", /.+/, (src)=>
  155 + @ask "\tWhere do you want your release file? (i.e. release/app.js)", /.+/, (release)=>
157 156 path = pn "#{@basepath}/toaster.coffee"
158 157 toaster = @tpl.replace "%name", name
159 158 toaster = toaster.replace "%src", src
160 159 toaster = toaster.replace "%release", release
161 160 fs.writeFileSync path, toaster
162 161 process.exit()
163   -
  162 +
164 163 ask:(question, format, fn)->
165 164 stdin = process.stdin
166 165 stdout = process.stdout
@@ -174,4 +173,27 @@ class Machine
174 173 fn data
175 174 else
176 175 stdout.write "It should match: #{format}\n"
177   - @ask question, format, fn
  176 + @ask question, format, fn
  177 +
  178 +class Watcher
  179 +
  180 + constructor:(@toaster, @module)->
  181 + console.log "Watching:"
  182 + @toaster.findall @module.src, false, (files)=>
  183 + @watch_file file for file in files
  184 + @toaster.findall @module.src, true, (folders)=>
  185 + @watch_folder folder for folder in folders
  186 +
  187 + watch_file:(path)->
  188 + path = pn path
  189 + console.log "...file: \t#{path}"
  190 + fs.watchFile path, {interval : 250}, (curr,prev)=>
  191 + mtime = curr.mtime.valueOf() != prev.mtime.valueOf()
  192 + ctime = curr.ctime.valueOf() != prev.ctime.valueOf()
  193 + @toaster.compile @module if mtime || ctime
  194 +
  195 + watch_folder:(path)->
  196 + path = pn path
  197 + console.log "...folder: \t#{path}"
  198 + fs.watchFile path, {interval : 250}, (curr,prev)=>
  199 + console.log curr, prev
2  toaster.coffee
... ... @@ -1,4 +1,4 @@
1 1 modules =
2 2 name: 'Coffee Toaster'
3 3 src: 'src'
4   - release: 'lib/coffepot.js'
  4 + release: 'lib/toaster.js'

0 comments on commit 0d460b6

Please sign in to comment.
Something went wrong with that request. Please try again.